commit 690e6e65acebe80384883c7065c7b6fbcc5b65a9 Author: Arlo Breault arlolra@gmail.com Date: Wed Nov 9 09:07:00 2016 -0800
Remove old Yahoo! Messenger support
* Bugzilla 1316000
* https://web.archive.org/web/20160730080614/https://help.yahoo.com/kb/yahoo-m... --- ChangeLog | 1 + .../0001-Set-Tor-Messenger-preferences.patch | 2 +- ...0002-Trac-16489-Prevent-account-autologin.patch | 2 +- ...Support-Special-Characters-input-prompt-o.patch | 2 +- ...Better-error-reporting-for-failed-outgoin.patch | 2 +- .../0005-Trac-13312-OTR-over-Twitter-DMs.patch | 2 +- ...-Fix-tab-strip-background-colour-on-OS-X..patch | 2 +- ...-XMPP-createConversation-should-handle-in.patch | 2 +- ...-Set-_userVCard-own-property-when-downloa.patch | 2 +- .../0009-XMPP-in-band-registration.patch | 2 +- .../instantbird/0010-Remove-search-from-UI.patch | 2 +- .../0011-Add-Tor-Messenger-branding.patch | 2 +- projects/instantbird/0012-Account-picture.patch | 2 +- .../0013-Modify-protocol-defaults.patch | 2 +- .../instantbird/0014-Modify-IRC-defaults.patch | 2 +- projects/instantbird/0015-Modify-themes.patch | 2 +- .../instantbird/0016-Modify-XMPP-defaults.patch | 2 +- projects/instantbird/0017-Remove-logging-UI.patch | 2 +- projects/instantbird/0018-Cert-override.patch | 2 +- .../0019-Display-all-traffic-over-Tor.patch | 2 +- .../instantbird/0020-Trac-17480-Content-sink.patch | 2 +- .../0021-SASL-ECDSA-NIST256P-CHALLENGE.patch | 2 +- ...-msg-is-not-defined-error-in-irc.js-chang.patch | 2 +- ...Contact-list-entries-should-adapt-their-h.patch | 2 +- ...1187281-Only-show-close-button-on-Windows.patch | 2 +- ...-Remove-old-Yahoo-Messenger-support.-r-al.patch | 2398 ++++++++++++++++++++ projects/instantbird/config | 1 + 27 files changed, 2424 insertions(+), 24 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 765e033..67f2523 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ Tor Messenger 0.3.0b1 -- * Trac 20608: Use Instantbird app version * Bugzilla 1246431: Properly handle incoming xmpp server messages * Bugzilla 1313137: Fix irc "msg is not defined" error + * Bugzilla 1316000: Remove old Yahoo! Messenger support * Mac * Trac 20204: Windows don't drag on macOS Sierra * Trac 20206: Avoid prompting to download font "Osaka" on macOS Sierra diff --git a/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch b/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch index 44e2669..a79e25e 100644 --- a/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch +++ b/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch @@ -1,7 +1,7 @@ From 1d67d081f0a1c5c354152c5c54387403a7334946 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:48:41 -0700 -Subject: [PATCH 01/24] Set Tor Messenger preferences +Subject: [PATCH 01/25] Set Tor Messenger preferences
--- im/app/profile/all-instantbird.js | 399 ++++++++++++++++++++++++++++++++++++-- diff --git a/projects/instantbird/0002-Trac-16489-Prevent-account-autologin.patch b/projects/instantbird/0002-Trac-16489-Prevent-account-autologin.patch index 3b908e3..034cc47 100644 --- a/projects/instantbird/0002-Trac-16489-Prevent-account-autologin.patch +++ b/projects/instantbird/0002-Trac-16489-Prevent-account-autologin.patch @@ -1,7 +1,7 @@ From f1e661a5b83c86b1f2d04a434f59c938d3ae1eef Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Mon, 16 Nov 2015 20:37:53 -0800 -Subject: [PATCH 02/24] Trac 16489: Prevent account autologin +Subject: [PATCH 02/25] Trac 16489: Prevent account autologin
--- chat/components/src/imAccounts.js | 2 +- diff --git a/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch b/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch index 454ce61..90fd28b 100644 --- a/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch +++ b/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch @@ -1,7 +1,7 @@ From ffc41b64d3a203ada0549a57044329afb31e88dd Mon Sep 17 00:00:00 2001 From: aleth aleth@instantbird.org Date: Sat, 30 Jan 2016 20:56:38 +0100 -Subject: [PATCH 03/24] Trac 17896: Support "Special Characters" input prompt +Subject: [PATCH 03/25] Trac 17896: Support "Special Characters" input prompt on OS X
* Bug 1151784 - Add Edit menu to the conversation window on OS X. r=nhnt11,florian diff --git a/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch b/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch index d7bcf52..a03c275 100644 --- a/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch +++ b/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch @@ -1,7 +1,7 @@ From 4f8444932609dcf396adf0ee8a44668015d0ab8a Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Tue, 2 Feb 2016 16:04:51 -0800 -Subject: [PATCH 04/24] Trac 17494: Better error reporting for failed outgoing +Subject: [PATCH 04/25] Trac 17494: Better error reporting for failed outgoing messages
* Bug 1245325 - Better error reporting for failed outgoing messages. r=clokep diff --git a/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch b/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch index 5b2b93b..63df479 100644 --- a/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch +++ b/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch @@ -1,7 +1,7 @@ From 5a0596c8ea7d084e1f9f1851c85fcc1999df6422 Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Tue, 15 Mar 2016 17:40:42 -0700 -Subject: [PATCH 05/24] Trac 13312: OTR over Twitter DMs +Subject: [PATCH 05/25] Trac 13312: OTR over Twitter DMs
--- chat/components/src/imConversations.js | 4 +- diff --git a/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch b/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch index 39efb0d..f0fb0c9 100644 --- a/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch +++ b/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch @@ -1,7 +1,7 @@ From 41cedec3b05aefe585f32f4ebde2d6b39e2f01b3 Mon Sep 17 00:00:00 2001 From: Nihanth Subramanya nhnt11@gmail.com Date: Sun, 9 Oct 2016 21:53:04 -0700 -Subject: [PATCH 06/24] Bug 1218193 - Fix tab strip background colour on OS X. +Subject: [PATCH 06/25] Bug 1218193 - Fix tab strip background colour on OS X. r=aleth
--- diff --git a/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch b/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch index ce7bf88..ce1a34e 100644 --- a/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch +++ b/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch @@ -1,7 +1,7 @@ From bbb740af1dc8fd62723494efa3593b6d82bc4ffc Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Sun, 9 Oct 2016 21:57:07 -0700 -Subject: [PATCH 07/24] Bug 1246431 - XMPP createConversation should handle +Subject: [PATCH 07/25] Bug 1246431 - XMPP createConversation should handle incoming messages from the server properly. r=aleth
--- diff --git a/projects/instantbird/0008-Bug-1298574-Set-_userVCard-own-property-when-downloa.patch b/projects/instantbird/0008-Bug-1298574-Set-_userVCard-own-property-when-downloa.patch index 76faa87..2f8c67e 100644 --- a/projects/instantbird/0008-Bug-1298574-Set-_userVCard-own-property-when-downloa.patch +++ b/projects/instantbird/0008-Bug-1298574-Set-_userVCard-own-property-when-downloa.patch @@ -1,7 +1,7 @@ From 1f0fdd5fa6e4ad05edb9ee6424d773c3d1d3f503 Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Sun, 28 Aug 2016 08:57:41 -0700 -Subject: [PATCH 08/24] Bug 1298574 - Set _userVCard own property when +Subject: [PATCH 08/25] Bug 1298574 - Set _userVCard own property when downloading vCard fails. r=aleth
* This prevents an infinite req / res cycle. diff --git a/projects/instantbird/0009-XMPP-in-band-registration.patch b/projects/instantbird/0009-XMPP-in-band-registration.patch index 0e96930..53f99c0 100644 --- a/projects/instantbird/0009-XMPP-in-band-registration.patch +++ b/projects/instantbird/0009-XMPP-in-band-registration.patch @@ -1,7 +1,7 @@ From 30f8a460dc5b471bb303874a25534bc4ec79a78c Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 18:42:25 -0700 -Subject: [PATCH 09/24] XMPP in-band registration +Subject: [PATCH 09/25] XMPP in-band registration
--- chat/locales/en-US/xmpp.properties | 5 + diff --git a/projects/instantbird/0010-Remove-search-from-UI.patch b/projects/instantbird/0010-Remove-search-from-UI.patch index a33bf1c..57c3a1a 100644 --- a/projects/instantbird/0010-Remove-search-from-UI.patch +++ b/projects/instantbird/0010-Remove-search-from-UI.patch @@ -1,7 +1,7 @@ From adee8bb3ecf5d6c2358ac5795653420cd4cd906b Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 18:47:48 -0700 -Subject: [PATCH 10/24] Remove search from UI +Subject: [PATCH 10/25] Remove search from UI
--- im/content/nsContextMenu.js | 18 +----------------- diff --git a/projects/instantbird/0011-Add-Tor-Messenger-branding.patch b/projects/instantbird/0011-Add-Tor-Messenger-branding.patch index 8ca2358..7f8df6e 100644 --- a/projects/instantbird/0011-Add-Tor-Messenger-branding.patch +++ b/projects/instantbird/0011-Add-Tor-Messenger-branding.patch @@ -1,7 +1,7 @@ From e86eb410dfe15ffe4a5128baf41d4aa30f290070 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 18:56:27 -0700 -Subject: [PATCH 11/24] Add Tor Messenger branding +Subject: [PATCH 11/25] Add Tor Messenger branding
--- im/app/macbuild/Contents/Info.plist.in | 2 +- diff --git a/projects/instantbird/0012-Account-picture.patch b/projects/instantbird/0012-Account-picture.patch index 67c7d6e..6e53968 100644 --- a/projects/instantbird/0012-Account-picture.patch +++ b/projects/instantbird/0012-Account-picture.patch @@ -1,7 +1,7 @@ From f7ea3deb695f7cd076735264fa2f9a0f1dcc715f Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:24:09 -0700 -Subject: [PATCH 12/24] Account picture +Subject: [PATCH 12/25] Account picture
--- im/content/blist.xul | 3 +-- diff --git a/projects/instantbird/0013-Modify-protocol-defaults.patch b/projects/instantbird/0013-Modify-protocol-defaults.patch index 1e1b075..f78740a 100644 --- a/projects/instantbird/0013-Modify-protocol-defaults.patch +++ b/projects/instantbird/0013-Modify-protocol-defaults.patch @@ -1,7 +1,7 @@ From 90636b77ec46308386df5acefb43a55ad86548cf Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:25:34 -0700 -Subject: [PATCH 13/24] Modify protocol defaults +Subject: [PATCH 13/25] Modify protocol defaults
* Top protocols
diff --git a/projects/instantbird/0014-Modify-IRC-defaults.patch b/projects/instantbird/0014-Modify-IRC-defaults.patch index ee86b1e..e7d535b 100644 --- a/projects/instantbird/0014-Modify-IRC-defaults.patch +++ b/projects/instantbird/0014-Modify-IRC-defaults.patch @@ -1,7 +1,7 @@ From 9f2fe7b31af96af64ec93dd5b9c3d199705e5114 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:31:58 -0700 -Subject: [PATCH 14/24] Modify IRC defaults +Subject: [PATCH 14/25] Modify IRC defaults
* ctcp ping
diff --git a/projects/instantbird/0015-Modify-themes.patch b/projects/instantbird/0015-Modify-themes.patch index 318cffc..6084fc6 100644 --- a/projects/instantbird/0015-Modify-themes.patch +++ b/projects/instantbird/0015-Modify-themes.patch @@ -1,7 +1,7 @@ From 92aa4ae0d3bde10c502bac0721a2ff5057891840 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:36:38 -0700 -Subject: [PATCH 15/24] Modify themes +Subject: [PATCH 15/25] Modify themes
* theme extension updateh
diff --git a/projects/instantbird/0016-Modify-XMPP-defaults.patch b/projects/instantbird/0016-Modify-XMPP-defaults.patch index afce7ea..1054c51 100644 --- a/projects/instantbird/0016-Modify-XMPP-defaults.patch +++ b/projects/instantbird/0016-Modify-XMPP-defaults.patch @@ -1,7 +1,7 @@ From 50c6ab1b9ddded85679dd91b3e0dd71918511d38 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:38:49 -0700 -Subject: [PATCH 16/24] Modify XMPP defaults +Subject: [PATCH 16/25] Modify XMPP defaults
* xmpp-default-domain
diff --git a/projects/instantbird/0017-Remove-logging-UI.patch b/projects/instantbird/0017-Remove-logging-UI.patch index b820b03..d22341d 100644 --- a/projects/instantbird/0017-Remove-logging-UI.patch +++ b/projects/instantbird/0017-Remove-logging-UI.patch @@ -1,7 +1,7 @@ From ae5671b3b7ebff4470d091cdb50ee1efd94f60d2 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:50:48 -0700 -Subject: [PATCH 17/24] Remove logging UI +Subject: [PATCH 17/25] Remove logging UI
--- im/content/preferences/privacy.xul | 20 -------------------- diff --git a/projects/instantbird/0018-Cert-override.patch b/projects/instantbird/0018-Cert-override.patch index a10f32a..6fd5592 100644 --- a/projects/instantbird/0018-Cert-override.patch +++ b/projects/instantbird/0018-Cert-override.patch @@ -1,7 +1,7 @@ From c9c8d083f1176e60299af2abe9db3bcad3b87e67 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:56:46 -0700 -Subject: [PATCH 18/24] Cert override +Subject: [PATCH 18/25] Cert override
--- im/app/profile/cert_override.txt | 3 +++ diff --git a/projects/instantbird/0019-Display-all-traffic-over-Tor.patch b/projects/instantbird/0019-Display-all-traffic-over-Tor.patch index f481e7a..307045c 100644 --- a/projects/instantbird/0019-Display-all-traffic-over-Tor.patch +++ b/projects/instantbird/0019-Display-all-traffic-over-Tor.patch @@ -1,7 +1,7 @@ From 6fb6121d1bf2942358ead4424e8f368debcc0631 Mon Sep 17 00:00:00 2001 From: Sukhbir Singh sukhbir@torproject.org Date: Mon, 10 Oct 2016 19:58:31 -0700 -Subject: [PATCH 19/24] Display all traffic over Tor +Subject: [PATCH 19/25] Display all traffic over Tor
--- im/content/accountWizard.xul | 2 ++ diff --git a/projects/instantbird/0020-Trac-17480-Content-sink.patch b/projects/instantbird/0020-Trac-17480-Content-sink.patch index 9f4d67b..087e1d5 100644 --- a/projects/instantbird/0020-Trac-17480-Content-sink.patch +++ b/projects/instantbird/0020-Trac-17480-Content-sink.patch @@ -1,7 +1,7 @@ From 837b27c523d1eaba88d14758adb8653caa3f202d Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Wed, 5 Oct 2016 11:09:25 -0700 -Subject: [PATCH 20/24] Trac 17480: Content sink +Subject: [PATCH 20/25] Trac 17480: Content sink
--- chat/modules/imContentSink.jsm | 32 ++++++-------------------------- diff --git a/projects/instantbird/0021-SASL-ECDSA-NIST256P-CHALLENGE.patch b/projects/instantbird/0021-SASL-ECDSA-NIST256P-CHALLENGE.patch index e87f26c..00c47dc 100644 --- a/projects/instantbird/0021-SASL-ECDSA-NIST256P-CHALLENGE.patch +++ b/projects/instantbird/0021-SASL-ECDSA-NIST256P-CHALLENGE.patch @@ -1,7 +1,7 @@ From b7169c4c36ea9e7f582259b8b93516c319539c9f Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Sun, 2 Oct 2016 08:46:55 -0700 -Subject: [PATCH 21/24] SASL ECDSA-NIST256P-CHALLENGE +Subject: [PATCH 21/25] SASL ECDSA-NIST256P-CHALLENGE
--- chat/components/src/imAccounts.js | 1 + diff --git a/projects/instantbird/0022-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch b/projects/instantbird/0022-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch index d562407..e0b2c6a 100644 --- a/projects/instantbird/0022-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch +++ b/projects/instantbird/0022-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch @@ -1,7 +1,7 @@ From df14c41303be11e2b684359f504b80954c7a6de6 Mon Sep 17 00:00:00 2001 From: aleth aleth@instantbird.org Date: Wed, 26 Oct 2016 20:16:58 +0200 -Subject: [PATCH 22/24] Bug 1313137 - "msg is not defined" error in +Subject: [PATCH 22/25] Bug 1313137 - "msg is not defined" error in irc.js:changeBuddyNick. r=clokep
--HG-- diff --git a/projects/instantbird/0023-Bug-954368-Contact-list-entries-should-adapt-their-h.patch b/projects/instantbird/0023-Bug-954368-Contact-list-entries-should-adapt-their-h.patch index b8e2b2a..15cfbae 100644 --- a/projects/instantbird/0023-Bug-954368-Contact-list-entries-should-adapt-their-h.patch +++ b/projects/instantbird/0023-Bug-954368-Contact-list-entries-should-adapt-their-h.patch @@ -1,7 +1,7 @@ From 9ec3b2210152f48feda6d1f7fa12db4455cc7f01 Mon Sep 17 00:00:00 2001 From: aleth aleth@instantbird.org Date: Thu, 12 May 2016 15:10:43 +0200 -Subject: [PATCH 23/24] Bug 954368 - Contact list entries should adapt their +Subject: [PATCH 23/25] Bug 954368 - Contact list entries should adapt their height to the actual font size. r=florian
--HG-- diff --git a/projects/instantbird/0024-Bug-1187281-Only-show-close-button-on-Windows.patch b/projects/instantbird/0024-Bug-1187281-Only-show-close-button-on-Windows.patch index 500615c..3d2efda 100644 --- a/projects/instantbird/0024-Bug-1187281-Only-show-close-button-on-Windows.patch +++ b/projects/instantbird/0024-Bug-1187281-Only-show-close-button-on-Windows.patch @@ -1,7 +1,7 @@ From 52731dd57da7b04b18c6835b77d284e0f70536a5 Mon Sep 17 00:00:00 2001 From: Arlo Breault arlolra@gmail.com Date: Sat, 5 Nov 2016 14:55:20 -0700 -Subject: [PATCH 24/24] Bug 1187281 - Only show "close" button on Windows +Subject: [PATCH 24/25] Bug 1187281 - Only show "close" button on Windows
--- im/content/accounts.xul | 2 ++ diff --git a/projects/instantbird/0025-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch b/projects/instantbird/0025-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch new file mode 100644 index 0000000..97d5e86 --- /dev/null +++ b/projects/instantbird/0025-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch @@ -0,0 +1,2398 @@ +From 4adccc038eea1619377e91bd3f9ce3b4922466c7 Mon Sep 17 00:00:00 2001 +From: Patrick Cloke clokep@gmail.com +Date: Wed, 9 Nov 2016 09:03:49 -0800 +Subject: [PATCH 25/25] Bug 1316000 - Remove old Yahoo! Messenger support. + r=aleth + +--- + chat/chat-prefs.js | 2 + + chat/locales/en-US/facebook.properties | 3 +- + chat/locales/en-US/yahoo.properties | 34 +- + chat/protocols/facebook/facebook.js | 13 +- + chat/protocols/yahoo/moz.build | 6 - + chat/protocols/yahoo/test/test_yahooAccount.js | 98 -- + chat/protocols/yahoo/test/test_yahooLoginHelper.js | 89 -- + chat/protocols/yahoo/test/test_yahoopacket.js | 217 ---- + chat/protocols/yahoo/test/xpcshell.ini | 7 - + chat/protocols/yahoo/yahoo-session.jsm | 1156 -------------------- + chat/protocols/yahoo/yahoo.js | 552 +--------- + im/content/conversation.xml | 3 +- + .../chrome/instantbird/accountWizard.properties | 3 +- + im/test/xpcshell.ini | 1 - + mail/components/im/content/imconversation.xml | 3 +- + 15 files changed, 18 insertions(+), 2169 deletions(-) + delete mode 100644 chat/protocols/yahoo/test/test_yahooAccount.js + delete mode 100644 chat/protocols/yahoo/test/test_yahooLoginHelper.js + delete mode 100644 chat/protocols/yahoo/test/test_yahoopacket.js + delete mode 100644 chat/protocols/yahoo/test/xpcshell.ini + delete mode 100644 chat/protocols/yahoo/yahoo-session.jsm + +diff --git a/chat/chat-prefs.js b/chat/chat-prefs.js +index fb76916..60b9c1e 100644 +--- a/chat/chat-prefs.js ++++ b/chat/chat-prefs.js +@@ -84,6 +84,8 @@ pref("chat.irc.automaticList", true); + pref("chat.prpls.prpl-skype.disable", true); + // Disable Facebook as the XMPP gateway no longer exists. + pref("chat.prpls.prpl-facebook.disable", true); ++// Disable Yahoo Messenger as legacy Yahoo was shut down. ++pref("chat.prpls.prpl-yahoo.disable", true); + + // loglevel is the minimum severity level that a libpurple message + // must have to be reported in the Error Console. +diff --git a/chat/locales/en-US/facebook.properties b/chat/locales/en-US/facebook.properties +index aaf7cdc..2e00cbc 100644 +--- a/chat/locales/en-US/facebook.properties ++++ b/chat/locales/en-US/facebook.properties +@@ -2,6 +2,5 @@ + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +-connection.error.useUsernameNotEmailAddress=Please use your Facebook username, not an email address +- + facebook.chat.name=Facebook Chat ++facebook.disabled=Facebook Chat is no longer supported due to Facebook disabling their XMPP gateway. +diff --git a/chat/locales/en-US/yahoo.properties b/chat/locales/en-US/yahoo.properties +index 727faa6..89ee009 100644 +--- a/chat/locales/en-US/yahoo.properties ++++ b/chat/locales/en-US/yahoo.properties +@@ -2,36 +2,4 @@ + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +-login.error.badCredentials=Username or password is incorrect. +-login.error.accountLockedFailed=Account locked due to too many failed login attempts. +-login.error.accountLockedGeneral=Account locked due to too many login attempts. +-login.error.accountDeactivated=Account has been deactivated. +-login.error.usernameNotExist=The username does not exist. +-# The %S will be an error code returned by the server. +-login.error.unknown=Unknown error: %S +-network.error.http=HTTP connection error. +- +-conference.invite.message=Join my conference. +- +-# Some options are commented out because they aren't used. We do the same thing +-# to their description strings. +-options.pagerPort=Port +-options.transferHost=File transfer server +-options.transferPort=File transfer port +-options.chatEncoding=Encoding +-options.ignoreInvites=Ignore conference invitations +- +-# In this message, %S is replaced with the username of the user who left. +-system.message.conferenceLogoff=%S has left the conference. +-system.message.conferenceLogon=%S has joined the conference. +- +-# LOCALZIATION NOTE (command.*): +-# These are the help messages for each command, the %S is the command name +-# Each command first gives the parameter it accepts and then a description of +-# the command. +-command.help.invite2=%S <user1>[,<user2>,...] [<invite message>]: invite one or more users into this conference chat. +-command.help.conference=%S: Create a new conference room in which you can later invite other users. +- +-# LOCALIZATION NOTE (command.feedback.invite): +-# %S is the user, or comma separated list of users, invited to the conference. +-command.feedback.invite=You have invited %S to the conference. ++yahoo.disabled=Yahoo Messenger is no longer supported due to Yahoo disabling their legacy protocol. +diff --git a/chat/protocols/facebook/facebook.js b/chat/protocols/facebook/facebook.js +index 7b5b3b8..9d90eac 100644 +--- a/chat/protocols/facebook/facebook.js ++++ b/chat/protocols/facebook/facebook.js +@@ -6,33 +6,26 @@ var {interfaces: Ci, utils: Cu} = Components; + + Cu.import("resource:///modules/imXPCOMUtils.jsm"); + Cu.import("resource:///modules/jsProtoHelper.jsm"); +-Cu.import("resource:///modules/xmpp.jsm"); +-Cu.import("resource:///modules/xmpp-session.jsm"); + + XPCOMUtils.defineLazyGetter(this, "_", () => + l10nHelper("chrome://chat/locale/facebook.properties") + ); +-XPCOMUtils.defineLazyGetter(this, "_irc", () => +- l10nHelper("chrome://chat/locale/irc.properties") +-); + + function FacebookAccount(aProtoInstance, aImAccount) { + this._init(aProtoInstance, aImAccount); + } + FacebookAccount.prototype = { +- __proto__: XMPPAccountPrototype, +- get canJoinChat() { return false; }, ++ __proto__: GenericAccountPrototype, + connect: function() { + this.WARN("As Facebook deprecated its XMPP gateway, it is currently not " + + "possible to connect to Facebook Chat. See bug 1141674."); + this.reportDisconnecting(Ci.prplIAccount.ERROR_OTHER_ERROR, +- _irc("error.unavailable", _("facebook.chat.name"))); ++ _("facebook.disabled")); + this.reportDisconnected(); + } + }; + +-function FacebookProtocol() { +-} ++function FacebookProtocol() {} + FacebookProtocol.prototype = { + __proto__: GenericProtocolPrototype, + get normalizedName() { return "facebook"; }, +diff --git a/chat/protocols/yahoo/moz.build b/chat/protocols/yahoo/moz.build +index f144347..ea37853 100644 +--- a/chat/protocols/yahoo/moz.build ++++ b/chat/protocols/yahoo/moz.build +@@ -3,15 +3,9 @@ + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + +-XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini'] +- + EXTRA_COMPONENTS += [ + 'yahoo.js', + 'yahoo.manifest', + ] + +-EXTRA_JS_MODULES += [ +- 'yahoo-session.jsm', +-] +- + JAR_MANIFESTS += ['jar.mn'] +diff --git a/chat/protocols/yahoo/test/test_yahooAccount.js b/chat/protocols/yahoo/test/test_yahooAccount.js +deleted file mode 100644 +index 51df00b..0000000 +--- a/chat/protocols/yahoo/test/test_yahooAccount.js ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/publicdomain/zero/1.0/ */ +- +-Components.utils.import("resource://gre/modules/Services.jsm"); +-var yahoo = {}; +-Services.scriptloader.loadSubScript("resource:///components/yahoo.js", yahoo); +- +-function run_test() +-{ +- add_test(test_cleanUsername); +- add_test(test_fixFontSize); +- run_next_test(); +-} +- +-// Test the stripping of @yahoo.* domains from usernames. +-function test_cleanUsername() +-{ +- // These are just a few of the many possible domains. +- let domains = ["yahoo.com.ar", "yahoo.com.au", "yahoo.com", "yahoo.co.jp", +- "yahoo.it", "yahoo.cn", "yahoo.co.in"]; +- let userId = "user"; +- +- // We must provide a mimimal fake implementation of a protocol object, to keep +- // the YahooAccount constructor happy. +- let fakeProtocol = { +- id: "fake-proto", +- options: { +- local_charset: "UTF-8" +- }, +- _getOptionDefault: function(aOption) { return this.options[aOption]; } +- }; +- let fakeImAccount = {}; +- +- for each(let domain in domains) { +- fakeImAccount.name = userId + "@" + domain; +- let yahooAccount = new yahoo.YahooAccount(fakeProtocol, fakeImAccount); +- do_check_eq(userId, yahooAccount.cleanUsername); +- } +- run_next_test(); +-} +- +-// Test the _fixFontSize() method and ensure that it correctly fixes font sizes +-// in <font> tags while keeping any mention of size= in conversation untouched. +-function test_fixFontSize() +-{ +- // This is an array of two-element arrays. Each inner two-element array +- // contains a message with a badly formed font size as the first element, +- // and a message with a well-formed font size as the second element. We test +- // to ensure that the badly formed message is converted to the well-formed +- // one. +- let testMessages = [ +- // Single font tag. +- ["<font face="Arial" size="12">Test message 1", +- "<font face="Arial" size="3">Test message 1"], +- // Single font tag with size="<digit>" in innner message. +- ["<font face="Arial" size="9">size="30" is a big size.</font>", +- "<font face="Arial" size="2">size="30" is a big size.</font>"], +- // Single font tag with no face attribute. +- ["<font size="12">This message has no font face attribute.", +- "<font size="3">This message has no font face attribute."], +- // Single font tag with no size attribute. +- ["<font face="Arial">This message has no font size attribute.", +- "<font face="Arial">This message has no font size attribute."], +- // Single font tag with rearranged attribute order. +- ["<font size="9" face="Arial">size="30" is a big size.</font>", +- "<font size="2" face="Arial">size="30" is a big size.</font>"], +- // Multiple font tags. +- ["<font face="Arial" size="12">Hello. <font face="Consolas" size="40">World", +- "<font face="Arial" size="3">Hello. <font face="Consolas" size="7">World"] +- ]; +- +- let fakeProtocol = { +- id: "fake-proto", +- options: { +- local_charset: "UTF-8" +- }, +- _getOptionDefault: function(aOption) { return this.options[aOption]; } +- }; +- let fakeImAccount = {name: "test-user"}; +- // We create a fake conversation object so we can obtain the cleaned up +- // message from the conv.writeMessage() call. +- let messagePair; +- let fakeConversation = { +- writeMessage: function(aName, aMessage, aProperties) { +- do_check_eq(aMessage, messagePair[1]); // Compare to the good message. +- }, +- updateTyping: function(aStatus, aName) { } +- }; +- +- let yahooAccount = new yahoo.YahooAccount(fakeProtocol, fakeImAccount); +- yahooAccount._conversations.set("test-user", fakeConversation); +- for each(let pair in testMessages) { +- messagePair = pair; +- // Send in the badly formed message. +- yahooAccount.receiveMessage("test-user", messagePair[0]); +- } +- run_next_test(); +-} +diff --git a/chat/protocols/yahoo/test/test_yahooLoginHelper.js b/chat/protocols/yahoo/test/test_yahooLoginHelper.js +deleted file mode 100644 +index e4d8bc1..0000000 +--- a/chat/protocols/yahoo/test/test_yahooLoginHelper.js ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/publicdomain/zero/1.0/ */ +- +-Components.utils.import("resource:///modules/ArrayBufferUtils.jsm"); +-Components.utils.import("resource://gre/modules/Services.jsm"); +-Components.utils.import("resource:///modules/yahoo-session.jsm"); +-var yahoo = {}; +-Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo); +- +-// Preset test values. +-var kUsername = "testUser"; +-var kPassword = "instantbird"; +-var kPagerIp = "123.456.78.9"; +-var kCrumb = "MG-Z/jNG+Q=="; +-var kChallengeString = "AEF08DBAC33F9EEDABCFEA=="; +-var kYCookie = "OTJmMTQyOTU1ZGQ4MDA3Y2I2ODljMTU5"; +-var kTCookie = "NTdlZmIzY2Q4ODI3ZTc3NTIxYTk1MDhm"; +-var kToken = "MThmMzg3OWM3ODcxMW"; +- +-var kPagerAddressResponse = "COLO_CAPACITY=1\r\nCS_IP_ADDRESS=" + kPagerIp; +-var kTokenResponse = "0\r\n" + kToken + "\r\npartnerid=dummyValue"; +-var kCookieResponse = "0\r\ncrumb=" + kCrumb + "\r\nY=" + kYCookie + +- "\r\nT=" + kTCookie + "\r\ncookievalidfor=86400"; +- +-/* In each test, we override the function that would normally be called next in +- * the login process. We do this so that we can intercept the login process, +- * preventing calls to real Yahoo! servers, and do equality testing. */ +-function run_test() +-{ +- add_test(test_pagerAddress); +- add_test(test_challengeString); +- add_test(test_loginToken); +- add_test(test_cookies); +- run_next_test(); +-} +- +-function test_pagerAddress() +-{ +- let helper = new yahoo.YahooLoginHelper({}, {}); +- +- helper._getChallengeString = function() { +- do_check_eq(kPagerIp, helper._session.pagerAddress); +- run_next_test(); +- }; +- +- helper._onPagerAddressResponse(kPagerAddressResponse, null); +-} +- +-function test_challengeString() +-{ +- let helper = new yahoo.YahooLoginHelper({}, {}); +- +- helper._getLoginToken = function() { +- do_check_eq(kChallengeString, helper._challengeString); +- run_next_test(); +- }; +- +- let response = new yahoo.YahooPacket(yahoo.kPacketType.AuthResponse, 0, 0); +- response.addValue(1, helper._username); +- response.addValue(94, kChallengeString); +- response.addValue(13, 0); +- helper._onChallengeStringResponse(response.toArrayBuffer()); +-} +- +-function test_loginToken() +-{ +- let helper = new yahoo.YahooLoginHelper({}, {}); +- +- helper._getCookies = function() { +- do_check_eq(kToken, helper._loginToken); +- run_next_test(); +- }; +- +- helper._onLoginTokenResponse(kTokenResponse, null); +-} +- +-function test_cookies() +-{ +- let helper = new yahoo.YahooLoginHelper({}, {}); +- +- helper._sendPagerAuthResponse = function() { +- do_check_eq(kCrumb, helper._crumb); +- do_check_eq(kYCookie, helper._session.yCookie); +- do_check_eq(kTCookie, helper._session.tCookie); +- run_next_test(); +- }; +- +- helper._onLoginCookiesResponse(kCookieResponse, null); +-} +diff --git a/chat/protocols/yahoo/test/test_yahoopacket.js b/chat/protocols/yahoo/test/test_yahoopacket.js +deleted file mode 100644 +index 7908c44..0000000 +--- a/chat/protocols/yahoo/test/test_yahoopacket.js ++++ /dev/null +@@ -1,217 +0,0 @@ +-/* Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/publicdomain/zero/1.0/ */ +- +-Components.utils.import("resource:///modules/ArrayBufferUtils.jsm"); +-Components.utils.import("resource://gre/modules/Services.jsm"); +-Components.utils.import("resource:///modules/yahoo-session.jsm"); +-var yahoo = {}; +-Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo); +- +-var kPacketIdBytes = StringToBytes(yahoo.kPacketIdentfier); +-var kHelloKey = 1; +-var kHelloValue = "Hello"; +-var kWorldKey = 20; +-var kWorldValue = "World"; +-var kNumberKey = 4; +-var kNumberValue = 32; +-var kParamsKey = 60; +-var kParam1Value = "param1"; +-var kParam2Value = "param2"; +-var kPacketDataString = "1\xC0\x80Hello\xC0\x8020\xC0\x80World\xC0\x80" + +- "4\xC0\x8032\xC0\x8060\xC0\x80param1\xC0\x80" + +- "60\xC0\x80param2\xC0\x80"; +- +-function run_test() +-{ +- add_test(test_headerCreation); +- add_test(test_fullPacketCreation); +- add_test(test_packetDecoding); +- add_test(test_extractPackets); +- add_test(test_malformedPacketExtraction); +- +- run_next_test(); +-} +- +-function test_headerCreation() +-{ +- let packetLength = 0; +- // Random numbers. +- let serviceNumber = 0x57; +- let status = 0x04; +- let sessionId = 0x57842390; +- +- let packet = new yahoo.YahooPacket(serviceNumber, status, sessionId); +- let buf = packet.toArrayBuffer(); +- let view = new DataView(buf); +- +- // Ensure that the first 4 bytes contain the YMSG identifier. +- for (let i = 0; i < kPacketIdBytes.length; ++i) +- do_check_eq(kPacketIdBytes[i], view.getUint8(i)); +- +- do_check_eq(yahoo.kProtocolVersion, view.getUint16(4)); +- do_check_eq(yahoo.kVendorId, view.getUint16(6)); +- do_check_eq(packetLength, view.getUint16(8)); +- do_check_eq(serviceNumber, view.getUint16(10)); +- do_check_eq(status, view.getUint32(12)); +- do_check_eq(sessionId, view.getUint32(16)); +- +- run_next_test(); +-} +- +-function test_fullPacketCreation() +-{ +- packetLength = kPacketDataString.length; +- // Random numbers. +- let serviceNumber = 0x55; +- let status = 0x02; +- let sessionId = 0x12567800; +- +- let packet = new yahoo.YahooPacket(serviceNumber, status, sessionId); +- packet.addValue(kHelloKey, kHelloValue); +- packet.addValue(kWorldKey, kWorldValue); +- packet.addValue(kNumberKey, kNumberValue); +- packet.addValues(kParamsKey, [kParam1Value, kParam2Value]); +- let buf = packet.toArrayBuffer(); +- let view = new DataView(buf); +- +- // Header check. +- +- // Ensure that the first 4 bytes contain the YMSG identifier. +- for (let i = 0; i < kPacketIdBytes.length; ++i) +- do_check_eq(kPacketIdBytes[i], view.getUint8(i)); +- +- do_check_eq(yahoo.kProtocolVersion, view.getUint16(4)); +- do_check_eq(yahoo.kVendorId, view.getUint16(6)); +- do_check_eq(packetLength, view.getUint16(8)); +- do_check_eq(serviceNumber, view.getUint16(10)); +- do_check_eq(status, view.getUint32(12)); +- do_check_eq(sessionId, view.getUint32(16)); +- +- // Packet data check. +- let dataBytes = StringToBytes(kPacketDataString); +- for (let i = 0; i < dataBytes.length; ++i) +- do_check_eq(dataBytes[i], view.getUint8(yahoo.kPacketHeaderSize + i)); +- run_next_test() +-} +- +-function test_packetDecoding() +-{ +- let packetLength = kPacketDataString.length; +- // Random numbers. +- let serviceNumber = 0x20; +- let status = 0x06; +- let sessionId = 0x13319AB2; +- +- let buf = new ArrayBuffer(yahoo.kPacketHeaderSize + packetLength); +- let view = new DataView(buf); +- +- for (let i = 0; i < kPacketIdBytes.length; ++i) +- view.setUint8(i, kPacketIdBytes[i]); +- +- view.setUint16(4, yahoo.kProtocolVersion); +- view.setUint16(6, yahoo.kVendorId); +- view.setUint16(8, packetLength); +- view.setUint16(10, serviceNumber); +- view.setUint32(12, status); +- view.setUint32(16, sessionId); +- +- let dataBuf = BytesToArrayBuffer(StringToBytes(kPacketDataString)); +- copyBytes(buf, dataBuf, 20); +- +- // Now we decode and test. +- let packet = new yahoo.YahooPacket(); +- packet.fromArrayBuffer(buf); +- +- // Test header information. +- do_check_eq(serviceNumber, packet.service); +- do_check_eq(status, packet.status); +- do_check_eq(sessionId, packet.sessionId); +- +- // Test the getting of single packet data values. +- do_check_eq(kHelloValue, packet.getValue(kHelloKey)); +- do_check_eq(kWorldValue, packet.getValue(kWorldKey)); +- do_check_eq(kNumberValue, packet.getValue(kNumberKey)); +- +- // Test the getting of multiple values with a single key. +- let multiValue = packet.getValues(kParamsKey); +- do_check_eq(2, multiValue.length); +- do_check_eq(kParam1Value, multiValue[0]); +- do_check_eq(kParam2Value, multiValue[1]); +- +- // Test if certain keys are non-existant. +- do_check_true(packet.hasKey(kHelloKey)); +- do_check_false(packet.hasKey(500)); // There is no key 500. +- +- run_next_test(); +-} +- +-function test_extractPackets() +-{ +- // Some constants for each packet. +- const kP1Service = 0x47; +- const kP1Status = 0; +- const kP1SessionId = 0x12345678; +- // Used for testing packet verification. +- const kP1FuzzerKey = 42; +- const kP1FuzzerValue = "I am using the YMSG protocol!"; +- +- const kP2Service = 0x57; +- const kP2Status = 5; +- const kP2SessionId = 0x87654321; +- +- // First, create two packets and obtain their buffers. +- let packet1 = new yahoo.YahooPacket(kP1Service, kP1Status, kP1SessionId); +- packet1.addValue(kHelloKey, kHelloValue); +- packet1.addValue(kP1FuzzerKey, kP1FuzzerValue); +- let packet1Buffer = packet1.toArrayBuffer(); +- +- let packet2 = new yahoo.YahooPacket(kP2Service, kP2Status, kP2SessionId); +- packet2.addValue(kWorldKey, kWorldValue); +- let packet2Buffer = packet2.toArrayBuffer(); +- +- // Create one full buffer with both packets inside. +- let fullBuffer = new ArrayBuffer(packet1Buffer.byteLength + +- packet2Buffer.byteLength); +- copyBytes(fullBuffer, packet1Buffer); +- copyBytes(fullBuffer, packet2Buffer, packet1Buffer.byteLength); +- +- // Now, run the packets through the extractPackets() method. +- let [extractedPackets, bytesHandled] = +- yahoo.YahooPacket.extractPackets(fullBuffer); +- do_check_eq(2, extractedPackets.length); +- +- // Packet 1 checks. +- let p1 = extractedPackets[0]; +- do_check_eq(kP1Service, p1.service); +- do_check_eq(kP1Status, p1.status); +- do_check_eq(kP1SessionId, p1.sessionId); +- do_check_true(p1.hasKey(kHelloKey)); +- do_check_eq(kHelloValue, p1.getValue(kHelloKey)); +- +- // Packet 2 checks. +- let p2 = extractedPackets[1]; +- do_check_eq(kP2Service, p2.service); +- do_check_eq(kP2Status, p2.status); +- do_check_eq(kP2SessionId, p2.sessionId); +- do_check_true(p2.hasKey(kWorldKey)); +- do_check_eq(kWorldValue, p2.getValue(kWorldKey)); +- +- // Check if all the bytes were handled. +- do_check_eq(fullBuffer.byteLength, bytesHandled); +- +- run_next_test(); +-} +- +-function test_malformedPacketExtraction() +-{ +- const kInvalidPacketData = "MSYG1\xC0\x80Hello\xC0\x8020\xC0\x80World\xC0\x80"; +- let buffer = BytesToArrayBuffer(StringToBytes(kInvalidPacketData)); +- let malformed = false; +- try { +- yahoo.YahooPacket.extractPackets(buffer); +- } catch(e) { +- malformed = true; +- } +- do_check_true(malformed); +- run_next_test(); +-} +diff --git a/chat/protocols/yahoo/test/xpcshell.ini b/chat/protocols/yahoo/test/xpcshell.ini +deleted file mode 100644 +index f4b464e..0000000 +--- a/chat/protocols/yahoo/test/xpcshell.ini ++++ /dev/null +@@ -1,7 +0,0 @@ +-[DEFAULT] +-head = +-tail = +- +-[test_yahooAccount.js] +-[test_yahooLoginHelper.js] +-[test_yahoopacket.js] +diff --git a/chat/protocols/yahoo/yahoo-session.jsm b/chat/protocols/yahoo/yahoo-session.jsm +deleted file mode 100644 +index cc96120..0000000 +--- a/chat/protocols/yahoo/yahoo-session.jsm ++++ /dev/null +@@ -1,1156 +0,0 @@ +-/* This Source Code Form is subject to the terms of the Mozilla Public +- * License, v. 2.0. If a copy of the MPL was not distributed with this +- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +- +-this.EXPORTED_SYMBOLS = ["YahooSession"]; +- +-var {classes: Cc, interfaces: Ci, utils: Cu} = Components; +- +-Cu.import("resource://gre/modules/FileUtils.jsm"); +-Cu.import("resource://gre/modules/Http.jsm"); +-Cu.import("resource://gre/modules/NetUtil.jsm"); +-Cu.import("resource:///modules/ArrayBufferUtils.jsm"); +-Cu.import("resource:///modules/imServices.jsm"); +-Cu.import("resource:///modules/imXPCOMUtils.jsm"); +-Cu.import("resource:///modules/socket.jsm"); +- +-XPCOMUtils.defineLazyGetter(this, "_", () => +- l10nHelper("chrome://chat/locale/yahoo.properties") +-); +- +-XPCOMUtils.defineLazyServiceGetter(this, "imgTools", +- "@mozilla.org/image/tools;1", "imgITools"); +- +-var kProtocolVersion = 16; +-var kVendorId = 0; +- +-var kPacketDataDelimiter = "\xC0\x80"; +-var kPacketIdentifier = "YMSG"; +-var kPacketHeaderSize = 20; +-var kProfileIconWidth = 96; +- +-// These constants are used by the icon uploading code since the Yahoo! file +-// transfer server is used for user icon uploads. +-var kFileTransferHost = "filetransfer.msg.yahoo.com"; +-var kFileTransferPort = 80; +- +-var kPacketType = { +- // Sent by a client when logging off of the Yahoo! network. +- Logoff: 0x02, +- // Sent by a client when a message is sent to a buddy. +- Message: 0x06, +- // Sent to the pager server once per hour. +- Ping: 0x12, +- // Used for inviting others to a conference. +- ConfInvite: 0x18, +- // Used as a notification when you or someone else joins a conference room. +- ConfLogon: 0x19, +- // Used as a notification when you or someone else leaves a conference room. +- ConfLogoff: 0x1b, +- // This is sent by the client when additional users are invited to the +- // conference, but it can be sent as the first invite as well. +- ConfAddInvite: 0x1c, +- // Broadcast to all users in a conference room when someone posts a message. +- ConfMessage: 0x1d, +- // Used for typing notifications. +- Notify: 0x4b, +- // These two are used during initial authentication with the pager server. +- AuthResponse: 0x54, +- Auth: 0x57, +- // Buddy list controls. +- AddBuddy: 0x83, +- RemoveBuddy: 0x84, +- // This is sent when you reject a Yahoo! user's buddy request. +- BuddyReqReject: 0x86, +- // Sent to the server once every minute, telling it here are still alive. +- KeepAlive: 0x8A, +- // This is sent when we request a buddy icon. +- Picture: 0xbe, +- // This is sent after a profile picture has been successfully uploaded. +- PictureUpload: 0xc2, +- // This is sent whenever a buddy changes their status. +- StatusUpdate: 0xc6, +- // This is sent when we update our icon. +- AvatarUpdate: 0xc7, +- // This is sent when someone wishes to become your buddy. +- BuddyAuth: 0xd6, +- // Holds the initial status of all buddies when a user first logs in. +- StatusInitial: 0xf0, +- // Contains the buddy list sent from the server. +- List: 0xf1, +- // Sent back to the pager server after each received message. Sending this +- // prevents echoed messages when chatting with the official Yahoo! client. +- MessageAck: 0xfb +-}; +- +-var kPacketStatuses = { +- ServerAck: 0x1, +- Typing: 0x16 +-}; +- +-// Each Yahoo! error code is mapped to a two-element array. The first element +-// contains the last part of the name of its localized string. This is appended +-// to "login.error." to obtain the string. The second element is the +-// Instantbird error that is given to the error handler. +-var kLoginStatusErrors = { +- "1212" : ["badCredentials", +- Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED], +- "1213" : ["accountLockedFailed", +- Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED], +- "1218" : ["accountDeactivated", +- Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED], +- "1235" : ["usernameNotExist", +- Ci.prplIAccount.ERROR_INVALID_USERNAME], +- "1236" : ["accountLockedGeneral", +- Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED] +-}; +- +-// These are the status codes that buddies can send us. +-var kBuddyStatuses = { +- // Available. +- "0" : Ci.imIStatusInfo.STATUS_AVAILABLE, +- // Be right back. +- "1" : Ci.imIStatusInfo.STATUS_AWAY, +- // Busy. +- "2" : Ci.imIStatusInfo.STATUS_UNAVAILABLE, +- // Not at home. +- "3" : Ci.imIStatusInfo.STATUS_AWAY, +- // Not at desk. +- "4" : Ci.imIStatusInfo.STATUS_AWAY, +- // Not in office. +- "5" : Ci.imIStatusInfo.STATUS_AWAY, +- // On phone. +- "6" : Ci.imIStatusInfo.STATUS_AWAY, +- // On vacation. +- "7" : Ci.imIStatusInfo.STATUS_AWAY, +- // Out to lunch. +- "8" : Ci.imIStatusInfo.STATUS_AWAY, +- // Stepped out. +- "9" : Ci.imIStatusInfo.STATUS_AWAY, +- // Invisible. +- "12" : Ci.imIStatusInfo.STATUS_INVISIBLE, +- // Custom status. +- "99" : Ci.imIStatusInfo.STATUS_AWAY, +- // Idle. +- "999" : Ci.imIStatusInfo.STATUS_IDLE +-}; +- +-/* The purpose of the YahooSession object is to serve as a gateway between the +- * protocol plug-in and the Yahoo! Messenger servers. Anytime an object outside +- * of this file wishes to communicate with the servers, it should do it through +- * one of the methods provided by YahooSession. By centralizing such network +- * access, we can easily catch errors, and ensure that communication is handled +- * correctly. */ +-function YahooSession(aAccount) +-{ +- this._account = aAccount; +- this.binaryMode = true; +-} +-YahooSession.prototype = { +- __proto__: Socket, +- _account: null, +- _socket: null, +- _username: null, +- // This is the IPv4 address to the pager server which is the gateway into the +- // Yahoo! Messenger network. +- pagerAddress: null, +- // The session ID is obtained during the login process and is maintained +- // throughout the session. This helps the pager server identify the client. +- sessionId: null, +- // The T and Y cookies obtained by the YahooLoginHelper during login. +- tCookie: null, +- yCookie: null, +- +- // Public methods. +- login: function() { +- this._account.reportConnecting(); +- new YahooLoginHelper(this).login(this._account); +- }, +- +- sendPacket: function(aPacket) { +- this.sendBinaryData(aPacket.toArrayBuffer(), aPacket.toString()); +- }, +- +- addBuddyToServer: function(aBuddy) { +- let packet = new YahooPacket(kPacketType.AddBuddy, 0, this.sessionId); +- // We leave this invite message empty. Any message placed here will +- // annoyingly be sent to the invitee when they accept the invite. +- packet.addValue(14, ""); +- packet.addValue(65, aBuddy.tag.name); +- packet.addValue(97, "1"); // UTF-8 encoding. +- packet.addValue(1, this._account.cleanUsername); +- // The purpose of these two values are unknown. +- packet.addValue(302, "319"); +- packet.addValue(300, "319"); +- packet.addValue(7, aBuddy.userName); +- // The purpose of these three values are also unknown. +- packet.addValue(334, "0"); +- packet.addValue(301, "319"); +- packet.addValue(303, "319"); +- this.sendPacket(packet); +- }, +- +- removeBuddyFromServer: function(aBuddy) { +- let packet = new YahooPacket(kPacketType.RemoveBuddy, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(7, aBuddy.userName); +- packet.addValue(65, aBuddy.tag.name); +- this.sendPacket(packet); +- }, +- +- setStatus: function(aStatus, aMessage) { +- let packet = new YahooPacket(kPacketType.StatusUpdate, 0, this.sessionId); +- +- // When a custom status message is used, key 10 is set to 99, and key 97 +- // is set to 1. Otherwise, key 10 is set to our current status code. +- if (aMessage && aMessage.length > 0) { +- packet.addValue(10, "99"); +- packet.addValue(97, "1"); +- } else { +- let statusCode; +- switch(aStatus) { +- // Available +- case Ci.imIStatusInfo.STATUS_AVAILABLE: +- case Ci.imIStatusInfo.STATUS_MOBILE: +- statusCode = "0"; +- break; +- // Away +- case Ci.imIStatusInfo.STATUS_AWAY: +- statusCode = "1"; +- break; +- // Busy +- case Ci.imIStatusInfo.STATUS_UNAVAILABLE: +- statusCode = "2"; +- break; +- // Invisible +- case Ci.imIStatusInfo.STATUS_INVISIBLE: +- statusCode = "12"; +- break; +- // Idle +- case Ci.imIStatusInfo.STATUS_IDLE: +- statusCode = "999"; +- break; +- } +- packet.addValue(10, statusCode); +- } +- +- // Key 19 is always set as the status messgae, even when the message is +- // empty. If key 10 is set to 99, the message is used. +- packet.addValue(19, aMessage); +- +- // Key 47 is always set to either 0, if we are available, or 1, if we are +- // not available. The value is used by the server if key 10 is set to 99. +- // Otherwise, the value of key 10 is used to determine our status. +- packet.addValue(47, (aStatus == Ci.imIStatusInfo.STATUS_AVAILABLE) ? +- "0" : "1"); +- this.sendPacket(packet); +- }, +- +- sendChatMessage: function(aName, aMessage) { +- let packet = new YahooPacket(kPacketType.Message, 0, this.sessionId); +- // XXX Key 0 is the user ID, and key 1 is the active ID. We need to find +- // the difference between these two. Alias maybe? +- packet.addValue(0, this._account.cleanUsername); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(5, aName); +- packet.addValue(14, aMessage); +- this.sendPacket(packet); +- }, +- +- sendConferenceMessage: function(aRecipients, aRoom, aMessage) { +- let packet = new YahooPacket(kPacketType.ConfMessage, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValues(53, aRecipients); +- packet.addValue(57, aRoom); +- packet.addValue(14, aMessage); +- packet.addValue(97, "1"); // Use UTF-8 encoding. +- this.sendPacket(packet); +- }, +- +- sendTypingStatus: function(aBuddyName, aIsTyping) { +- let packet = new YahooPacket(kPacketType.Notify, kPacketStatuses.Typing, +- this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(5, aBuddyName); +- packet.addValue(13, aIsTyping ? "1" : "0"); +- packet.addValue(14, " "); // Key 14 contains a single space. +- packet.addValue(49, "TYPING"); +- this.sendPacket(packet); +- }, +- +- acceptConferenceInvite: function(aOwner, aRoom, aParticipants) { +- let packet = new YahooPacket(kPacketType.ConfLogon, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(57, aRoom); +- packet.addValues(3, aParticipants); +- this.sendPacket(packet); +- }, +- +- createConference: function(aRoom) { +- let packet = new YahooPacket(kPacketType.ConfLogon, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(3, this._account.cleanUsername); +- packet.addValue(57, aRoom); +- this.sendPacket(packet); +- }, +- +- inviteToConference: function(aInvitees, aRoom, aParticipants, aMessage) { +- let packet = new YahooPacket(kPacketType.ConfAddInvite, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValues(51, aInvitees); +- packet.addValues(53, aParticipants); +- packet.addValue(57, aRoom); +- packet.addValue(58, aMessage); +- packet.addValue(13, "0"); +- this.sendPacket(packet); +- }, +- +- sendConferenceLogoff: function(aName, aParticipants, aRoom) { +- let packet = new YahooPacket(kPacketType.ConfLogoff, 0, this.sessionId); +- packet.addValue(1, aName); +- packet.addValues(3, aParticipants); +- packet.addValue(57, aRoom); +- this.sendPacket(packet); +- }, +- +- setProfileIcon: function(aFileName) { +- // If we have an empty filename, remove the icon from the server. +- if (!aFileName) { +- let packet = new YahooPacket(kPacketType.AvatarUpdate, 0, this.sessionId); +- packet.addValue(3, this._account.cleanUsername); +- packet.addValue(213, 0); +- this.sendPacket(packet); +- return; +- } +- // Try to get a handle to the icon file. +- let file = FileUtils.getFile("ProfD", [aFileName]); +- let type = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService) +- .getTypeFromFile(file); +- NetUtil.asyncFetch({ +- uri: NetUtil.newURI(file), +- contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE, +- securityFlags: Ci.nsILoadInfo.SEC_NORMAL, +- loadUsingSystemPrincipal: true +- }, (aStream, aStatus) => { +- if (!Components.isSuccessCode(aStatus)) { +- throw "Could not access icon file."; +- return; +- } +- let image = imgTools.decodeImage(aStream, type); +- let uploader = new YahooProfileIconUploader(this._account, this, +- aFileName, image); +- uploader.uploadIcon(); +- }); +- }, +- +- requestBuddyIcon: function(aName) { +- let packet = new YahooPacket(kPacketType.Picture, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(5, aName); // The name of the buddy. +- packet.addValue(13, "1"); // "1" means we wish to request an icon. +- this.sendPacket(packet); +- }, +- +- acceptBuddyRequest: function(aRequest) { +- let packet = new YahooPacket(kPacketType.BuddyAuth, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(5, aRequest.userName); +- // Misc. Unknown flags. +- packet.addValue(13, 1); +- packet.addValue(334, 0); +- this.sendPacket(packet); +- +- // If someone wants to add us as a buddy, place them under the default +- // tag. Also, we make sure that the buddy doesn't already exist in the +- // list in case of a server acknowledgement. +- if (!this._account.hasBuddy(aRequest.userName)) +- this._account.addBuddy(Services.tags.defaultTag, aRequest.userName); +- }, +- +- denyBuddyRequest: function(aRequest) { +- let packet = new YahooPacket(kPacketType.BuddyReqReject, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(7, aRequest.userName); +- packet.addValue(14, ""); +- this.sendPacket(packet); +- }, +- +- sendKeepAlive: function() { +- let packet = new YahooPacket(kPacketType.KeepAlive, 0, this.sessionId); +- packet.addValue(0, this._account.cleanUsername); +- this.sendBinaryData(packet.toArrayBuffer()); +- }, +- +- sendPing: function() { +- let packet = new YahooPacket(kPacketType.Ping, 0, this.sessionId); +- this.sendBinaryData(packet.toArrayBuffer()); +- }, +- +- // Callbacks. +- onLoginComplete: function() { +- this._account.reportConnected(); +- this._account.onLoginComplete(); +- }, +- +- onSessionError: function(aError, aMessage) { +- this._account.reportDisconnecting(aError, aMessage); +- if (!this.disconnected) +- this.disconnect(); +- this._account.reportDisconnected(); +- }, +- +- // Private methods. +- +- // Socket Event Callbacks. +- LOG: function(aString) { return this._account.LOG(aString); }, +- +- DEBUG: function(aString) { return this._account.DEBUG(aString); }, +- +- onConnection: function() { +- // We send an authentication request packet as soon as we connect to the +- // pager server. +- let packet = new YahooPacket(kPacketType.Auth, 0, 0); +- packet.addValue(1, this._account.cleanUsername); +- this.sendPacket(packet); +- }, +- +- onConnectionTimedOut: function() { +- this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, ""); +- }, +- +- onConnectionReset: function() { +- this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, ""); +- }, +- +- // Called when the other end has closed the connection. +- onConnectionClosed: function() { +- if (!this._account.connected) +- return; +- this._account.reportDisconnecting(Ci.prplIAccount.NO_ERROR, ""); +- this._account.reportDisconnected(); +- }, +- +- onBinaryDataReceived: function(aData) { +- let packets; +- let bytesHandled; +- try { +- [packets, bytesHandled] = YahooPacket.extractPackets(aData); +- } catch(e) { +- this._account.ERROR(e); +- this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, ""); +- return 0; +- } +- +- for each (let packet in packets) { +- this._account.LOG("Received Packet:\n" + packet.toString()); +- if (YahooPacketHandler.hasOwnProperty(packet.service)) { +- try { +- YahooPacketHandler[packet.service].call(this._account, packet); +- } catch(e) { +- this._account.ERROR(e); +- } +- } else { +- this._account.WARN("No handler for Yahoo! packet " + +- packet.service.toString(16) + "."); +- } +- } +- return bytesHandled; +- } +-}; +- +-/* The purpose of YahooLoginHelper is to separate the complicated login logic +- * from the YahooSession object. Logging in on Yahoo!'s network is the most +- * complicated stage of a session due to the authentication system that is +- * employed. The login steps are listed below. +- * +- * 1) Get the address of a "pager" server. This pager will be our gateway to +- * the network. +- * +- * 2) Obtain the challenge string from the pager. This string is used to help +- * create the base64 response string needed for the final step. +- * +- * 3) Obtain a token from the login server via HTTP. +- * +- * 4) Obtain the login crumb, Y-Cookie, and T-Cookie from the login server via +- * HTTP. These will also be used in the final response packet to the pager. +- * +- * 5) Create the base64 response string from the MD5 hash of the crumb and +- * challenge string, and build a packet containing the username, password, +- * response string, version numbers, crumb, and cookies, sending it to the +- * pager for a final authenticatcation. +- * +- * If all goes well after the 5th step, the user is considered logged in. */ +-function YahooLoginHelper(aSession) +-{ +- this._session = aSession; +-} +-YahooLoginHelper.prototype = { +- // YahooSession object passed in constructor. +- _session: null, +- // YahooAccount object passed to login(). +- _account: null, +- // The username, stripped of any @yahoo.com or @yahoo.co.jp suffix. +- _username: null, +- // The authentication challenge string sent from the Yahoo!'s login server. +- _challengeString: null, +- // The authentication token sent from Yahoo!'s login server. +- _loginToken: null, +- // Crumb sent from Yahoo!'s login server, and used in the final authentication +- // request to the pager server. +- _crumb: null, +- +- // Public methods. +- login: function(aAccount) { +- this._account = aAccount; +- this._getPagerAddress(); +- }, +- +- // Private methods. +- _getPagerAddress: function() { +- let options = { +- onLoad: this._onPagerAddressResponse.bind(this), +- onError: this._onHttpError.bind(this) +- } +- httpRequest(this._account._protocol.pagerRequestUrl, options); +- }, +- +- _getChallengeString: function() { +- let port = this._account.getInt("port"); +- this._session.connect(this._session.pagerAddress, port); +- // We want to handle a challenge string when the server responds. +- this._session.onBinaryDataReceived = +- this._onChallengeStringResponse.bind(this); +- }, +- +- _getLoginToken: function() { +- // TODO - Simplify this using map and join. +- let url = this._account._protocol.loginTokenGetUrl; +- url += "?src=ymsgr&"; +- url += "login=" + percentEncode(this._account.cleanUsername) + "&"; +- url += "passwd=" + percentEncode(this._account.imAccount.password) + "&"; +- url += "chal=" + percentEncode(this._challengeString); +- +- let options = { +- onLoad: this._onLoginTokenResponse.bind(this), +- onError: this._onHttpError.bind(this) +- } +- httpRequest(url, options); +- }, +- +- _getCookies: function() { +- // TODO - Simplify this using map and join. +- let url = this._account._protocol.loginTokenLoginUrl; +- url += "?src=ymsgr&"; +- url += "token=" + this._loginToken; +- +- let options = { +- onLoad: this._onLoginCookiesResponse.bind(this), +- onError: this._onHttpError.bind(this) +- } +- httpRequest(url, options); +- }, +- +- _sendPagerAuthResponse: function() { +- let response = this._calculatePagerResponse(); +- let packet = new YahooPacket(kPacketType.AuthResponse, 0, +- this._session.sessionId); +- // Build the key/value pairs. +- packet.addValue(1, this._account.cleanUsername); +- packet.addValue(0, this._account.cleanUsername); +- packet.addValue(277, this._session.yCookie); +- packet.addValue(278, this._session.tCookie); +- packet.addValue(307, response); +- packet.addValue(244, this._account.protocol.buildId); +- packet.addValue(2, this._account.cleanUsername); +- packet.addValue(2, "1"); +- packet.addValue(98, "us"); +- this._session.sendPacket(packet); +- // We want to handle a final login confirmation packet when the server +- // responds. +- this._session.onBinaryDataReceived = this._onFinalLoginResponse.bind(this); +- }, +- +- _calculatePagerResponse: function() { +- let hasher = Cc["@mozilla.org/security/hash;1"] +- .createInstance(Ci.nsICryptoHash); +- hasher.init(hasher.MD5); +- +- let crypt = this._crumb + this._challengeString; +- let cryptData = StringToBytes(crypt); +- hasher.update(cryptData, cryptData.length); +- +- // The protocol requires replacing + with ., / with _, and = with - within +- // the base64 response string. +- return btoa(hasher.finish(false)).replace(/+/g, ".").replace(///g, "_") +- .replace(/=/g, "-"); +- }, +- +- _handleLoginError: function(aErrorCode) { +- let errorInfo = kLoginStatusErrors[aErrorCode]; +- let errorMessage; +- let error; +- +- // If we find information on the error code we received, we will use that +- // information. If the error wasn't found in our error table, just throw a +- // generic error with the code included. +- if (errorInfo) { +- errorMessage = _("login.error." + errorInfo[0]); +- error = errorInfo[1]; +- } else { +- errorMessage = _("login.error.unknown", aErrorCode); +- error = Ci.prplIAccount.ERROR_OTHER_ERROR; +- // We also throw a console error because we didn't expect +- // this error code. +- this._account.ERROR("Received unknown error from pager server. Code: " + +- aErrorCode); +- } +- this._session.onSessionError(error, errorMessage); +- }, +- +- _onHttpError: function(aError, aStatusText, aXHR) { +- this._session.onSessionError(Ci.prplIAccount.NETWORK_ERROR, +- _("network.error.http")); +- }, +- +- // HTTP Response Callbacks. +- _onPagerAddressResponse: function(aResponse, aXHR) { +- this._session.pagerAddress = +- aResponse.substring(aResponse.lastIndexOf("=") + 1); +- this._getChallengeString(); +- }, +- +- _onLoginTokenResponse: function(aResponse, aXHR) { +- let responseParams = aResponse.split("\r\n"); +- // Status code "0" means success. +- let statusCode = responseParams[0]; +- if (statusCode != "0") { +- this._handleLoginError(statusCode); +- return; +- } +- +- this._loginToken = responseParams[1].replace("ymsgr=", ""); +- this._getCookies(); +- }, +- +- _onLoginCookiesResponse: function(aResponse, aXHR) { +- let responseParams = aResponse.split("\r\n"); +- // Status code "0" means success. +- let statusCode = responseParams[0]; +- if (statusCode != "0") { +- this._handleLoginError(statusCode); +- return; +- } +- +- this._crumb = responseParams[1].replace("crumb=", ""); +- // Remove the "Y=" bit. +- this._session.yCookie = responseParams[2].substring(2); +- // Remove the "T=" bit. +- this._session.tCookie = responseParams[3].substring(2); +- this._sendPagerAuthResponse(); +- }, +- +- // TCP Response Callbacks. +- _onChallengeStringResponse: function(aData) { +- let packet = new YahooPacket(); +- packet.fromArrayBuffer(aData); +- // The value of the challenge string is associated with key 94. +- this._challengeString = packet.getValue(94); +- this._session.sessionId = packet.sessionId; +- this._getLoginToken(); +- }, +- +- _onFinalLoginResponse: function(aData) { +- this._session.onLoginComplete(); +- // We need to restore data handling to the YahooSession object since our +- // login steps are complete. +- this._session.onBinaryDataReceived = +- YahooSession.prototype.onBinaryDataReceived.bind(this._session); +- } +-}; +- +-/* The YahooPacket class represents a single Yahoo! Messenger data packet. +- * Using this class allows you to easily create packets, stuff them with +- * required data, and convert them to/from ArrayBuffer objects. */ +-function YahooPacket(aService, aStatus, aSessionId) +-{ +- this.service = aService; +- this.status = aStatus; +- this.sessionId = aSessionId; +- this.keyValuePairs = []; +-} +-YahooPacket.prototype = { +- service: null, +- status: null, +- sessionId: null, +- keyValuePairs: null, +- +- // Public methods. +- +- // Add a single key/value pair. +- addValue: function(aKey, aValue) { +- let pair = { +- key: aKey.toString(), // The server handles keys as ASCII number values. +- value: aValue +- }; +- +- this.keyValuePairs.push(pair); +- }, +- +- // Add multiple key/value pairs with the same key but different values +- // stored in an array. +- addValues: function(aKey, aValues) { +- for each (let value in aValues) +- this.addValue(aKey, value); +- }, +- +- // This method returns the first value found with the given key. +- getValue: function(aKey) { +- for (let i = 0; i < this.keyValuePairs.length; ++i) { +- let pair = this.keyValuePairs[i]; +- // The server handles keys as ASCII number values. +- if (pair.key == aKey.toString()) +- return pair.value; +- } +- +- // Throw an error if the key wasn't found. +- throw "Required key " + aKey + " wasn't found. Packet Service: " + +- this.service.toString(16); +- }, +- +- // This method returns all of the values found with the given key. In some +- // packets, one key is associated with multiple values. If that is the case, +- // use this method to retrieve all of them instead of just the first one. +- getValues: function(aKey) { +- let values = []; +- for (let i = 0; i < this.keyValuePairs.length; ++i) { +- let pair = this.keyValuePairs[i]; +- // The server handles keys as ASCII number values. +- if (pair.key == aKey.toString()) +- values.push(pair.value); +- } +- +- // Throw an error if no keys were found. +- if (values.length == 0) { +- throw "Required key " + aKey + " wasn't found. Packet Service: " + +- this.service.toString(16); +- } +- return values; +- }, +- +- hasKey: function(aKey) { +- for (let i = 0; i < this.keyValuePairs.length; ++i) { +- // The server handles keys as ASCII number values. +- if (this.keyValuePairs[i].key == aKey.toString()) +- return true; +- } +- return false; +- }, +- +- toArrayBuffer: function() { +- let dataString = ""; +- for (let i = 0; i < this.keyValuePairs.length; ++i) { +- let pair = this.keyValuePairs[i]; +- dataString += pair.key + kPacketDataDelimiter; +- dataString += pair.value + kPacketDataDelimiter; +- } +- +- let packetLength = dataString.length; +- let buffer = new ArrayBuffer(kPacketHeaderSize + packetLength); +- +- // Build header. +- let view = new DataView(buffer); +- let idBytes = StringToBytes(kPacketIdentifier); +- view.setUint8(0, idBytes[0]); +- view.setUint8(1, idBytes[1]); +- view.setUint8(2, idBytes[2]); +- view.setUint8(3, idBytes[3]); +- view.setUint16(4, kProtocolVersion); +- view.setUint16(6, 0); // Vendor ID +- view.setUint16(8, packetLength); +- view.setUint16(10, this.service); +- view.setUint32(12, this.status); +- view.setUint32(16, this.sessionId); +- +- // Copy in data. +- copyBytes(buffer, BytesToArrayBuffer(StringToBytes(dataString)), kPacketHeaderSize); +- +- return buffer; +- }, +- +- fromArrayBuffer: function(aBuffer) { +- let view = new DataView(aBuffer); +- this.length = view.getUint16(8) + kPacketHeaderSize; +- this.service = view.getUint16(10); +- this.status = view.getUint32(12); +- this.sessionId = view.getUint32(16); +- +- let dataString = ArrayBufferToString(aBuffer).substring(kPacketHeaderSize); +- let delimitedData = dataString.split(kPacketDataDelimiter); +- // Since the data should also end with a trailing delmiter, split() will +- // add an empty element at the end. We need to pop this element off. +- delimitedData.pop(); +- +- // If we don't have an even number of delimitedData elements, that means +- // we are either missing a key or a value. +- if (delimitedData.length % 2 != 0) { +- throw "Odd number of data elements. Either a key or value is missing. " +- "Num of elements: " + delimitedData.length; +- } +- +- for (let i = 0; i < delimitedData.length; i += 2) { +- let key = delimitedData[i]; +- let value = delimitedData[i + 1]; +- if (key && value) { +- let pair = { +- key: key, +- value: value +- }; +- this.keyValuePairs.push(pair); +- } +- } +- }, +- +- toString: function() { +- // First, add packet header information. +- let s = "Service: 0x" + this.service.toString(16) + "\n"; +- s += "Status: 0x" + this.status.toString(16) + "\n"; +- s += "Session ID: 0x" + this.sessionId.toString(16); +- // Now we add the packet data, if there is some. +- if (this.keyValuePairs.length) { +- // Add two preceding newlines for space to make reading easier. +- s += "\n\nPacket Key-Value Data:\n"; +- for each (let pair in this.keyValuePairs) +- s += pair.key + ":\t" + pair.value + "\n"; +- } +- return s; +- } +-}; +-YahooPacket.extractPackets = function(aData, aOnNetworkError) { +- let packets = []; +- let bytesHandled = 0; +- +- while (aData.byteLength >= kPacketHeaderSize) { +- if (ArrayBufferToString(aData.slice(0, kPacketIdentifier.length)) != +- kPacketIdentifier) { +- throw "Malformed packet received. Packet content: " + +- ArrayBufferToHexString(aData); +- } +- +- let packetView = new DataView(aData); +- let packetLength = packetView.getUint16(8) + kPacketHeaderSize; +- // Don't process half packets. +- if (packetLength > aData.byteLength) +- break; +- let packet = new YahooPacket(); +- packet.fromArrayBuffer(aData.slice(0, packetLength)); +- packets.push(packet); +- bytesHandled += packetLength; +- aData = aData.slice(packetLength); +- } +- return [packets, bytesHandled]; +-} +- +-/* In YahooPacketHandler, each handler function is assosiated with a packet +- * service number. You can use the kPacketType enumeration to understand +- * what kind of packet each number is linked to. +- * +- * Keep in mind too that "this" in each function will be bound to a +- * YahooAccount object, since they are all invoked using call(). */ +-var YahooPacketHandler = { +- // Buddy logoff. +- 0x02: function(aPacket) { +- let name = aPacket.getValue(7); +- this.setBuddyStatus(name, Ci.imIStatusInfo.STATUS_OFFLINE, ""); +- }, +- +- // Incoming chat message. +- 0x06: function(aPacket) { +- let from = aPacket.getValue(4); +- let to = aPacket.getValue(5); +- let message = aPacket.getValue(14); +- this.receiveMessage(from, message); +- +- // The official Yahoo! Messenger desktop client requires message ACKs to be +- // sent back to the server. The web client doesn't require this. A good +- // indication of when an ACK is required is when key 429 is sent, which +- // contains the ID of the message. When a message is sent from the official +- // desktop client, and no ACK is sent back, the message is resent seconds +- // later. +- if (aPacket.hasKey(429)) { +- let messageId = aPacket.getValue(429); +- let packet = new YahooPacket(kPacketType.MessageAck, 0, aPacket.sessionId); +- // Some keys have an unknown purpose, so we set a constant value. +- packet.addValue(1, to); +- packet.addValue(5, from); +- packet.addValue(302, "430"); +- packet.addValue(430, messageId); +- packet.addValue(303, 430); +- packet.addValue(450, 0); +- this._session.sendPacket(packet); +- } +- }, +- +- // New mail notification. +- // TODO: Implement this handler when mail notifications are handled in the +- // base code. +- 0x0b: function(aPacket) {}, +- +- // Server ping. +- // TODO: Add support for ping replies. +- 0x12: function(aPacket) {}, +- +- // Conference invitation. +- 0x18: function(aPacket) { +- let owner = aPacket.getValue(50); +- let roomName = aPacket.getValue(57); +- let participants = aPacket.getValues(53); +- // The owner is also a participant. +- participants.push(owner); +- let message = aPacket.getValue(58); +- this.receiveConferenceInvite(owner, roomName, participants, message); +- }, +- +- // Conference logon. +- 0x19: function(aPacket) { +- let userName = aPacket.getValue(53); +- let room = aPacket.getValue(57); +- this.receiveConferenceLogon(room, userName); +- }, +- +- // Conference logoff +- 0x1b: function(aPacket) { +- let userName = aPacket.getValue(56); +- let roomName = aPacket.getValue(57); +- this.receiveConferenceLogoff(roomName, userName); +- }, +- +- // Conference additional invitation. NOTE: Since this packet has the same +- // structure as the normal conference invite (packet 0x18), we simply +- // reuse that handler. +- 0x1c: function(aPacket) { return YahooPacketHandler[0x18].call(this, aPacket); }, +- +- // Conference message. +- 0x1d: function(aPacket) { +- let from = aPacket.getValue(3); +- let room = aPacket.getValue(57); +- let message = aPacket.getValue(14); +- this.receiveConferenceMessage(from, room, message); +- }, +- +- // Typing notification. +- 0x4b: function(aPacket) { +- let name = aPacket.getValue(4); +- let isTyping = (aPacket.getValue(13) == "1"); +- this.receiveTypingNotification(name, isTyping); +- }, +- +- // Legacy Yahoo! buddy list. Packet 0xf1 has replaced this. +- 0x55: function(aPacket) {}, +- +- // Authentication acknowledgement. We can ignore this since we are known +- // to be authenticated if we are receiving other packets anyway. +- 0x57: function(aPacket) {}, +- +- // AddBuddy ack packets can be ignored. They do not depend on whether or not +- // the buddy accepted the invite. +- 0x83: function(aPacket) {}, +- +- // RemoveBuddy ack packets let us know when we should actually remove the +- // buddy from the list, keeping us in sync with the server. +- 0x84: function(aPacket) { +- let buddy = this.getBuddy(aPacket.getValue(7)); +- // The buddy is off the server, so remove it locally. +- this.removeBuddy(buddy, false); +- }, +- +- // Picture upload. +- 0xc2: function(aPacket) { +- let onlineBuddies = this.getOnlineBuddies(); +- // Send a notification to each online buddy that your icon has changed. +- // Those offline will automatically pick up the change when they log in. +- for each (let buddy in onlineBuddies) { +- let packet = new YahooPacket(kPacketType.AvatarUpdate, 0, +- this._session.sessionId); +- packet.addValue(3, buddy.userName); +- packet.addValue(213, 2); // A value of 2 means we are using an icon. +- this._session.sendPacket(packet); +- } +- }, +- +- // Buddy icon checksum. +- // TODO - Make use of the icon checksum to allow icon caching. +- 0xbd: function(aPacket) { +- // Extract the checksum from the URL parameter chksum. +- let buddyName = aPacket.getValue(4); +- let url = aPacket.getValue(20); +- let parameter = "chksum="; +- // The "chksum" parameter is the only parameter in the URL. +- let checksum = url.substring(url.indexOf(parameter) + parameter.length); +- +- let buddy = this.getBuddy(buddyName); +- // We only download the new icon if no older checksum exists, or if the +- // older checksum differs, indicating an updated icon. +- if (buddy && buddy.iconChecksum !== checksum) { +- buddy.buddyIconFilename = url; +- buddy.iconChecksum = checksum; +- } +- }, +- +- // Buddy icon request reply. This can be handled in the same way as a buddy +- // icon checksum packet, so we simply reuse the handler. +- 0xbe: function (aPacket) { return YahooPacketHandler[0xbd].call(this, aPacket); }, +- +- // Buddy status update. +- 0xc6: function (aPacket) { +- let name = aPacket.getValue(7); +- // If the user is mobile, use the mobile status. +- let status = aPacket.hasKey(60) ? Ci.imIStatusInfo.STATUS_MOBILE : +- kBuddyStatuses[aPacket.getValue(10)]; +- +- let message = aPacket.hasKey(19) ? aPacket.getValue(19) : ""; +- this.setBuddyStatus(name, status, message); +- }, +- +- // Buddy avatar (icon) update. +- 0xc7: function(aPacket) { +- // Strangely, in some non-official clients, when someone updates their +- // profile icon we are sent two avatar update packets: one with a default +- // status containing little information, and another with a Server Ack +- // status containing the info we need. So we only accept packets with a +- // Server Ack status to prevent errors. +- if (aPacket.status != kPacketStatuses.ServerAck) +- return; +- // Key 4 contains the name of the buddy who updated their icon. +- this._session.requestBuddyIcon(aPacket.getValue(4)); +- }, +- +- // Buddy authorization request. +- 0xd6: function(aPacket) { +- // Whenever we authorize someone to be our buddy, the server will send an +- // acknowledgement packet. We ignore the ack to prevent the auth request +- // from showing again. +- if (aPacket.status == kPacketStatuses.ServerAck) +- return; +- +- let session = this._session; +- let userName = aPacket.getValue(4); +- this.addBuddyRequest(userName, session.acceptBuddyRequest.bind(session), +- session.denyBuddyRequest.bind(session)); +- }, +- +- // XXX: What does this packet do? +- 0xef: function(aPacket) {}, +- +- // Initial user status. +- 0xf0: function (aPacket) { +- // Return early if we find no buddy names. +- if (!aPacket.hasKey(7)) +- return; +- +- // The key/value pairs are in order as sent by the server. So we must +- // iterate though them to find out information about each buddy. Each +- // buddy section starts with key 7. +- let currentBuddy; +- for (let i = 0; i < aPacket.keyValuePairs.length; ++i) { +- let {key: key, value: value} = aPacket.keyValuePairs[i]; +- +- if (key == 7) { // Buddy name. +- currentBuddyName = value; +- this._session.requestBuddyIcon(currentBuddyName); +- } else if (key == 10) // Buddy status. +- this.setBuddyStatus(currentBuddyName, kBuddyStatuses[value]); +- else if (key == 19) // Buddy status message. +- this.setBuddyStatus(currentBuddyName, undefined, value); +- else if (key == 60) // Mobile status. +- this.setBuddyStatus(currentBuddyName, Ci.imIStatus.STATUS_MOBILE); +- } +- }, +- +- // Friends and groups list. +- 0xf1: function(aPacket) { +- let tagName = ""; +- for each (let pair in aPacket.keyValuePairs) { +- if (pair.key == "65") +- tagName = pair.value; +- else if (pair.key == "7") { +- let buddyName = pair.value; +- this.addBuddyFromServer(Services.tags.createTag(tagName), buddyName); +- } +- } +- } +-}; +- +-/* The YahooProfileIconUploader class is specifically designed to set a profile +- * image on a Yahoo! Messenger account. The reason this functionality is split +- * into a separate class is because of the complexity of the operation. Because +- * of special protocol requirements, it is easier to use raw TCP communication +- * instead of the httpRequest() method. */ +-function YahooProfileIconUploader(aAccount, aSession, aFileName, aImage) +-{ +- this._account = aAccount; +- this._session = aSession; +- this._fileName = aFileName; +- this._image = aImage; +-} +-YahooProfileIconUploader.prototype = { +- __proto__: Socket, +- _account: null, +- _session: null, +- _fileName: null, +- _image: null, +- _host: null, +- _port: null, +- +- uploadIcon: function() { +- // Connect to the file transfer server, and the onConnection callback +- // will do the rest. +- this.connect(kFileTransferHost, kFileTransferPort); +- }, +- +- // Socket callbacks. +- onConnection: function() { +- // Scale the image down, and make it a PNG. Icon widths are constant, but +- // their height varies depending on the aspect ratio of the original image. +- let aspectRatio = this._image.width / this._image.height; +- let scaledHeight = kProfileIconWidth / aspectRatio; +- let scaledImage = imgTools.encodeScaledImage(this._image, "image/png", +- kProfileIconWidth, +- scaledHeight); +- let imageData = NetUtil.readInputStreamToString(scaledImage, +- scaledImage.available()); +- +- // Build the Yahoo packet. +- let packet = new YahooPacket(kPacketType.Picture, 0, this.sessionId); +- packet.addValue(1, this._account.cleanUsername); +- // TODO - Look into how expiration time works for profile icons, and its +- // purpose. We aren't sure if this refers to seconds, days, years, etc. +- packet.addValue(38, "604800"); // Expiration time. +- packet.addValue(0, this._account.cleanUsername); +- packet.addValue(28, imageData.length); // Picture size in bytes. +- packet.addValue(27, this._fileName); // Picture filename. +- packet.addValue(14, ""); // Null string. +- let packetBuffer = packet.toArrayBuffer(); +- +- // Build the request header. +- let headers = [ +- ["User-Agent", "Mozilla/5.0"], +- ["Cookie", "T=" + this._session.tCookie + "; Y=" + this._session.yCookie], +- ["Host", kFileTransferHost + ":" + kFileTransferPort], +- ["Content-Length", packetBuffer.byteLength + 4 + imageData.length], +- ["Cache-Control", "no-cache"], +- ]; +- let headerString = "POST /notifyft HTTP/1.1\r\n"; +- headers.forEach(function(header) { +- headerString += header[0] + ": " + header[1] + "\r\n"; +- }); +- +- // The POST request uses a special delimeter between the end of the included +- // Yahoo binary packet, and the image data. +- let requestPacketEnd = "29" + kPacketDataDelimiter; +- // Build the complete POST request data. +- let requestData = headerString + "\r\n" + +- ArrayBufferToString(packetBuffer) + requestPacketEnd + +- imageData; +- this.sendData(requestData); +- } +-}; +diff --git a/chat/protocols/yahoo/yahoo.js b/chat/protocols/yahoo/yahoo.js +index 8beadb5..86a2589 100644 +--- a/chat/protocols/yahoo/yahoo.js ++++ b/chat/protocols/yahoo/yahoo.js +@@ -2,575 +2,39 @@ + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +-var {classes: Cc, interfaces: Ci, utils: Cu} = Components; ++var {interfaces: Ci, utils: Cu} = Components; + +-Cu.import("resource:///modules/imServices.jsm"); + Cu.import("resource:///modules/imXPCOMUtils.jsm"); + Cu.import("resource:///modules/jsProtoHelper.jsm"); +-Cu.import("resource:///modules/yahoo-session.jsm"); + + XPCOMUtils.defineLazyGetter(this, "_", () => + l10nHelper("chrome://chat/locale/yahoo.properties") + ); + +-// These timeouts are in milliseconds. +-var kKeepAliveTimeout = 60 * 1000; // One minute. +-var kPingTimeout = 3600 * 1000; // One hour. +- +-function YahooConversation(aAccount, aName) +-{ +- this._buddyUserName = aName; +- this._account = aAccount; +- this.buddy = aAccount.getBuddy(aName); +- this._init(aAccount); +-} +-YahooConversation.prototype = { +- __proto__: GenericConvIMPrototype, +- _account: null, +- _buddyUserName: null, +- _typingTimer: null, +- +- close: function() { +- this._account.deleteConversation(this._buddyUserName); +- GenericConvChatPrototype.close.call(this); +- }, +- +- sendMsg: function (aMsg) { +- // Deliver the message, then write it to the window. +- this._account._session.sendChatMessage(this._buddyUserName, +- this._account.encodeMessage(aMsg)); +- this.finishedComposing(); +- this.writeMessage(this._account.cleanUsername, aMsg, +- {outgoing: true, _alias: this._account.imAccount.alias}); +- }, +- +- sendTyping: function(aString) { +- if (aString.length) { +- if (!this._typingTimer) +- this._account._session.sendTypingStatus(this._buddyUserName, true); +- this._refreshTypingTimer(); +- } +- return Ci.prplIConversation.NO_TYPING_LIMIT; +- }, +- +- finishedComposing: function() { +- this._account._session.sendTypingStatus(this._buddyUserName, false); +- this._cancelTypingTimer(); +- }, +- +- _refreshTypingTimer: function() { +- this._cancelTypingTimer(); +- this._typingTimer = setTimeout(this.finishedComposing.bind(this), 10000); +- }, +- +- _cancelTypingTimer: function() { +- if (!this._typingTimer) +- return; +- clearTimeout(this._typingTimer); +- delete this._typingTimer +- this._typingTimer = null; +- }, +- +- get name() { return this._buddyUserName; } +-}; +- +-function YahooConference(aAccount, aRoom, aOwner) +-{ +- this._account = aAccount; +- this._roomName = aRoom; +- this._owner = aOwner; +- this._init(aAccount, aRoom, aAccount.cleanUsername); +-} +-YahooConference.prototype = { +- __proto__: GenericConvChatPrototype, +- _account: null, +- _roomName: null, +- _owner: null, +- +- close: function() { +- this.reportLogoff(); +- this._account.deleteConference(this._roomName); +- GenericConvChatPrototype.close.call(this); +- }, +- +- reportLogoff: function() { +- if (this.left) +- return; +- this._account._session.sendConferenceLogoff(this._account.cleanUsername, +- this.getParticipantNames(), +- this._roomName); +- this.left = true; +- }, +- +- sendMsg: function(aMsg) { +- this._account._session.sendConferenceMessage(this.getParticipantNames(), +- this._roomName, +- this._account.encodeMessage(aMsg)); +- }, +- +- addParticipant: function(aName) { +- // In case we receive multiple conference logon packets, prevent adding +- // duplicate buddies. +- if (this._participants.get(aName)) +- return; +- let buddy = new YahooConferenceBuddy(aName, this); +- this._participants.set(aName, buddy); +- this.notifyObservers(new nsSimpleEnumerator([buddy]), "chat-buddy-add"); +- this.writeMessage(this._roomName, +- _("system.message.conferenceLogon", aName), +- {system: true}); +- }, +- +- getParticipantNames: function() { return [for (p of this._participants.values()) p.name]; } +-}; +- +-function YahooConferenceBuddy(aName, aConference) +-{ +- this._name = aName; +- this._conference = aConference; +-} +-YahooConferenceBuddy.prototype = { +- __proto__: GenericConvChatBuddyPrototype, +- _conference: null, +- +- get founder() { return this._conference._owner == this._name; } +-}; +- +-function YahooAccountBuddy(aAccount, aBuddy, aTag, aUserName) +-{ +- this._init(aAccount, aBuddy, aTag, aUserName); +-} +-YahooAccountBuddy.prototype = { +- __proto__: GenericAccountBuddyPrototype, +- iconChecksum: null, +- +- // This removes the buddy locally, and from the Yahoo! servers. +- remove: function() { return this._account.removeBuddy(this, true); }, +- // This removes the buddy locally, but keeps him on the servers. +- removeLocal: function() { return this._account.removeBuddy(this, false); }, +- createConversation: function() { return this._account.createConversation(this.userName); } +-} +- + function YahooAccount(aProtoInstance, aImAccount) + { + this._init(aProtoInstance, aImAccount); +- this._buddies = new Map(); +- this._conversations = new Map(); +- this._conferences = new Map(); +- this._protocol = aProtoInstance; +- this._converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] +- .createInstance(Ci.nsIScriptableUnicodeConverter); +- this._converter.charset = this.getString("local_charset") || "UTF-8"; +- +- // The username stripped of any @yahoo.* domain. +- this.cleanUsername = this.name.replace(/@yahoo..+$/, ""); + } + YahooAccount.prototype = { + __proto__: GenericAccountPrototype, +- // YahooSession object passed in constructor. +- _session: null, +- // A Map holding the list of buddies associated with their usernames. +- _buddies: null, +- // A Map holding the list of open buddy conversations associated with the +- // username of the buddy. +- _conversations: null, +- // A Map holding the list of open conference rooms associated with the room +- // name. +- _conferences: null, +- // YahooProtocol object passed in the constructor. +- _protocol: null, +- // An nsIScriptableUnicodeConverter used to convert incoming/outgoing chat +- // messages to the correct charset. +- _converter: null, +- // This is simply incremented by one everytime a new conference room is +- // created. It is appened to the end of the room name when a new room is +- // created, ensuring name uniqueness. +- _roomsCreated: 0, +- // The username stripped of any @yahoo.* domain. +- cleanUsername: null, +- // The timers used to send keepalive and ping packets to the server to ensrue +- // the server that the user is still connected. +- _keepAliveTimer: null, +- _pingTimer: null, + + connect: function() { +- this._session = new YahooSession(this); +- this._session.login(this.imAccount.name, this.imAccount.password); +- }, +- +- disconnect: function(aSilent) { +- // Log out of all of the conferences the user is in. +- for (let conf of this._conferences) +- conf[1].reportLogoff(); +- +- if (this.connected) { +- this.reportDisconnecting(Ci.prplIAccount.NO_ERROR, ""); +- if (this._session.isConnected) +- this._session.disconnect(); +- this.reportDisconnected(); +- } +- // buddy[1] is the actual object. +- for (let buddy of this._buddies) +- buddy[1].setStatus(Ci.imIStatusInfo.STATUS_UNKNOWN, ""); +- +- // Clear and delete the timers to avoid memory leaks. +- if (this._keepAliveTimer) { +- this._keepAliveTimer.cancel(); +- delete this._keepAliveTimer; +- } +- +- if (this._pingTimer) { +- this._pingTimer.cancel(); +- delete this._pingTimer; +- } +- }, +- +- observe: function(aSubject, aTopic, aData) { +- if (aTopic == "status-changed") +- this._session.setStatus(aSubject.statusType, aData); +- else if (aTopic == "user-icon-changed") +- this._session.setProfileIcon(aData); +- }, +- +- remove: function() { +- for each(let conv in this._conversations) +- conv.close(); +- delete this._conversations; +- for (let buddy of this._buddies) +- buddy[1].removeLocal(); // buddy[1] is the actual object. +- }, +- +- unInit: function() { +- this.disconnect(true); +- delete this.imAccount; +- }, +- +- createConversation: function(aName) { +- let conv = new YahooConversation(this, aName); +- this._conversations.set(aName, conv); +- return conv; +- }, +- +- deleteConversation: function(aName) { +- if (this._conversations.has(aName)) +- this._conversations.delete(aName); +- }, +- +- receiveConferenceInvite: function(aOwner, aRoom, aParticipants, aMessage) { +- // Do nothing if we wish to ignore invites. +- if (!Services.prefs.getIntPref("messenger.conversations.autoAcceptChatInvitations") || +- this.getBool("ignore_invites")) +- return; +- +- let conf = new YahooConference(this, aRoom, aOwner); +- this._conferences.set(aRoom, conf); +- +- for each (let participant in aParticipants) +- conf.addParticipant(participant); +- +- // Add ourselves to the conference room as well. +- conf.addParticipant(this.imAccount.name); +- +- this._session.acceptConferenceInvite(aOwner, aRoom, +- conf.getParticipantNames()); +- }, +- +- receiveConferenceLogon: function(aRoom, aUsername) { +- if (!this._conferences.has(aRoom)) +- return; +- let conf = this._conferences.get(aRoom); +- conf.addParticipant(aUsername); +- }, +- +- receiveConferenceLogoff: function(aRoom, aUsername) { +- if (!this._conferences.has(aRoom)) +- return; +- let conf = this._conferences.get(aRoom); +- conf.removeParticipant(aUsername); +- conf.writeMessage(this._roomName, +- _("system.message.conferenceLogoff", aName), +- {system: true}); +- }, +- +- deleteConference: function(aName) { +- if (this._conferences.has(aName)) +- this._conferences.delete(aName); +- }, +- +- // Called when the user adds or authorizes a new contact. +- addBuddy: function(aTag, aName) { +- let buddy = new YahooAccountBuddy(this, null, aTag, aName); +- this._buddies.set(buddy.userName, buddy); +- this._session.addBuddyToServer(buddy); +- Services.contacts.accountBuddyAdded(buddy); +- }, +- +- hasBuddy: function(aName) { +- return this._buddies.has(aName); +- }, +- +- // Called for each buddy that is sent in a list packet from Yahoo! on login. +- addBuddyFromServer: function(aTag, aName) { +- let buddy; +- if (this._buddies.has(aName)) +- buddy = this._buddies.get(aName); +- else { +- buddy = new YahooAccountBuddy(this, null, aTag, aName); +- Services.contacts.accountBuddyAdded(buddy); +- this._buddies.set(aName, buddy); +- } +- +- // Set all new buddies as offline because a following status packet will +- // tell their status if they are online. +- buddy.setStatus(Ci.imIStatusInfo.STATUS_OFFLINE, ""); +- +- // Request the buddy's picture. +- this._session.requestBuddyIcon(aName); +- }, +- +- // Called when a user removes a contact from within Instantbird. +- removeBuddy: function(aBuddy, aRemoveFromServer) { +- if (aRemoveFromServer) { +- // We will remove the buddy locally when we get a server ack packet. +- this._session.removeBuddyFromServer(aBuddy); +- return; +- } +- +- this._buddies.delete(aBuddy.userName); +- Services.contacts.accountBuddyRemoved(aBuddy); +- }, +- +- loadBuddy: function(aBuddy, aTag) { +- let buddy = new YahooAccountBuddy(this, aBuddy, aTag); +- this._buddies.set(buddy.userName, buddy); +- +- return buddy; +- }, +- +- // Both the status and message can be defined, or only one can be defined. +- // When defining just the message, set aStatus to undefined. +- setBuddyStatus: function(aName, aStatus, aMessage) { +- if (!this._buddies.has(aName)) +- return; +- let buddy = this._buddies.get(aName); +- // If the message is set as undefined, use the existing message. +- if (aMessage === undefined) +- aMessage = buddy.statusText; +- // If the status is undefined, use the existing status. +- if (aStatus === undefined) +- aStatus = buddy.statusType; +- buddy.setStatus(aStatus, aMessage); +- }, +- +- getBuddy: function(aName) { +- if (this._buddies.has(aName)) +- return this._buddies.get(aName); +- return null; +- }, +- +- getOnlineBuddies: function() { +- let onlineBuddies = []; +- for (let buddy of this._buddies) { +- if (buddy[1].statusType != Ci.imIStatusInfo.STATUS_OFFLINE) +- onlineBuddies.push(buddy[1]); +- } +- return onlineBuddies; +- }, +- +- receiveMessage: function(aName, aMessage) { +- let conv; +- // Check if we have an existing converstaion open with this user. If not, +- // create one and add it to the list. +- if (!this._conversations.has(aName)) +- conv = this.createConversation(aName); +- else +- conv = this._conversations.get(aName); +- +- // Certain Yahoo clients, such as the official web client, sends formatted +- // messages, but the size value is the actual pt size, not the 1 - 7 size +- // expected from the HTML <font> tag. We replace it with the correct size. +- let message = this.decodeMessage(aMessage) +- .replace(/(<font[^>]+)size="(\d+)"/g, this._fixFontSize); +- +- conv.writeMessage(aName, message, {incoming: true}); +- conv.updateTyping(Ci.prplIConvIM.NOT_TYPING, conv.name); +- }, +- +- receiveConferenceMessage: function(aName, aRoom, aMessage) { +- if (!this._conferences.has(aRoom)) +- return; +- +- this._conferences.get(aRoom).writeMessage(aName, +- this.decodeMessage(aMessage), +- {incoming: true}); +- }, +- +- receiveTypingNotification: function(aName, aIsTyping) { +- if (!this._conversations.has(aName)) +- return; +- +- let conv = this._conversations.get(aName); +- if (aIsTyping) +- conv.updateTyping(Ci.prplIConvIM.TYPING, conv.name); +- else +- conv.updateTyping(Ci.prplIConvIM.NOT_TYPING, conv.name); +- }, +- +- encodeMessage: function(aMessage) { +- // Try to perform a convertion from JavaScript UTF-16 into the charset +- // specified in the options. If the conversion fails, just leave +- // the message as it is. +- let encodedMsg; +- try { +- encodedMsg = this._converter.ConvertFromUnicode(aMessage); +- } catch (e) { +- encodedMsg = aMessage; +- this.WARN("Could not encode UTF-16 message into " + +- this._converter.charset + ". Message: " + aMessage); +- } +- return encodedMsg; +- }, +- +- decodeMessage: function(aMessage) { +- // Try to perform a convertion from the charset specified in the options +- // to JavaScript UTF-16. If the conversion fails, just leave the message +- // as it is. +- let decodedMsg; +- try { +- decodedMsg = this._converter.ConvertToUnicode(aMessage); +- } catch (e) { +- decodedMsg = aMessage; +- this.WARN("Could not decode " + this._converter.charset + +- " message into UTF-16. Message: " + aMessage); +- } +- return decodedMsg; +- }, +- +- get canJoinChat() { return true; }, +- chatRoomFields: {}, +- joinChat: function(aComponents) { +- // Use _roomsCreated to append a unique number to the room name. +- let roomName = this.cleanUsername + "-" + ++this._roomsCreated; +- let conf = new YahooConference(this, roomName, this.cleanUsername); +- this._conferences.set(roomName, conf); +- this._session.createConference(roomName); +- }, +- +- // Callbacks. +- onLoginComplete: function() { +- // Now that we are connected, get ready to start to sending pings and +- // keepalive packets. +- this._keepAliveTimer = Cc["@mozilla.org/timer;1"] +- .createInstance(Ci.nsITimer); +- this._pingTimer = Cc["@mozilla.org/timer;1"] +- .createInstance(Ci.nsITimer); +- +- // We use slack timers since we don't need millisecond precision when +- // sending the keepalive and ping packets. +- let s = this._session; +- this._keepAliveTimer +- .initWithCallback(s.sendKeepAlive.bind(s), kKeepAliveTimeout, +- this._keepAliveTimer.TYPE_REPEATING_SLACK); +- +- this._pingTimer +- .initWithCallback(s.sendPing.bind(s), kPingTimeout, +- this._pingTimer.TYPE_REPEATING_SLACK); +- +- }, +- +- // Private methods. +- +- // This method is used to fix font sizes given by formatted messages. This +- // method is designed to be used as a method for a string replace() call. +- _fixFontSize: function(aMatch, aTagAttributes, aFontSize, aOffset, aString) { +- // Approximate the font size. +- let newSize; +- if (aFontSize <= 8) +- newSize = "1"; +- else if (aFontSize <= 10) +- newSize = "2"; +- else if (aFontSize <= 12) +- newSize = "3"; +- else if (aFontSize <= 14) +- newSize = "4"; +- else if (aFontSize <= 20) +- newSize = "5"; +- else if (aFontSize <= 30) +- newSize = "6"; +- else if (aFontSize <= 40) +- newSize = "7"; +- else // If we get some gigantic size, just default to the standard 3 size. +- newSize = "3"; +- +- let sizeAttribute = "size="" + newSize + """; +- // We keep any preceding attributes, but replace the size attribute. +- return aTagAttributes + sizeAttribute; ++ this.WARN("The legacy versions of Yahoo Messenger was disabled on August " + ++ "5, 2016. It is currently not possible to connect to Yahoo " + ++ "Messenger. See bug 1316000"); ++ this.reportDisconnecting(Ci.prplIAccount.ERROR_OTHER_ERROR, ++ _("yahoo.disabled")); ++ this.reportDisconnected(); + } + }; + +-function YahooProtocol() { +- this.registerCommands(); +-} ++function YahooProtocol() {} + YahooProtocol.prototype = { + __proto__: GenericProtocolPrototype, +- // Protocol specific connection parameters. +- pagerRequestUrl: "http://scsa.msg.yahoo.com/capacity", +- loginTokenGetUrl: "https://login.yahoo.com/config/pwtoken_get", +- loginTokenLoginUrl: "https://login.yahoo.com/config/pwtoken_login", +- buildId: "4194239", + + get id() { return "prpl-yahoo"; }, + get name() { return "Yahoo"; }, + get iconBaseURI() { return "chrome://prpl-yahoo/skin/"; }, +- options: { +- port: {get label() { return _("options.pagerPort"); }, default: 5050}, +- local_charset: {get label() { return _("options.chatEncoding"); }, default: "UTF-8"}, +- ignore_invites: {get label() { return _("options.ignoreInvites"); }, default: false} +- }, +- commands: [ +- { +- name: "invite", +- get helpString() { return _("command.help.invite2", "invite"); }, +- usageContext: Ci.imICommand.CMD_CONTEXT_ALL, +- run: function(aMsg, aConv) { +- if (aMsg.trim().length == 0) +- return false; +- +- let splitPosition = aMsg.indexOf(" "); // Split at first space. +- let invitees; +- let message; +- +- // If we have an invite message. +- if (splitPosition > 0) { +- invitees = aMsg.substring(0, splitPosition).split(","); +- message = aMsg.substring(splitPosition); +- } else { +- invitees = aMsg.split(","); +- message = _("conference.invite.message"); // Use default message. +- } +- +- let conf = aConv.wrappedJSObject; +- conf._account._session.inviteToConference(invitees, conf._roomName, +- conf.getParticipantNames(), +- message); +- conf.writeMessage(conf._roomName, +- _("command.feedback.invite", invitees.join(", ")), +- {system: true, noLog: true}); +- conf._account.LOG("Sending conference invite to " + invitees); +- return true; +- }, +- }, +- +- { +- name: "conference", +- get helpString() { return _("command.help.conference", "conference"); }, +- usageContext: Ci.imICommand.CMD_CONTEXT_CHAT, +- run: function(aMsg, aConv) { +- aConv.account.joinChat(null); +- return true; +- } +- } +- ], + getAccount: function(aImAccount) { return new YahooAccount(this, aImAccount); }, + classID: Components.ID("{50ea817e-5d79-4657-91ae-aa0a52bdb98c}") + }; +diff --git a/im/content/conversation.xml b/im/content/conversation.xml +index 6f00c8d..c93dab0 100644 +--- a/im/content/conversation.xml ++++ b/im/content/conversation.xml +@@ -342,8 +342,7 @@ + msg = "<font face="" + style.fontFamily + "">" + msg + "</font>"; + // MSN doesn't support font size info in messages... + } +- else if (proto == "prpl-aim" || proto == "prpl-icq" || +- proto == "prpl-yahoo" || proto == "prpl-yahoojp") { ++ else if (proto == "prpl-aim" || proto == "prpl-icq") { + let styleAttributes = "" + if ("color" in style) + styleAttributes += " color="" + style.color + """; +diff --git a/im/locales/en-US/chrome/instantbird/accountWizard.properties b/im/locales/en-US/chrome/instantbird/accountWizard.properties +index 7d371bd..1d6fd48 100644 +--- a/im/locales/en-US/chrome/instantbird/accountWizard.properties ++++ b/im/locales/en-US/chrome/instantbird/accountWizard.properties +@@ -14,9 +14,8 @@ topProtocol.list=prpl-irc,prpl-jabber,prpl-twitter,prpl-gtalk + # These are the descriptions of the top protocols specified above. + # A description should be provided for each protocol ID listed above. + topProtocol.prpl-irc.description=Connect to your favourite IRC network +-topProtocol.prpl-jabber.description=Chat with friends using XMPP + topProtocol.prpl-gtalk.description=Talk to your Gmail contacts + topProtocol.prpl-twitter.description=Stay up to date with your Twitter timeline + topProtocol.prpl-aim.description=Chat with your buddies on AOL Instant Messenger +-topProtocol.prpl-yahoo.description=Chat with friends using Yahoo! Messenger + topProtocol.prpl-irc.description=Join IRC channels ++topProtocol.prpl-jabber.description=Chat using the open Jabber/XMPP protocol +diff --git a/im/test/xpcshell.ini b/im/test/xpcshell.ini +index 5f7dd70..578122a 100644 +--- a/im/test/xpcshell.ini ++++ b/im/test/xpcshell.ini +@@ -6,5 +6,4 @@ + [include:chat/components/src/test/xpcshell.ini] + [include:chat/protocols/irc/test/xpcshell.ini] + [include:chat/protocols/skype/test/xpcshell.ini] +-[include:chat/protocols/yahoo/test/xpcshell.ini] + #[include:extensions/purple/purplexpcom/src/test/xpcshell.ini] +diff --git a/mail/components/im/content/imconversation.xml b/mail/components/im/content/imconversation.xml +index 16c665a..a4b9fc6 100644 +--- a/mail/components/im/content/imconversation.xml ++++ b/mail/components/im/content/imconversation.xml +@@ -285,8 +285,7 @@ + msg = "<font face="" + style.fontFamily + "">" + msg + "</font>"; + // MSN doesn't support font size info in messages... + } +- else if (proto == "prpl-aim" || proto == "prpl-icq" || +- proto == "prpl-yahoo" || proto == "prpl-yahoojp") { ++ else if (proto == "prpl-aim" || proto == "prpl-icq") { + let styleAttributes = "" + if ("color" in style) + styleAttributes += " color="" + style.color + """; +-- +2.10.2 + diff --git a/projects/instantbird/config b/projects/instantbird/config index eedc112..c4f64cd 100644 --- a/projects/instantbird/config +++ b/projects/instantbird/config @@ -86,6 +86,7 @@ input_files: - filename: 0022-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch - filename: 0023-Bug-954368-Contact-list-entries-should-adapt-their-h.patch - filename: 0024-Bug-1187281-Only-show-close-button-on-Windows.patch + - filename: 0025-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch - filename: mozconfig-common - filename: 'mozconfig-[% c("var/osname") %]' name: mozconfig