Your message dated Thu, 30 Apr 2015 22:00:24 +0000
with message-id <[email protected]>
and subject line Bug#773005: fixed in yowsup 2.2.78-1
has caused the Debian Bug report #773005,
regarding yowsup: unusable after new WhatsApp version
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
773005: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=773005
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Source: yowsup
Version: 0.0~git20140314.938cf1-1
Severity: grave
Tags: upstream patch jessie
Justification: renders package unusable

I am the maintainer of this package.

Recently (November 2014), the WhatsApp changed its protocol to implement the
famous "double blue check", photo transfer when contacting a person and other
features. To support it, the authentication method was changed and this new
method is mandatory now. So, the old versions of the WhatsApp and the current
version of the youwsup in testing (revision -1) don't work anymore. In other
words, the version in testing is RC, because no longer register a new user
number nor authenticate a registered number.

The upstream provided new versions and a "legacy" version[1]. So, based in
legacy version and with support from the upstream, I added patches to fix each
file (as needed) in current yowsup package in Debian.

[1] https://github.com/tgalal/yowsup/tree/legacy

The list of patches:
         - add-missing-variable
         - add-PictureClient
         - add-the-tokenmap
         - add-whatsapp-auth-v2
         - update-bintreenode
         - update-connection-manager
         - update-protocoltreenode
         - update-the-interface-messages
         - update-user-agent
         - yowsup-cli (updated only; already in Debian)

Regards,

Eriberto

-- System Information:
Debian Release: 8.0
  APT prefers testing-updates
  APT policy: (500, 'testing-updates'), (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=pt_BR.UTF-8, LC_CTYPE=pt_BR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Description: add the new and necessary file src/Examples/PictureClient.py.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Examples/PictureClient.py
===================================================================
--- /dev/null
+++ yowsup-0.0~git20140314.938cf1/src/Examples/PictureClient.py
@@ -0,0 +1,80 @@
+'''
+Copyright (c) <2012> Tarek Galal <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this 
+software and associated documentation files (the "Software"), to deal in the Software 
+without restriction, including without limitation the rights to use, copy, modify, 
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
+permit persons to whom the Software is furnished to do so, subject to the following 
+conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
+A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+'''
+
+import os
+parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+os.sys.path.insert(0,parentdir)
+import time
+
+from Yowsup.connectionmanager import YowsupConnectionManager
+
+class WhatsappPictureClient:
+	
+	def __init__(self, target, waitForReceipt=True):
+		
+		self.jid = target
+		jid = self.jid
+		print(jid)
+
+		
+		connectionManager = YowsupConnectionManager()
+		self.signalsInterface = connectionManager.getSignalsInterface()
+		self.methodsInterface = connectionManager.getMethodsInterface()
+		
+		self.signalsInterface.registerListener("auth_success", self.onAuthSuccess)
+		self.signalsInterface.registerListener("auth_fail", self.onAuthFailed)
+		self.signalsInterface.registerListener("contact_gotProfilePicture", self.onProfilePicture)
+		self.signalsInterface.registerListener("disconnected", self.onDisconnected)
+
+
+	
+	def login(self, username, password):
+		self.username = username
+		self.methodsInterface.call("auth_login", (username, password))
+
+
+	def onAuthSuccess(self, username):
+		print("Authed %s" % username)
+
+
+
+		self.methodsInterface.call("ready")
+		
+
+		self.getPictureByID(self.jid) 
+		print("getting picture..please press strg+c in case you got the picture")
+		
+		while True:
+			input()
+
+	def onAuthFailed(self, username, err):
+		print("Auth Failed!")
+
+	def onDisconnected(self, reason):
+		print("Disconnected because %s" %reason)
+
+	def onProfilePicture(self, jid, path, rest):
+		print('jid: ' + str(jid) + ' path: ' + str(path) + ' rest: ' + str(rest))
+		
+	def getPictureByID(self, jid):
+		print('jid:'+jid)
+		self.methodsInterface.call("contact_getProfilePicture", ( [jid+'@s.whatsapp.net'] ))
+
Description: change the authentication method to version 2.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/Auth/auth.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/Auth/auth.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/Auth/auth.py
@@ -19,7 +19,7 @@ CONTRACT, TORT OR OTHERWISE, ARISING FRO
 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 '''
 
-from .mechanisms.wauth import WAuth as AuthMechanism
+from .mechanisms.wauth2 import WAuth2 as AuthMechanism
 
 from Yowsup.Common.constants import Constants
 from Yowsup.Common.debugger import Debugger
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/Auth/mechanisms/wauth2.py
===================================================================
--- /dev/null
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/Auth/mechanisms/wauth2.py
@@ -0,0 +1,363 @@
+'''
+Copyright (c) <2012> Tarek Galal <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
+A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+'''
+import sys
+sys.path.append("/home/tarek/Projects/Yowsupgit/yowsup/src")
+import socket, hashlib, hmac, sys
+from Yowsup.Common.debugger import Debugger
+from Yowsup.Common.watime import WATime
+from Yowsup.ConnectionIO.protocoltreenode import ProtocolTreeNode
+
+from struct import pack
+from operator import xor
+from itertools import starmap
+from hashlib import sha1
+import uuid
+
+def _bytearray(data):
+
+  if type(data) == str:
+		  return data
+  elif type(data) == list:
+		  tmp = [chr(x) if type(x) == int else x for x in data]
+		  return "".join(tmp)
+  elif type(data) == int:
+		  tmp = ""
+    #for i in range(0,data):
+    #	tmp = tmp + chr(0)
+    #	return tmp
+		  return [0] * data
+
+  return ""
+
+class WAuth2():
+
+  def __init__(self,conn):
+    Debugger.attach(self);
+
+    self.conn = conn
+    self._d("Yowsup WAUTH-2 INIT");
+
+  def setAuthObject(self, authObject):
+    self.authObject = authObject
+
+  def login(self, username, password, domain, resource):
+
+    self.username = username
+
+    try:
+      self._d("Starting stream")
+      self.conn.writer.streamStart(domain,resource);
+
+      self._d("Sending Features")
+      self.sendFeatures();
+
+      self._d("Sending Auth");
+      self.sendAuth();
+
+      self._d("Read stream start");
+      self.conn.reader.streamStart();
+
+      self._d("Read features and challenge");
+      challengeData = self.readFeaturesAndChallenge();
+
+      self._d("Sending Response")
+      self.sendResponse(challengeData);
+
+      self._d("Read success")
+
+      if not self.readSuccess(): return 0
+
+      self.conn.jid = "%s@%s" % (username, domain)
+      return self.conn
+
+    except socket.error:
+      return self.connectionError.emit()
+
+
+  def sendFeatures(self):
+    toWrite = ProtocolTreeNode("stream:features",None)
+
+
+    self.conn.writer.write(toWrite);
+
+  def sendAuth(self):
+    # "user":self.connection.user,
+    blob = []
+    node = ProtocolTreeNode("auth", {"passive": "false", "mechanism": "WAUTH-2", "user": self.username})
+    #node = ProtocolTreeNode("auth",{"user":self.username,"xmlns":"urn:ietf:params:xml:ns:xmpp-sasl","mechanism":"WAUTH-1"}, None, ''.join(map(chr, blob)));
+    self.conn.writer.write(node);
+
+  def readFeaturesAndChallenge(self):
+    root = self.conn.reader.nextTree();
+
+    while root is not None:
+      if ProtocolTreeNode.tagEquals(root,"stream:features"):
+        self._d("GOT FEATURES !!!!");
+        self.authObject.supportsReceiptAcks  = root.getChild("receipt_acks") is not None;
+        root = self.conn.reader.nextTree();
+
+        continue;
+
+      if ProtocolTreeNode.tagEquals(root,"challenge"):
+        self._d("GOT CHALLENGE !!!!");
+        #data = base64.b64decode(root.data);
+        return root.data;
+    raise Exception("fell out of loop in readFeaturesAndChallenge");
+
+
+  def sendResponse(self,challengeData):
+
+    authBlob = self.getAuthBlob(challengeData);
+    node = ProtocolTreeNode("response",{"xmlns":"urn:ietf:params:xml:ns:xmpp-sasl"}, None, authBlob);
+    self.conn.writer.write(node);
+    self.conn.reader.inn.buf = [];
+
+  def getAuthBlob(self, nonce):
+    #numArray = _bytearray(KeyStream.keyFromPasswordAndNonce(self.authObject.password, nonce))
+    keys = KeyStream.generateKeys(self.authObject.password, nonce)
+
+    self.conn.reader.inputKey = self.inputKey = KeyStream(keys[2], keys[3])
+    self.outputKey = KeyStream(keys[0], keys[1])
+
+    nums = [0] * 4
+
+    nums.extend(self.username)
+    nums.extend(nonce)
+
+    wt = WATime()
+    utcNow = int(wt.utcTimestamp())
+    nums.extend(str(utcNow))
+
+    encoded = self.outputKey.encodeMessage(nums, 0, 4, len(nums) - 4)
+    encoded = "".join(map(chr, encoded))
+
+    return encoded
+
+  def readSuccess(self):
+    node = self.conn.reader.nextTree();
+    self._d("Login Status: %s"%(node.tag));
+
+    if ProtocolTreeNode.tagEquals(node,"failure"):
+      self.authObject.authenticationFailed()
+      return 0
+      #raise Exception("Login Failure");
+
+    ProtocolTreeNode.require(node,"success");
+
+    expiration = node.getAttributeValue("expiration");
+
+    if expiration is not None:
+      self._d("Expires: "+str(expiration));
+      self.authObject.expireDate = expiration;
+
+      kind = node.getAttributeValue("kind");
+      self._d("Account type: %s"%(kind))
+
+    if kind == "paid":
+      self.authObject.accountKind = 1;
+    elif kind == "free":
+      self.authObject.accountKind = 0;
+    else:
+      self.authObject.accountKind = -1;
+
+    status = node.getAttributeValue("status");
+    self._d("Account status: %s"%(status));
+
+    if status == "expired":
+      self.loginFailed.emit()
+      raise Exception("Account expired on "+str(self.authObject.expireDate));
+
+    if status == "active":
+      if expiration is None:
+        #raise Exception ("active account with no expiration");
+        '''@@TODO expiration changed to creation'''
+    else:
+      self.authObject.accountKind = 1;
+
+    self.conn.reader.inn.buf = [];
+
+    self.conn.writer.outputKey = self.outputKey
+    self.authObject.authenticationComplete()
+    return 1
+
+
+class RC4:
+  def __init__(self, key, drop):
+    self.s = []
+    self.i = 0;
+    self.j = 0;
+
+    self.s = [0] * 256
+
+    for i in range(0, len(self.s)):
+      self.s[i] = i
+
+    for i in range(0, len(self.s)):
+      self.j = (self.j + self.s[i] + ord(key[i % len(key)])) % 256
+      RC4.swap(self.s, i, self.j)
+
+    self.j = 0;
+
+    self.cipher(_bytearray(drop), 0, drop)
+
+
+  def cipher(self, data, offset, length):
+    while True:
+      num = length
+      length = num - 1
+
+      if num == 0: break
+
+      self.i = (self.i+1) % 256
+      self.j = (self.j + self.s[self.i]) % 256
+
+      RC4.swap(self.s, self.i, self.j)
+
+      num2 = offset
+      offset = num2 + 1
+
+      data[num2] = ord(data[num2]) if type(data[num2]) == str else data[num2]
+      data[num2] = (data[num2] ^ self.s[(self.s[self.i] + self.s[self.j]) % 256])
+
+  @staticmethod
+  def swap(arr, i, j):
+    tmp = arr[i]
+    arr[i] = arr[j]
+    arr[j] = tmp
+
+
+if sys.version_info >= (3, 0):
+  buffer = lambda x: bytes(x, 'iso-8859-1') if type(x) is str else bytes(x)
+  _bytearray = lambda x: [0]*x if type(x) is int else x
+
+
+class KeyStream:
+
+  def __init__(self, key, macKey):
+    self.key = key if sys.version_info < (3, 0) else bytes(key, 'iso-8859-1')
+    self.rc4 = RC4(self.key, 0x300)
+    self.macKey = macKey if sys.version_info < (3, 0) else bytes(macKey, 'iso-8859-1')
+    self.seq = 0
+
+  def computeMac(self, bytes_buffer, int_offset, int_length):
+    mac = hmac.new(self.macKey, None, sha1)
+    mac.update(buffer(_bytearray(bytes_buffer[int_offset:])))
+
+    numArray = "%s%s%s%s" % (chr(self.seq >> 24), chr(self.seq >> 16), chr(self.seq >> 8), chr(self.seq))
+
+    mac.update(buffer(_bytearray(numArray)))
+
+    self.seq += 1
+    return mac.digest()
+
+
+  def decodeMessage(self, bufdata, macOffset, offset, length):
+    buf = bufdata[:-4]
+    hashed = bufdata[-4:]
+    numArray = self.computeMac(buf, 0, len(buf))
+
+    numArray = [ord(x) for x in numArray.decode('iso-8859-1')];
+
+    num = 0
+    while num < 4:
+      if numArray[macOffset + num] == hashed[num]:
+        num += 1
+      else:
+        raise Exception("INVALID MAC")
+
+    self.rc4.cipher(buf, 0, len(buf))
+
+    return [x for x in buf]
+
+  def encodeMessage(self, buf, macOffset, offset, length):
+    self.rc4.cipher(buf, offset, length)
+
+    hashed = self.computeMac(buf, offset, length)
+
+    numArray = [ord(x) for x in hashed.decode('iso-8859-1')]
+
+    output = buf[0:macOffset] + numArray[0:4] + buf[macOffset+4:]
+
+    return [x for x in output]
+
+  @staticmethod
+  def generateKeys(password, nonce):
+    _bytes = [0] * 4
+    numArray = [1,2,3,4]
+
+    if sys.version >= (3, 0):
+      nonce = nonce.encode('iso-8859-1')
+
+    for j in range(0, len(numArray)):
+      noncex = nonce + chr(numArray[j])
+      _bytes[j] = KeyStream.pbkdf2(password, noncex, 2, 20)
+
+    return _bytes
+
+  @staticmethod
+  def pbkdf2( password, salt, itercount, keylen, hashfn = hashlib.sha1 ):
+
+    def pbkdf2_F( h, salt, itercount, blocknum ):
+
+      def prf( h, data ):
+        hm = h.copy()
+        hm.update( buffer(_bytearray(data)) )
+        #hm.update(bytes(data))
+        d = hm.digest()
+
+        #return map(ord, d)
+        #print (hm.digest())
+
+        #if sys.version_info < (3, 0):
+        return [ord(i) for i in d.decode('iso-8859-1')]
+
+
+      U = prf( h, salt + pack('>i',blocknum ) )
+      T = U
+
+      for i in range(2, itercount+1):
+        U = prf( h, U )
+        T = starmap(xor, zip(T, U))
+
+      return T
+
+    digest_size = hashfn().digest_size
+    l = int(keylen / digest_size)
+    if keylen % digest_size != 0:
+      l += 1
+
+    h = hmac.new( password, None, hashfn )
+
+    T = []
+    for i in range(1, l+1):
+      tmp = pbkdf2_F( h, salt, itercount, i )
+      #tmp = map(chr, tmp)
+      #print(tmp)
+      #for item in tmp:
+      # print(item)
+      #sys.exit(1)
+      T.extend(tmp)
+
+    #print(T)
+    #sys.exit()
+    T = [chr(i) for i in T]
+    return "".join(T[0: keylen])
+
Description: update the connection manager to support the new WhatsApp version.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/connectionmanager.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/connectionmanager.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/connectionmanager.py
@@ -27,7 +27,7 @@ from Yowsup.Common.utilities import Util
 from Yowsup.Common.debugger import Debugger
 import threading, select, time
 from Yowsup.Common.watime import WATime
-from .Auth.auth import YowsupAuth
+from Yowsup.Auth.auth import YowsupAuth
 from Yowsup.Common.constants import Constants
 from Yowsup.Interfaces.Lib.LibInterface import LibMethodInterface, LibSignalInterface
 import tempfile
@@ -38,13 +38,12 @@ import base64
 import sys
 
 
-
 import traceback
 class YowsupConnectionManager:
 	
 	def __init__(self):
 		Debugger.attach(self)
-		self.currKeyId = 1
+		self.currKeyId = 0
 		self.iqId = 0
 		self.verbose = True
 		self.state = 0
@@ -124,20 +123,16 @@ class YowsupConnectionManager:
 
 		self.methodInterface.registerCallback("visible_ack",self.sendVisibleReceiptAck)
 
-		self.methodInterface.registerCallback("ping",self.sendPing)
-		self.methodInterface.registerCallback("pong",self.sendPong)
-
 		self.methodInterface.registerCallback("typing_send",self.sendTyping)
 		self.methodInterface.registerCallback("typing_paused",self.sendPaused)
 
-		self.methodInterface.registerCallback("subject_ack",self.sendSubjectReceived)
-
 		self.methodInterface.registerCallback("group_getGroups", self.sendGetGroups)
 		self.methodInterface.registerCallback("group_getInfo",self.sendGetGroupInfo)
 		self.methodInterface.registerCallback("group_create",self.sendCreateGroupChat)
 		self.methodInterface.registerCallback("group_addParticipants",self.sendAddParticipants)
 		self.methodInterface.registerCallback("group_removeParticipants",self.sendRemoveParticipants)
-		self.methodInterface.registerCallback("group_end",self.sendEndGroupChat)
+		self.methodInterface.registerCallback("group_leave",self.sendLeaveGroupChat)
+		self.methodInterface.registerCallback("group_delete",self.sendDeleteGroupChat)
 		self.methodInterface.registerCallback("group_setSubject",self.sendSetGroupSubject)
 		self.methodInterface.registerCallback("group_setPicture", self.sendSetPicture)
 		self.methodInterface.registerCallback("group_getPicture", self.sendGetPicture)
@@ -152,7 +147,7 @@ class YowsupConnectionManager:
 		self.methodInterface.registerCallback("status_update",self.sendChangeStatus)
 
 		self.methodInterface.registerCallback("presence_request",self.getLastOnline)
-		#self.methodInterface.registerCallback("presence_unsubscribe",self.sendUnsubscribe)#@@TODO implement method
+		self.methodInterface.registerCallback("presence_unsubscribe",self.sendUnsubscribe)
 		self.methodInterface.registerCallback("presence_subscribe",self.sendSubscribe)
 		self.methodInterface.registerCallback("presence_sendAvailableForChat",self.sendAvailableForChat)
 		self.methodInterface.registerCallback("presence_sendAvailable",self.sendAvailable)
@@ -164,13 +159,27 @@ class YowsupConnectionManager:
 		
 		self.methodInterface.registerCallback("profile_setStatus", self.sendChangeStatus)
 
+		self.methodInterface.registerCallback("sync_sendSync", self.sendSync)
+		
 		self.methodInterface.registerCallback("disconnect", self.disconnect)
 		self.methodInterface.registerCallback("ready", self.startReader)
 		
-		self.methodInterface.registerCallback("auth_login", self.auth )
-		#self.methodInterface.registerCallback("auth_login", self.auth)
+		self.methodInterface.registerCallback("auth_login", self.auth)
 		
 		self.methodInterface.registerCallback("media_requestUpload", self.sendRequestUpload)
+		
+		self.methodInterface.registerCallback("sync_sendContacts", self.sendSyncContacts)
+		self.methodInterface.registerCallback("sync_getStatuses", self.sendGetStatuses)
+
+		self.methodInterface.registerCallback("privacy_setList", self.sendSetPrivacyList)
+		self.methodInterface.registerCallback("privacy_getList", self.sendGetPrivacyList)
+
+		self.methodInterface.registerCallback("privacy_setSettings", self.sendSetPrivacySettings)
+		self.methodInterface.registerCallback("privacy_getSettings", self.sendGetPrivacySettings)
+
+		self.methodInterface.registerCallback("account_delete", self.sendAccountDelete)
+
+		self.methodInterface.registerCallback("subscription_generateLink", self.generateSubscriptionLink)
 
 
 	def disconnect(self, reason=""):
@@ -284,8 +293,10 @@ class YowsupConnectionManager:
 			
 			self.readerThread.setSocket(self.socket)
 			self.readerThread.disconnectedCallback = self.onDisconnected
+			self.readerThread.sendReceiptAck = self.sendReceiptAck
 			self.readerThread.onPing = self.sendPong
 			self.readerThread.ping = self.sendPing
+			self.readerThread.sendNotificationReceived = self.sendNotificationReceived
 			
 	
 			self.signalInterface.send("auth_success", (username,))
@@ -296,33 +307,19 @@ class YowsupConnectionManager:
 		
 	def sendTyping(self,jid):
 		self._d("SEND TYPING TO JID")
-		composing = ProtocolTreeNode("composing",{"xmlns":"http://jabber.org/protocol/chatstates"})
-		message = ProtocolTreeNode("message",{"to":jid,"type":"chat"},[composing]);
+		composing = ProtocolTreeNode("composing")
+		message = ProtocolTreeNode("chatstate",{"to":jid},[composing]);
 		self._writeNode(message);
 
 
 
 	def sendPaused(self,jid):
 		self._d("SEND PAUSED TO JID")
-		composing = ProtocolTreeNode("paused",{"xmlns":"http://jabber.org/protocol/chatstates"})
-		message = ProtocolTreeNode("message",{"to":jid,"type":"chat"},[composing]);
+		composing = ProtocolTreeNode("paused")
+		message = ProtocolTreeNode("chatstate",{"to":jid},[composing]);
 		self._writeNode(message);
 
 
-
-	def getSubjectMessage(self,to,msg_id,child):
-		messageNode = ProtocolTreeNode("message",{"to":to,"type":"subject","id":msg_id},[child]);
-
-		return messageNode
-
-	def sendSubjectReceived(self,to,msg_id):
-		self._d("Sending subject recv receipt")
-		receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"});
-		messageNode = self.getSubjectMessage(to,msg_id,receivedNode);
-		self._writeNode(messageNode);
-
-
-
 	def sendMessageReceipt(self, jid, msgId):
 		self.sendReceipt(jid, "chat", msgId)
 
@@ -331,9 +328,11 @@ class YowsupConnectionManager:
 
 	def sendReceipt(self,jid,mtype,mid):
 		self._d("sending message received to "+jid+" - type:"+mtype+" - id:"+mid)
-		receivedNode = ProtocolTreeNode("received",{"xmlns": "urn:xmpp:receipts"})
-		messageNode = ProtocolTreeNode("message",{"to":jid,"type":mtype,"id":mid},[receivedNode]);
-		self._writeNode(messageNode);
+		attr = {"to": jid, "id": mid}
+		if mtype == "read":
+		  attr["type"] = "read"
+		receiptNode = ProtocolTreeNode("receipt", attr)
+		self._writeNode(receiptNode)
 
 
 	def sendDeliveredReceiptAck(self,to,msg_id):
@@ -347,6 +346,29 @@ class YowsupConnectionManager:
 		messageNode = ProtocolTreeNode("message",{"to":to,"type":"chat","id":msg_id},[ackNode]);
 		return messageNode;
 
+	def sendReceiptAck(self, msg_id, receiptType):
+		ackNode = ProtocolTreeNode("ack",{"class": "receipt", "type": "delivery" if receiptType is None else receiptType, "id": msg_id})
+		self._writeNode(ackNode);
+
+	def sendMessageReceived(self, jid, msg_id):
+		receiptNode = ProtocolTreeNode("receipt",{"to": jid, "id": msg_id})
+		self._writeNode(receiptNode)
+
+	def sendNotificationReceived(self, to, msg_id, from_jid, participant, notificationType, childNode):
+		attrs = {"to": to, "class": "notification", "id": msg_id, "type": notificationType}
+		if participant is not None:
+			attrs["participant"] = participant
+		if from_jid is not None:
+			attrs["from"] = from_jid
+		ackNode = ProtocolTreeNode("ack", attrs, [childNode] if childNode is not None else None)
+		self._writeNode(ackNode)
+
+	def sendCleanDirty(self, dirtyType):
+		idx = self.makeId("clean_dirty_")
+		cleanNode = ProtocolTreeNode("clean", {"type": dirtyType})
+		iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "set", "to": self.domain, "xmlns": "urn:xmpp:whatsapp:dirty"}, [cleanNode])
+		self._writeNode(iqNode);
+
 	def makeId(self,prefix):
 		self.iqId += 1
 		idx = ""
@@ -363,8 +385,8 @@ class YowsupConnectionManager:
 
 		self.readerThread.requests[idx] = self.readerThread.parsePingResponse;
 
-		pingNode = ProtocolTreeNode("ping",{"xmlns":"w:p"});
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.domain},[pingNode]);
+		pingNode = ProtocolTreeNode("ping");
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.domain,"xmlns":"w:p"},[pingNode]);
 		self._writeNode(iqNode);
 		return idx
 
@@ -384,8 +406,8 @@ class YowsupConnectionManager:
 		idx = self.makeId("last_")
 		self.readerThread.requests[idx] = self.readerThread.parseLastOnline;
 
-		query = ProtocolTreeNode("query",{"xmlns":"jabber:iq:last"});
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[query]);
+		query = ProtocolTreeNode("query");
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid,"xmlns":"jabber:iq:last"},[query]);
 		self._writeNode(iqNode)
 
 
@@ -416,6 +438,12 @@ class YowsupConnectionManager:
 		self._writeNode(presenceNode);
 
 
+	def sendUnsubscribe(self,to):
+		presenceNode = ProtocolTreeNode("presence",{"type":"unsubscribe","to":to});
+
+		self._writeNode(presenceNode);
+
+
 	def mediaNode(fn):
 		def wrapped(self, *args):
 				mediaType = fn(self, *args)
@@ -425,7 +453,7 @@ class YowsupConnectionManager:
 				name = args[2]
 				size = args[3]
 				
-				mmNode = ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":mediaType,"file":name,"size":size,"url":url},None, args[4:][0] if args[4:] else None);
+				mmNode = ProtocolTreeNode("media", {"type":mediaType,"file":name,"size":size,"url":url},None, args[4:][0] if args[4:] else None);
 				return mmNode
 			
 		return wrapped
@@ -444,10 +472,12 @@ class YowsupConnectionManager:
 		
 	def sendChangeStatus(self,status):
 		self._d("updating status to: %s"%(status))
+
+		idx = self.makeId("send_status_")
+		statusNode = ProtocolTreeNode("status", None, None, status)
+		iqNode = ProtocolTreeNode("iq", {"to": self.domain, "type": "set", "id": idx, "xmlns": "status"}, [statusNode]);
 		
-		bodyNode = ProtocolTreeNode("body",None,None,status);
-		messageNode = self.getMessageNode("s.us",bodyNode)
-		self._writeNode(messageNode);
+		self._writeNode(iqNode);
 		
 		return messageNode.getAttributeValue("id")
 		
@@ -476,13 +506,13 @@ class YowsupConnectionManager:
 	def sendLocation(self, jid, latitude, longitude, preview):
 		self._d("sending location (" + latitude + ":" + longitude + ")")
 
-		return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"location","latitude":latitude,"longitude":longitude},None,preview)
+		return ProtocolTreeNode("media", {"type":"location","latitude":latitude,"longitude":longitude},None,preview)
 		
 	@sendMessage
 	def sendVCard(self, jid, data, name):
 		
 		cardNode = ProtocolTreeNode("vcard",{"name":name},None,data);
-		return ProtocolTreeNode("media", {"xmlns":"urn:xmpp:whatsapp:mms","type":"vcard"},[cardNode])
+		return ProtocolTreeNode("media", {"type":"vcard"},[cardNode])
 	
 	@sendMessage
 	def sendBroadcast(self, jids, content):
@@ -493,10 +523,11 @@ class YowsupConnectionManager:
 		
 		return [broadcastNode, messageNode]
 
-	def sendClientConfig(self,sound,pushID,preview,platform):
+	def sendClientConfig(self):
 		idx = self.makeId("config_");
-		configNode = ProtocolTreeNode("config",{"xmlns":"urn:xmpp:whatsapp:push","sound":sound,"id":pushID,"preview":"1" if preview else "0","platform":platform})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":self.domain},[configNode]);
+		configNode = ProtocolTreeNode("config",{"platform":"none"})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":self.domain,"xmlns":"urn:xmpp:whatsapp:push"},[configNode]);
+		self.readerThread.requests[idx] = self.readerThread.parseResultNode;
 
 		self._writeNode(iqNode);
 
@@ -507,8 +538,8 @@ class YowsupConnectionManager:
 		idx = self.makeId("get_groups_")
 		self.readerThread.requests[idx] = self.readerThread.parseGroups;
 
-		queryNode = ProtocolTreeNode("list",{"xmlns":"w:g","type":gtype})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":"g.us"},[queryNode])
+		queryNode = ProtocolTreeNode("list",{"type":gtype})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":"g.us","xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -518,8 +549,8 @@ class YowsupConnectionManager:
 		idx = self.makeId("get_g_info_")
 		self.readerThread.requests[idx] = self.readerThread.parseGroupInfo;
 
-		queryNode = ProtocolTreeNode("query",{"xmlns":"w:g"})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[queryNode])
+		queryNode = ProtocolTreeNode("query")
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid,"xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -529,8 +560,19 @@ class YowsupConnectionManager:
 		idx = self.makeId("create_group_")
 		self.readerThread.requests[idx] = self.readerThread.parseGroupCreated;
 
-		queryNode = ProtocolTreeNode("group",{"xmlns":"w:g","action":"create","subject":subject})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode])
+		queryNode = ProtocolTreeNode("group",{"action":"create","subject":subject})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us","xmlns":"w:g"},[queryNode])
+
+		self._writeNode(iqNode)
+
+
+	def sendDeleteGroupChat(self,gjid):
+		self._d("creating group: %s"%(subject))
+		idx = self.makeId("create_group_")
+		self.readerThread.requests[idx] = self.readerThread.parseGroupCreated;
+
+		queryNode = ProtocolTreeNode("group",{"action":"delete"})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid,"xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -546,8 +588,8 @@ class YowsupConnectionManager:
 		for part in participants:
 			innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) )
 
-		queryNode = ProtocolTreeNode("add",{"xmlns":"w:g"},innerNodeChildren)
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode])
+		queryNode = ProtocolTreeNode("add",None,innerNodeChildren)
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid,"xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -562,13 +604,13 @@ class YowsupConnectionManager:
 		for part in participants:
 			innerNodeChildren.append( ProtocolTreeNode("participant",{"jid":part}) )
 
-		queryNode = ProtocolTreeNode("remove",{"xmlns":"w:g"},innerNodeChildren)
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode])
+		queryNode = ProtocolTreeNode("remove",None,innerNodeChildren)
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid,"xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
 
-	def sendEndGroupChat(self,gjid):
+	def sendLeaveGroupChat(self,gjid):
 		self._d("removing group: %s"%(gjid))
 		idx = self.makeId("leave_group_")
 		self.readerThread.requests[idx] = self.readerThread.parseGroupEnded;
@@ -576,8 +618,8 @@ class YowsupConnectionManager:
 		innerNodeChildren = []
 		innerNodeChildren.append( ProtocolTreeNode("group",{"id":gjid}) )
 
-		queryNode = ProtocolTreeNode("leave",{"xmlns":"w:g"},innerNodeChildren)
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us"},[queryNode])
+		queryNode = ProtocolTreeNode("leave",None,innerNodeChildren)
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":"g.us","xmlns":"w:g"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -587,8 +629,8 @@ class YowsupConnectionManager:
 		idx = self.makeId("set_group_subject_")
 		self.readerThread.requests[idx] = self.readerThread.parseGroupSubject
 
-		queryNode = ProtocolTreeNode("subject",{"xmlns":"w:g","value":subject})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid},[queryNode]);
+		queryNode = ProtocolTreeNode("subject",{"value":subject})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"set","to":gjid,"xmlns":"w:g"},[queryNode]);
 
 		self._writeNode(iqNode)
 
@@ -597,8 +639,8 @@ class YowsupConnectionManager:
 		idx = self.makeId("get_participants_")
 		self.readerThread.requests[idx] = self.readerThread.parseParticipants
 
-		listNode = ProtocolTreeNode("list",{"xmlns":"w:g"})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid},[listNode]);
+		listNode = ProtocolTreeNode("list")
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":jid,"xmlns":"w:g"},[listNode]);
 
 		self._writeNode(iqNode)
 
@@ -610,8 +652,8 @@ class YowsupConnectionManager:
 		#@@TODO, ?!
 		self.readerThread.requests[idx] =  self.readerThread.parseGetPicture
 
-		listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"})
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"get"},[listNode]);
+		listNode = ProtocolTreeNode("picture",{"type":"image"})
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"get","xmlns":"w:profile:picture"},[listNode]);
 
 		self._writeNode(iqNode)
 
@@ -625,8 +667,8 @@ class YowsupConnectionManager:
 		for jid in jids:
 			innerNodeChildren.append( ProtocolTreeNode("user",{"jid": jid}) )
 
-		queryNode = ProtocolTreeNode("list",{"xmlns":"w:profile:picture"},innerNodeChildren)
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get"},[queryNode])
+		queryNode = ProtocolTreeNode("list",None,innerNodeChildren)
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"type":"get","to":self.jid,"xmlns":"w:profile:picture"},[queryNode])
 
 		self._writeNode(iqNode)
 
@@ -647,9 +689,9 @@ class YowsupConnectionManager:
 		idx = self.makeId("set_picture_")
 		self.readerThread.requests[idx] = self.readerThread.parseSetPicture
 
-		listNode = ProtocolTreeNode("picture",{"xmlns":"w:profile:picture","type":"image"}, None, imageData)
+		listNode = ProtocolTreeNode("picture",{"type":"image"}, None, imageData)
 
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"set"},[listNode])
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":jid,"type":"set","xmlns":"w:profile:picture"},[listNode])
 
 		self._writeNode(iqNode)
 
@@ -662,42 +704,149 @@ class YowsupConnectionManager:
 		if type(size) is not str:
 			size = str(size)
 
-		attribs = {"xmlns":"w:m","hash":b64Hash, "type":t, "size":size}
+		attribs = {"hash":b64Hash, "type":t, "size":size}
 
 		if b64OrigHash:
 			attribs["orighash"] = b64OrigHash
 
 		mediaNode = ProtocolTreeNode("media", attribs)
-		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":"s.whatsapp.net","type":"set"},[mediaNode])
+		iqNode = ProtocolTreeNode("iq",{"id":idx,"to":"s.whatsapp.net","type":"set","xmlns":"w:m"},[mediaNode])
 		
 		
 		self._writeNode(iqNode)
 
+
+	def sendSync(self, contacts):
+		idx = self.makeId("sendsync_")
+		self.readerThread.requests[idx] = self.readerThread.parseSync
+		
+		users = []
+		
+		for c in contacts:
+			users.append(ProtocolTreeNode("user",None,None,'+' + c.replace('+', '')))
+
+		node = ProtocolTreeNode(
+			"iq", 
+			{
+				"type" : "get",
+				"id" : idx,
+				"xmlns" : "urn:xmpp:whatsapp:sync"
+			}, 
+			[
+				(
+				ProtocolTreeNode(
+				"sync", 
+				{
+					"mode" : 'full',
+					"context" : 'registration',
+					"sid" : str((time.time() + 11644477200) * 10000000),
+					"index" : '0',
+					"last" : "true",
+				}, 
+				users, 
+				None)
+			  ),
+		]
+		, None)
+		self._writeNode(node)
+
+
 	def getMessageNode(self, jid, child):
-			requestNode = None;
 			serverNode = ProtocolTreeNode("server",None);
 			xNode = ProtocolTreeNode("x",{"xmlns":"jabber:x:event"},[serverNode]);
-			childCount = (0 if requestNode is None else 1) +2;
-			messageChildren = []#[None]*childCount;
-			if requestNode is not None:
-				messageChildren.append(requestNode);
-			#System.currentTimeMillis() / 1000L + "-"+1
-			messageChildren.append(xNode)
+			messageChildren = []
 			
 			if type(child) == list:
-				messageChildren.extend(child)
+				messageChildren = child
 			else:
 				messageChildren.append(child)
+			messageChildren.append(xNode)
 				
 			msgId = str(int(time.time()))+"-"+ str(self.currKeyId)
 			
-			messageNode = ProtocolTreeNode("message",{"to":jid,"type":"chat","id":msgId},messageChildren)
+			messageNode = ProtocolTreeNode("message",{"to":jid,"type":"text","id":msgId},messageChildren)
 			
 			self.currKeyId += 1
 
 
 			return messageNode;
 
+	def sendSyncContacts(self, numbers):
+		print("sendSyncContacts")
+		syncNodes = []
+		for number in numbers:
+			print(number)
+			if number.find("@") >= 0:
+				number = "+" + number.split("@")[0]
+			userNode = ProtocolTreeNode("user", None, None, number)
+			syncNodes.append(userNode)
+		if len(syncNodes) > 0:
+			idx = self.makeId("sync_")
+			self.readerThread.requests[idx] = self.readerThread.parseSyncContacts
+			syncNode = ProtocolTreeNode("sync", {"context": "background", "index": 0, "mode": "delta", "last": "true", "sid": str(int(time.time()))}, syncNodes)
+			iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "get", "to": self.jid, "xmlns": "urn:xmpp:whatsapp:sync"}, syncNode)
+			self._writeNode(iqNode)
+
+	def sendGetStatuses(self, jids):
+		syncNodes = []
+		for cjid in cjids:
+			userNode = ProtocolTreeNode("user", {"jid": cjid})
+			syncNodes.append(userNode)
+		if len(syncNodes) > 0:
+			idx = self.makeId("sync_statuses_")
+			self.readerThread.requests[idx] = self.readerThread.parseSyncStatuses
+			statusNode = ProtocolTreeNode("status", None, syncNodes)
+			iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "get", "to": self.domain, "xmlns": "status"}, statusNode)
+			self._writeNode(iqNode)
+
+	def sendSetPrivacyList(self, cjids):
+		privacyNodes = []
+		order = 0
+		for cjid in cjids:
+			itemNode = ProtocolTreeNode("item", {"type": "jid", "value": cjid, "action": "deny", "order": order})
+			order += 1
+		if len(privacyNodes) > 0:
+			idx = self.makeId("privacy_setlist_")
+			listNode = ProtocolTreeNode("list", {"name": "default"}, privacyNodes)
+			queryNode = ProtocolTreeNode("query", None, [listNode])
+			iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "set", "xmlns": "jabber:iq:privacy"}, [queryNode])
+			self._writeNode(iqNode)
+
+	def sendGetPrivacyList(self):
+		idx = self.makeId("privacy_getlist_")
+		self.readerThread.requests[idx] = self.readerThread.parsePrivacyList
+		listNode = ProtocolTreeNode("list", {"name": "default"})
+		queryNode = ProtocolTreeNode("query", {}, [listNode])
+		iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "get", "xmlns": "jabber:iq:privacy"}, [queryNode])
+		self._writeNode(iqNode)
+
+	def sendSetPrivacySettings(self, key, value):
+		idx = self.makeId("privacy_setvalue_")
+		categoryNode = ProtocolTreeNode("category", {"name": key, "value": value})
+		privacyNode = ProtocolTreeNode("privacy", None, [categoryNode])
+		iqNode = ProtocolTreeNode("iq", {"id": idx, "to": self.domain, "type": "set", "xmlns": "privacy"}, [privacyNode])
+		self._writeNode(iqNode)
+
+	def sendGetPrivacySettings(self):
+		idx = self.makeId("privacy_getvalues_")
+		self.readerThread.requests[idx] = self.readerThread.parsePrivacySettings
+		privacyNode = ProtocolTreeNode("privacy")
+		iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "get", "to": self.domain, "xmlns": "privacy"}, [privacyNode])
+		self._writeNode(iqNode)
+
+	def sendAccountDelete(self):
+		idx = self.makeId("account_delete_")
+		self.readerThread.requests[idx] = self.readerThread.parseAccountDelete
+		removeNode = ProtocolTreeNode("remove")
+		iqNode = ProtocolTreeNode("iq", {"id": idx, "type": "get", "to": self.domain, "xmlns": "urn:xmpp:whatsapp:account"}, [removeNode])
+		self._writeNode(iqNode)
+
+	def generateSubscriptionLink(self, mode, years):
+		phone = self.jid.split("@")[0]
+		chksum = hashlib.md5(phone + "abc").hexdigest()
+		link = "https://www.whatsapp.com/payments/"; + mode + ".php?phone=" + phone + "&cksum=" + chksum + "&sku=" + years
+		self.signalInterface.send("subscription_link", (link, ))
+
 
 class ReaderThread(threading.Thread):
 	def __init__(self):
@@ -715,7 +864,6 @@ class ReaderThread(threading.Thread):
 		self.autoPong = True
 		self.onPing = self.ping = None
 
-		self.lastPongTime = int(time.time())
 		super(ReaderThread,self).__init__();
 
 		self.daemon = True
@@ -737,33 +885,12 @@ class ReaderThread(threading.Thread):
 			self.disconnectedSent = True
 			if self.disconnectedCallback:
 				self.disconnectedCallback()
-			self.lock.release()
-			self.signalInterface.send("disconnected", (reason,))
+		self.lock.release()
+		self.signalInterface.send("disconnected", (reason,))
 
 	def run(self):
 		self._d("Read thread startedX");
 		while True:
-
-			
-			countdown = self.timeout - ((int(time.time()) - self.lastPongTime))
-			
-			remainder = countdown % self.selectTimeout
-			countdown = countdown - remainder
-					
-			if countdown <= 0:
-				self._d("No hope, dying!")
-				self.sendDisconnected("closed")
-				return
-			else:
-				if countdown % (self.selectTimeout*10) == 0 or countdown < 11:
-					self._d("Waiting, time to die: T-%i seconds" % countdown )
-					
-				if self.timeout-countdown == 150 and self.ping and self.autoPong:
-					self.ping()
-
-				self.selectTimeout = 1 if countdown < 11 else 3
-
-
 			try:
 				ready = select.select([self.socket.reader.rawIn], [], [], self.selectTimeout)
 			except:
@@ -784,55 +911,38 @@ class ReaderThread(threading.Thread):
 					self.sendDisconnected("closed")
 					return
 
-				self.lastPongTime = int(time.time());
-
 				if node is not None:
-					if ProtocolTreeNode.tagEquals(node,"iq"):
+					if ProtocolTreeNode.tagEquals(node, "stream:error"):
+						childNode = node.getChild(0)
+						reason = childNode.getAttributeValue("text")
+						self._d("Stream error!")
+						self.sendDisconnected("stream:error" if reason is None else reason)
+
+					elif ProtocolTreeNode.tagEquals(node,"iq"):
 						iqType = node.getAttributeValue("type")
 						idx = node.getAttributeValue("id")
+						iqxmlns = node.getAttributeValue("xmlns")
 
 						if iqType is None:
 							raise Exception("iq doesn't have type")
 
-						if iqType == "result":
+						if iqxmlns == "urn:xmpp:ping":
+							self.onPing(idx)
+						elif iqType == "result":
 							if idx in self.requests:
 								self.requests[idx](node)
 								del self.requests[idx]
-							elif idx.startswith(self.connection.user):
-								accountNode = node.getChild(0)
-								ProtocolTreeNode.require(accountNode,"account")
-								kind = accountNode.getAttributeValue("kind")
-
-								if kind == "paid":
-									self.connection.account_kind = 1
-								elif kind == "free":
-									self.connection.account_kind = 0
-								else:
-									self.connection.account_kind = -1
-
-								expiration = accountNode.getAttributeValue("expiration")
-
-								if expiration is None:
-									raise Exception("no expiration")
-
-								try:
-									self.connection.expire_date = long(expiration)
-								except ValueError:
-									raise IOError("invalid expire date %s"%(expiration))
+							else:
+								self._d("unexpected result id: " + idx)
 
-								self.eventHandler.onAccountChanged(self.connection.account_kind,self.connection.expire_date)
 						elif iqType == "error":
 							if idx in self.requests:
 								self.requests[idx](node)
 								del self.requests[idx]
 						elif iqType == "get":
 							childNode = node.getChild(0)
-							if ProtocolTreeNode.tagEquals(childNode,"ping"):
-								if self.autoPong:
-									self.onPing(idx)
-									
-								self.signalInterface.send("ping", (idx,))	
-							elif ProtocolTreeNode.tagEquals(childNode,"query") and node.getAttributeValue("from") is not None and "http://jabber.org/protocol/disco#info"; == childNode.getAttributeValue("xmlns"):
+							
+							if ProtocolTreeNode.tagEquals(childNode,"query") and node.getAttributeValue("from") is not None and "http://jabber.org/protocol/disco#info"; == childNode.getAttributeValue("xmlns"):
 								pin = childNode.getAttributeValue("pin");
 								timeoutString = childNode.getAttributeValue("timeout");
 								try:
@@ -857,32 +967,166 @@ class ReaderThread(threading.Thread):
 						else:
 							raise Exception("Unkown iq type %s"%(iqType))
 
+					elif ProtocolTreeNode.tagEquals(node, "ib"):
+						dirtyNode = node.getChild("dirty")
+						if dirtyNode is not None:
+							dirtyType = dirtyNode.getAttributeValue("type")
+							self.signalInterface.send("ib_dirty", (dirtyType,))
+                            ##sendCleanDirty(dirtyType)
+
 					elif ProtocolTreeNode.tagEquals(node,"presence"):
-						xmlns = node.getAttributeValue("xmlns")
 						jid = node.getAttributeValue("from")
 
-						if (xmlns is None or xmlns == "urn:xmpp") and jid is not None:
+						if jid is not None:
 							presenceType = node.getAttributeValue("type")
 							if presenceType == "unavailable":
 								self.signalInterface.send("presence_unavailable", (jid,))
 							elif presenceType is None or presenceType == "available":
 								self.signalInterface.send("presence_available", (jid,))
 
-						elif xmlns == "w" and jid is not None:
-							status = node.getAttributeValue("status")
+					elif ProtocolTreeNode.tagEquals(node, "notification"):
+
+						receiptRequested = True;
+						notificationType = None
+
+						notificationType = node.getAttributeValue("type");
+						notificationId = node.getAttributeValue("id");
+						notificationTo = node.getAttributeValue("to");
+						fromJid = node.getAttributeValue("from");
+						timestamp =int(node.getAttributeValue("t"))
+						msgId = node.getAttributeValue("id")
+							
+						if notificationType == "picture":
+							bodyNode = node.getChild("set")
+							
+							if bodyNode:
+								pictureId = int(bodyNode.getAttributeValue("id"))
+								if "-" in bodyNode.getAttributeValue("jid"):
+									self.signalInterface.send("notification_groupPictureUpdated",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, pictureId, receiptRequested))
+								else:
+									self.signalInterface.send("notification_contactProfilePictureUpdated",(bodyNode.getAttributeValue("jid"), timestamp, msgId, pictureId, receiptRequested))
+
+							else:
+								bodyNode = node.getChild("delete")
+
+								if bodyNode:
+									if "-" in bodyNode.getAttributeValue("jid"):
+										self.signalInterface.send("notification_groupPictureRemoved",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, receiptRequested))
+									else:
+										self.signalInterface.send("notification_contactProfilePictureRemoved",(bodyNode.getAttributeValue("jid"), timestamp, msgId, receiptRequested))
+
+							#if isGroup:
+							#	
+							#	self.signalInterface.send("notification_groupPictureUpdated",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, receiptRequested))
+							#else:
+							#	self.signalInterface.send("notification_contactProfilePictureUpdated",(bodyNode.getAttributeValue("jid"), timestamp, msgId, receiptRequested))
+
+							#self.sendNotificationReceived(notificationTo, notificationId, fromJid, participant, notificationType, None)
+
+						elif notificationType == "participant":
+							addSubject = None
+							removeSubject = None
+							author = None
+
+							bodyNode = node.getChild("add");
+							if bodyNode is not None:
+								addSubject = bodyNode.getAttributeValue("jid");
+								author = bodyNode.getAttributeValue("author") or addSubject
+
+							bodyNode = node.getChild("remove");
+							if bodyNode is not None:
+								removeSubject = bodyNode.getAttributeValue("jid");
+								author = bodyNode.getAttributeValue("author") or removeSubject
+
+							if addSubject is not None:
+								
+								self.signalInterface.send("notification_groupParticipantAdded", (fromAttribute, addSubject, author, timestamp, msgId, receiptRequested))
+								
+							if removeSubject is not None:
+								self.signalInterface.send("notification_groupParticipantRemoved", (fromAttribute, removeSubject, author, timestamp, msgId, receiptRequested))
+
+							#self.sendNotificationReceived(notificationTo, notificationId, fromJid, participant, notificationType, None)
+
+						elif notificationType == "web":
+							self._d("web notification not implemented")
+
+							#self.sendNotificationReceived(fromJid, notificationId, notificationTo, participant, notificationType, None)
+
+						elif notificationType == "status":
+							setNode = node.getChild("set")
+							status = None if setNode is None else (setNode.data if sys.version_info < (3, 0) else setNode.data.encode('latin-1').decode());
+							
+							if status is not None:
+								self.signalInterface.send("contact_statusReceived",(fromJid, status))
+
+							#self.sendNotificationReceived(notificationTo, notificationId, fromJid, participant, notificationType, None)
+
+						elif notificationType == "subject":
+							receiptRequested = True;
+
+							bodyNode = node.getChild("body");
+							newSubject = None if bodyNode is None else (bodyNode.data if sys.version_info < (3, 0) else bodyNode.data.encode('latin-1').decode());
+							
+							if newSubject is not None:
+								self.signalInterface.send("group_subjectReceived",(msgId, fromAttribute, author, newSubject, int(attribute_t),  receiptRequested))
+
+							#self.sendNotificationReceived(notificationTo, notificationId, fromJid, participant, notificationType, None)
+
+						elif notificationType == "contacts":
+							contactNode = node.getChild("add")
+							contactJid = contactNode.getAttributeValue("jid")
+							self.signalInterface.send("notification_contactAdded", (contactJid, ))
+								
+							contactsNode = ProtocolTreeNode("sync", {"contacts": "out"})
+							#self.sendNotificationReceived(fromJid, notificationId, notificationTo, participant, notificationType, contactsNode)
+
+					elif ProtocolTreeNode.tagEquals(node, "receipt"):
+						receiptType = node.getAttributeValue("type");
+						fromJid = node.getAttributeValue("from");
+						msg_id = node.getAttributeValue("id")
+						if fromJid[-9:] == "broadcast":
+							fromJid = node.getAttributeValue("participant")
+						self.sendReceiptAck(msg_id, receiptType)
+						if receiptType != "delivered" and receiptType != "played":
+							self.signalInterface.send("receipt_messageDelivered", (fromJid, msg_id))
+							groupNode = node.getChild("list")
+							if groupNode:
+								items = groupNode.getAllChildren("item");
+								for i in items:
+									msg_id = i.getAttributeValue("id")
+									self.signalInterface.send("receipt_messageDelivered", (fromJid, msg_id))
+
+					elif ProtocolTreeNode.tagEquals(node, "ack"):
+						ackClass = node.getAttributeValue("class")
+						if ackClass == "message":
+							fromAttribute = node.getAttributeValue("from")
+							msgId = node.getAttributeValue("id")
+							self.signalInterface.send("receipt_messageSent", (fromAttribute, msgId))
+						elif ackClass == "receipt":
+							self._d("ack receipt not implemented")
+
+					elif ProtocolTreeNode.tagEquals(node, "chatstate"):
+						fromAttribute = node.getAttributeValue("from")
+						composingNode = node.getChild("composing");
+						if composingNode is not None:
+							self.signalInterface.send("contact_typing", (fromAttribute, ))
+						pausedNode = node.getChild("paused");
+						if pausedNode is not None:
+							self.signalInterface.send("contact_paused", (fromAttribute, ))
 
-							if status == "dirty":
-								#categories = self.parseCategories(node); #@@TODO, send along with signal
-								self._d("WILL SEND DIRTY")
-								self.signalInterface.send("status_dirty")
-								self._d("SENT DIRTY")
 
 					elif ProtocolTreeNode.tagEquals(node,"message"):
 						self.parseMessage(node)
-					
+
 
 		self._d("Reader thread terminating now!")
-					
+
+	def parseResultNode(self,node):
+		typeval = node.getAttributeValue("type");
+		if typeval != "result":
+			idx = node.getAttributeValue("id")
+			self._d("error response: " + idx)
+
 	def parseOfflineMessageStamp(self,stamp):
 
 		watime = WATime();
@@ -895,9 +1139,7 @@ class ReaderThread(threading.Thread):
 
 	def parsePingResponse(self, node):
 		idx = node.getAttributeValue("id")
-		self.lastPongTime = int(time.time())
-		
-		
+
 
 	def parseLastOnline(self,node):
 		jid = node.getAttributeValue("from");
@@ -920,6 +1162,7 @@ class ReaderThread(threading.Thread):
 
 	def parseGroups(self,node):
 		children = node.getAllChildren("group");
+		groups = []
 		for groupNode in children:
 			jid = groupNode.getAttributeValue("id") + "@g.us"
 			owner = groupNode.getAttributeValue("owner")
@@ -929,6 +1172,9 @@ class ReaderThread(threading.Thread):
 			creation = groupNode.getAttributeValue("creation")
 
 			self.signalInterface.send("group_gotInfo",(jid, owner, subject, subjectOwner, int(subjectT),int(creation)))
+			groups.append((jid, owner, subject, subjectOwner, int(subjectT),int(creation)))
+
+		self.signalInterface.send("group_gotGroups", (groups,))
 
 
 	def parseGroupInfo(self,node):
@@ -1028,6 +1274,21 @@ class ReaderThread(threading.Thread):
 
 		return tmp
 	
+	def parseSync(self, node):
+		node_in = node.getChild("sync").getChild("in").getAllChildren("user")
+		node_out = node.getChild("sync").getChild("out").getAllChildren("user")
+		
+		_in = [item.data for item in node_in]
+		_out = [item.data for item in node_out]
+		
+		# Uncomment the following lines if you would rather return the jid
+		# instead of the (international) phone number.
+		# _in = [item.getAttributeValue("jid") for item in node_in]
+		# _out = [item.getAttributeValue("jid") for item in node_out]
+		
+		self.signalInterface.send("sync_gotSyncResult", (_in, _out))
+		
+	
 	def parseGetPicture(self,node):
 		jid = node.getAttributeValue("from");
 		if "error code" in node.toString():
@@ -1048,14 +1309,14 @@ class ReaderThread(threading.Thread):
 	def parseGetPictureIds(self,node):
 		jid = node.getAttributeValue("from");
 		groupNode = node.getChild("list")
-		#self._d(groupNode.toString())
+		self._d(groupNode.toString())
 		children = groupNode.getAllChildren("user");
-		#pids = []
+		pids = []
 		for c in children:
 			if c.getAttributeValue("id") is not None:
-				#pids.append({"jid":c.getAttributeValue("jid"),"id":c.getAttributeValue("id")})
+				pids.append({"jid":c.getAttributeValue("jid"),"id":c.getAttributeValue("id")})
 				self.signalInterface.send("contact_gotProfilePictureId", (c.getAttributeValue("jid"), c.getAttributeValue("id")))
-		#self.signalInterface.send("contact_gotProfilePictureIds", (pids,))
+		self.signalInterface.send("contact_gotProfilePictureIds", (pids,))
 
 
 	def parseSetPicture(self,node):
@@ -1109,56 +1370,107 @@ class ReaderThread(threading.Thread):
 			else:
 				self.signalInterface.send("media_uploadRequestFailed", (_hash,))
 				
+	def parseSyncContacts(self, node):
+		syncNode = node.getChild("sync")
+		childs = []
+		syncList = []
+		if syncNode is not None:
+			fullNode = syncNode.getChild("full")
+			if fullNode is not None:
+				childs += fullNode.getAllChildren()
+			inNode = syncNode.getChild("in")
+			if inNode is not None:
+				childs += inNode.getAllChildren()
+		for child in childs:
+			if ProtocolTreeNode.tagEquals(child, "user"):
+				cjid = child.getAttributeValue("jid")
+				cphone = child.data
+				syncList.append({"jid": cjid, "phone": cphone})
+		if len(syncList) > 0:
+			self.signalInterface.send("sync_contactsReceived", (syncList,))
+
+
+	def parseSyncStatuses(self, node):
+		syncNode = node.getChild("sync")
+		childs = node.getAllChildren()
+		syncList = []
+		for child in childs:
+			if ProtocolTreeNode.tagEquals(child, "user"):
+				cjid = child.getAttributeValue("jid")
+				timestamp = child.getAttributeValue("t")
+				message = child.data
+				if len(message) == 0:
+					code = child.getAttributeValue("code")
+					if code == "401":
+						message = "hidden"
+				syncList.append({"jid": cjid, "lastseen": timestamp, "message": message})
+		if len(syncList) > 0:
+			self.signalInterface.send("sync_statusesReceived", (syncList,))
+
+	def parsePrivacyList(self, node):
+		listNode = node.getChild("list")
+		privacyList = []
+		if listNode is not None:
+			childs = listNode.getAllChildren()
+			for child in childs:
+				if ProtocolTreeNode.tagEquals(child, "item"):
+					cjid = child.getAttributeValue("jid")
+					if cjid is not None:
+						privacyList.append(cjid)
+		if len(privacyList) > 0:
+			self.signalInterface.send("privacy_listReceived", (privacyList,))
+
+	def parsePrivacySettings(self, node):
+		settingsList = []
+		childs = node.getAllChildren()
+		for child in childs:
+			if ProtocolTreeNode.tagEquals(node, "category"):
+				key = child.getAttributeValue("name")
+				value = child.getAttributeValue("value")
+				settingsList.append({"key": key, "value": value})
+		if len(settingsList) > 0:
+			self.signalInterface.send("privacy_settingsReceived", (settingsList,))
+
+	def parseAccountDelete(self, node):
+		#TODO
+		self._d("parseAccountDelete not implemented")
 
 	def parseMessage(self,messageNode):
-
-
-		bodyNode = messageNode.getChild("body");
-#		offlineNode = messageNode.getChild("offline")
-
+		id = messageNode.getAttributeValue("id");
+		timestamp = int(messageNode.getAttributeValue("t"))
+		fromAttribute = messageNode.getAttributeValue("from");
+		author = messageNode.getAttributeValue("participant");
+		isBroadcast = False;
+		if fromAttribute.find("@broadcast") >= 0:
+			fromAttribute = author;
+			isBroadcast = True;
 		
-		newSubject = "" if bodyNode is None else bodyNode.data;
+		offline = messageNode.getAttributeValue("offline") is not None
+		retry = messageNode.getAttributeValue("retry");
+		typeAttribute = messageNode.getAttributeValue("type");
+
 		msgData = None
-#		timestamp =long(time.time()*1000) if not offlineNode else int(messageNode.getAttributeValue("t"))*1000;
-		timestamp =int(messageNode.getAttributeValue("t"))
 		isGroup = False
-		isBroadcast = False
 		
+		bodyNode = messageNode.getChild("body");
+		newSubject = "" if bodyNode is None else bodyNode.data;
 		if newSubject.find("New version of WhatsApp Messenger is now available")>-1:
 			self._d("Rejecting whatsapp server message")
 			return #REJECT THIS FUCKING MESSAGE!
 
-
-		fromAttribute = messageNode.getAttributeValue("from");
-
 		try:
 			fromAttribute.index('-')
 			isGroup = True
 		except:
 			pass
 
-		author = messageNode.getAttributeValue("author");
-		#@@TODO reactivate blocked contacts check from client
-		'''if fromAttribute is not None and fromAttribute in self.eventHandler.blockedContacts:
-			self._d("CONTACT BLOCKED!")
-			return
-
-		if author is not None and author in self.eventHandler.blockedContacts:
-			self._d("CONTACT BLOCKED!")
-			return
-		'''
-
 		pushName = None
 		notifNode = messageNode.getChild("notify")
 		if notifNode is not None:
 			pushName = notifNode.getAttributeValue("name");
-			#pushName = pushName.decode("utf8")
 
 
 		msgId = messageNode.getAttributeValue("id");
-		attribute_t = messageNode.getAttributeValue("t");
-
-		typeAttribute = messageNode.getAttributeValue("type");
 
 		if typeAttribute == "error":
 			errorCode = 0;
@@ -1171,96 +1483,13 @@ class ReaderThread(threading.Thread):
 					'''catch value error'''
 				self.signalInterface.send("message_error", (msgId, fromAttribute, errorCode))
 
-		elif typeAttribute == "notification":
-
-			receiptRequested = False;
-			pictureUpdated = None
-
-			pictureUpdated = messageNode.getChild("notification").getAttributeValue("type");
-
-			wr = None
-			wr = messageNode.getChild("request").getAttributeValue("xmlns");
-			if wr == "urn:xmpp:receipts":
-				receiptRequested = True
-				
-			if pictureUpdated == "picture":
-				notifNode = messageNode.getChild("notification");
-				#bodyNode = messageNode.getChild("notification").getChild("set") or messageNode.getChild("notification").getChild("delete")
-
-				bodyNode = notifNode.getChild("set")
-				
-				if bodyNode:
-					pictureId = int(bodyNode.getAttributeValue("id"))
-					if isGroup:
-						self.signalInterface.send("notification_groupPictureUpdated",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, pictureId, receiptRequested))
-					else:
-						self.signalInterface.send("notification_contactProfilePictureUpdated",(bodyNode.getAttributeValue("jid"), timestamp, msgId, pictureId, receiptRequested))
-
-				else:
-					bodyNode = notifNode.getChild("delete")
-
-					if bodyNode:
-						if isGroup:
-							self.signalInterface.send("notification_groupPictureRemoved",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, receiptRequested))
-						else:
-							self.signalInterface.send("notification_contactProfilePictureRemoved",(bodyNode.getAttributeValue("jid"), timestamp, msgId, receiptRequested))
-
-				#if isGroup:
-				#	
-				#	self.signalInterface.send("notification_groupPictureUpdated",(bodyNode.getAttributeValue("jid"), bodyNode.getAttributeValue("author"), timestamp, msgId, receiptRequested))
-				#else:
-				#	self.signalInterface.send("notification_contactProfilePictureUpdated",(bodyNode.getAttributeValue("jid"), timestamp, msgId, receiptRequested))
-
-			else:
-				addSubject = None
-				removeSubject = None
-				author = None
-
-				bodyNode = messageNode.getChild("notification").getChild("add");
-				if bodyNode is not None:
-					addSubject = bodyNode.getAttributeValue("jid");
-					author = bodyNode.getAttributeValue("author") or addSubject
-
-				bodyNode = messageNode.getChild("notification").getChild("remove");
-				if bodyNode is not None:
-					removeSubject = bodyNode.getAttributeValue("jid");
-					author = bodyNode.getAttributeValue("author") or removeSubject
-
-				if addSubject is not None:
-					
-					self.signalInterface.send("notification_groupParticipantAdded", (fromAttribute, addSubject, author, timestamp, msgId, receiptRequested))
-					
-				if removeSubject is not None:
-					self.signalInterface.send("notification_groupParticipantRemoved", (fromAttribute, removeSubject, author, timestamp, msgId, receiptRequested))
-
-
-		elif typeAttribute == "subject":
-			receiptRequested = False;
-			requestNodes = messageNode.getAllChildren("request");
-			for requestNode in requestNodes:
-				if requestNode.getAttributeValue("xmlns") == "urn:xmpp:receipts":
-					receiptRequested = True;
-
-			bodyNode = messageNode.getChild("body");
-			newSubject = None if bodyNode is None else (bodyNode.data if sys.version_info < (3, 0) else bodyNode.data.encode('latin-1').decode());
-			
-			if newSubject is not None:
-				self.signalInterface.send("group_subjectReceived",(msgId, fromAttribute, author, newSubject, int(attribute_t),  receiptRequested))
-
-		elif typeAttribute == "chat":
+		elif typeAttribute == "text" or typeAttribute == "media":
 			wantsReceipt = False;
 			messageChildren = [] if messageNode.children is None else messageNode.children
 
 			for childNode in messageChildren:
 				if ProtocolTreeNode.tagEquals(childNode,"request"):
 					wantsReceipt = True;
-				
-				if ProtocolTreeNode.tagEquals(childNode,"broadcast"):
-					isBroadcast = True
-				elif ProtocolTreeNode.tagEquals(childNode,"composing"):
-						self.signalInterface.send("contact_typing", (fromAttribute,))
-				elif ProtocolTreeNode.tagEquals(childNode,"paused"):
-						self.signalInterface.send("contact_paused",(fromAttribute,))
 
 				elif ProtocolTreeNode.tagEquals(childNode,"media") and msgId is not None:
 	
@@ -1324,7 +1553,7 @@ class ReaderThread(threading.Thread):
 					elif mediaType =="vcard":
 						#return
 						#mediaItem.preview = messageNode.getChild("media").data
-						vcardData = messageNode.getChild("media").getChild("vcard").toString()
+						vcardData = messageNode.getChild("media").getChild("vcard").data
 						vcardName = messageNode.getChild("media").getChild("vcard").getAttributeValue("name")
 						
 						if vcardName and not sys.version_info < (3, 0):
@@ -1404,10 +1633,6 @@ class ReaderThread(threading.Thread):
 								self.signalInterface.send("receipt_messageDelivered", (fromAttribute, msgId))
 							elif receipt_type == "visible":
 								self.signalInterface.send("receipt_visible", (fromAttribute, msgId))
-							
-
-
-
 
 			if msgData:
 				msgData = msgData if sys.version_info < (3, 0) else msgData.encode('latin-1').decode()
Description: update the messages used by client/server interface.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/Interfaces/Interface.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/Interfaces/Interface.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/Interfaces/Interface.py
@@ -74,19 +74,33 @@ class SignalInterfaceBase(object):
 			"notification_groupPictureRemoved",
 			"notification_groupParticipantAdded",
 			"notification_groupParticipantRemoved",
+			"notification_contactAdded",
 
 			"contact_gotProfilePictureId",
+			"contact_gotProfilePictureIds",
 			"contact_gotProfilePicture",
 			"contact_typing",
 			"contact_paused",
+			"contact_statusReceived",
 			
 			"profile_setPictureSuccess",
 			"profile_setPictureError",
 			"profile_setStatusSuccess",
+			
+			"sync_gotSyncResult",
 
 			"ping",
 			"pong",
 			"disconnected",
+
+			"subscription_link",
+
+			"privacy_listReceived",
+
+			"privacy_settingsReceived",
+
+			"sync_contactsReceived",
+			"sync_statusesReceived",
 			
 			"media_uploadRequestSuccess",
 			"media_uploadRequestFailed",
@@ -200,6 +214,7 @@ class MethodInterfaceBase(object):
 			"profile_setPicture",
 			"profile_setStatus",
 
+			"sync_sendSync",
 			
 			"ready",
 			"disconnect",
Description: fix the Examples path and countries.csv place.
Author: Joao Eriberto Mota Filho <[email protected]>

Description: fix the Examples path and countries.csv place.
             Make the command compliant with new WhatsApp version.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/yowsup-cli
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/yowsup-cli
+++ yowsup-0.0~git20140314.938cf1/src/yowsup-cli
@@ -30,18 +30,18 @@ import argparse, sys, os, csv
 from Yowsup.Common.utilities import Utilities
 from Yowsup.Common.debugger import Debugger
 from Yowsup.Common.constants import Constants
-from Examples.CmdClient import WhatsappCmdClient
-from Examples.EchoClient import WhatsappEchoClient
-from Examples.ListenerClient import WhatsappListenerClient
+from Yowsup.Examples.CmdClient import WhatsappCmdClient
+from Yowsup.Examples.EchoClient import WhatsappEchoClient
+from Yowsup.Examples.ListenerClient import WhatsappListenerClient
 from Yowsup.Registration.v2.existsrequest import WAExistsRequest as WAExistsRequestV2
 from Yowsup.Registration.v2.coderequest import WACodeRequest as WACodeRequestV2
 from Yowsup.Registration.v2.regrequest import WARegRequest as WARegRequestV2
 from Yowsup.Contacts.contacts import WAContactsSyncRequest
-
+from Yowsup.Examples.PictureClient import WhatsappPictureClient
 import threading,time, base64
 
 DEFAULT_CONFIG = os.path.expanduser("~")+"/.yowsup/auth"
-COUNTRIES_CSV = "countries.csv"
+COUNTRIES_CSV = "/usr/share/yowsup-cli/countries.csv"
 
 CONFIG_HELP = """\
 Yowsup Configuration
@@ -170,6 +170,7 @@ regGroup = parser.add_argument_group("Re
 modes = clientsGroup.add_mutually_exclusive_group()
 modes.add_argument('-l','--listen', help='Listen to messages', action="store_true", required=False, default=False)
 modes.add_argument('-s','--send', help="Send message to phone number and close connection. Phone is full number including country code, without '+' or '00'", action="store",  nargs=2, metavar=('<phone>','<message>'), required=False)
+modes.add_argument('-p','--picture', help='Get Profile Picture by ID', action="store", metavar=('<phone>'), required=False)
 modes.add_argument('-i','--interactive', help="Start an interactive conversation with a contact. Phone is full number including country code, without '+' or '00'", action="store", metavar='<phone>', required=False)
 modes.add_argument('-b','--broadcast', help="Broadcast message to multiple recepients, comma seperated", action="store", nargs=2, metavar=('<jids>', '<message>'), required=False)
 
@@ -250,6 +251,10 @@ else:
 			message = args["send"][1]
 			wa = WhatsappEchoClient(phone, message, args['wait'])
 			wa.login(login, password)
+		elif args['picture']:
+			phone = args["picture"]
+			wa = WhatsappPictureClient(phone, args['wait'])
+			wa.login(login, password)
 		elif args['listen']:
 			wa = WhatsappListenerClient(args['keepalive'], args['autoack'])
 
Description: add the token map file, needed by new version.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/tokenmap.py
===================================================================
--- /dev/null
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/tokenmap.py
@@ -0,0 +1,70 @@
+class TokenDictionary:
+
+  def __init__(self):
+    self.dictionary = ["", "", "", "account", "ack", "action", "active", "add", "after", "all", "allow", "apple",
+        "auth", "author", "available", "bad-protocol", "bad-request", "before", "body", "broadcast",
+        "cancel", "category", "challenge", "chat", "clean", "code", "composing", "config", "contacts",
+        "count", "create", "creation", "debug", "default", "delete", "delivery", "delta", "deny",
+        "digest", "dirty", "duplicate", "elapsed", "enable", "encoding", "error", "event",
+        "expiration", "expired", "fail", "failure", "false", "favorites", "feature", "features",
+        "feature-not-implemented", "field", "first", "free", "from", "g.us", "get", "google", "group",
+        "groups", "http://etherx.jabber.org/streams";, "http://jabber.org/protocol/chatstates";, "ib",
+        "id", "image", "img", "index", "internal-server-error", "ip", "iq", "item-not-found", "item",
+        "jabber:iq:last", "jabber:iq:privacy", "jabber:x:event", "jid", "kind", "last", "leave",
+        "list", "max", "mechanism", "media", "message_acks", "message", "method", "microsoft",
+        "missing", "modify", "mute", "name", "nokia", "none", "not-acceptable", "not-allowed",
+        "not-authorized", "notification", "notify", "off", "offline", "order", "owner", "owning",
+        "p_o", "p_t", "paid", "participant", "participants", "participating", "paused", "picture",
+        "pin", "ping", "platform", "port", "presence", "preview", "probe", "prop", "props", "query",
+        "raw", "read", "reason", "receipt", "received", "relay", "remote-server-timeout", "remove",
+        "request", "required", "resource-constraint", "resource", "response", "result", "retry",
+        "rim", "s_o", "s_t", "s.us", "s.whatsapp.net", "seconds", "server-error", "server",
+        "service-unavailable", "set", "show", "silent", "stat", "status", "stream:error",
+        "stream:features", "subject", "subscribe", "success", "sync", "t", "text", "timeout",
+        "timestamp", "to", "true", "type", "unavailable", "unsubscribe", "uri", "url",
+        "urn:ietf:params:xml:ns:xmpp-sasl", "urn:ietf:params:xml:ns:xmpp-stanzas",
+        "urn:ietf:params:xml:ns:xmpp-streams", "urn:xmpp:ping", "urn:xmpp:receipts",
+        "urn:xmpp:whatsapp:account", "urn:xmpp:whatsapp:dirty", "urn:xmpp:whatsapp:mms",
+        "urn:xmpp:whatsapp:push", "urn:xmpp:whatsapp", "user", "user-not-found", "value",
+        "version", "w:g", "w:p:r", "w:p", "w:profile:picture", "w", "wait", "WAUTH-2",
+        "x", "xmlns:stream", "xmlns", "1", "chatstate", "crypto", "enc", "class", "off_cnt",
+        "w:g2", "promote", "demote", "creator", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
+		"Bell.caf", "Boing.caf", "Glass.caf", "Harp.caf", "TimePassing.caf", "Tri-tone.caf",
+        "Xylophone.caf", "background", "backoff", "chunked", "context", "full", "in", "interactive",
+        "out", "registration", "sid", "urn:xmpp:whatsapp:sync", "flt", "s16", "u8", "adpcm",
+        "amrnb", "amrwb", "mp3", "pcm", "qcelp", "wma", "h263", "h264", "jpeg", "mpeg4", "wmv",
+        "audio/3gpp", "audio/aac", "audio/amr", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/qcelp",
+        "audio/wav", "audio/webm", "audio/x-caf", "audio/x-ms-wma", "image/gif", "image/jpeg",
+        "image/png", "video/3gpp", "video/avi", "video/mp4", "video/mpeg", "video/quicktime",
+        "video/x-flv", "video/x-ms-asf", "302", "400", "401", "402", "403", "404", "405", "406",
+        "407", "409", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt",
+        "asampfreq", "audio", "bb_db", "clear", "conflict", "conn_no_nna", "cost", "currency",
+        "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "google_play", "hash",
+        "height", "invalid", "jid-malformed", "latitude", "lc", "lg", "live", "location", "log",
+        "longitude", "max_groups", "max_participants", "max_subject", "mimetype", "mode",
+        "napi_version", "normalize", "orighash", "origin", "passive", "password", "played",
+        "policy-violation", "pop_mean_time", "pop_plus_minus", "price", "pricing", "redeem",
+        "Replaced by new connection", "resume", "signature", "size", "sound", "source",
+        "system-shutdown", "username", "vbitrate", "vcard", "vcodec", "video", "width",
+        "xml-not-well-formed", "checkmarks", "image_max_edge", "image_max_kbytes", "image_quality",
+        "ka", "ka_grow", "ka_shrink", "newmedia", "library", "caption", "forward", "c0", "c1", "c2",
+        "c3", "clock_skew", "cts", "k0", "k1", "login_rtt", "m_id", "nna_msg_rtt", "nna_no_off_count",
+        "nna_offline_ratio", "nna_push_rtt", "no_nna_con_count", "off_msg_rtt", "on_msg_rtt",
+        "stat_name", "sts", "suspect_conn", "lists", "self", "qr", "web", "w:b", "recipient",
+        "w:stats", "forbidden", "aurora.m4r", "bamboo.m4r", "chord.m4r", "circles.m4r", "complete.m4r",
+        "hello.m4r", "input.m4r", "keys.m4r", "note.m4r", "popcorn.m4r", "pulse.m4r", "synth.m4r",
+        "filehash"]
+
+  def getToken(self, index):
+    if index >= 0 and index < len(self.dictionary):
+        return self.dictionary[index]
+
+    raise Exception("Token index does not exist: %s" % index)
+
+  def getIndex(self, token):
+    for i in range(0, len(self.dictionary)):
+      if token == self.dictionary[i]:
+        return i
+
+    raise KeyError("No index for given token %s" % token)
Description: update the protocoltreenode file.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/protocoltreenode.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/ConnectionIO/protocoltreenode.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/protocoltreenode.py
@@ -33,21 +33,21 @@ class ProtocolTreeNode():
 		self.children = children;
 		self.data = data
 		
-	def toString(self):
+	def toString(self, depth = 0):
 		try:
-			out = "<"+self.tag;
+			out = (" " * depth) + "<"+self.tag;
 			if self.attributes is not None:
 				for key,val in self.attributes.items():
 					out+= " "+key+'="'+val+'"'
 			out+= ">\n";
 			if self.data is not None:
-				out += self.data;
+				out += (" " * (depth + 4)) + self.data.encode("hex") + "\n"
 			
 			if self.children is not None:
 				for c in self.children:
-					out+=c.toString();
+					out+=c.toString(depth + 4);
 			#print sel
-			out+= "</"+self.tag+">\n"
+			out+= (" " * depth) + "</"+self.tag+">\n"
 			return out
 		except TypeError:
 			print("ignored toString call, probably encountered byte")
Description: add a missing variable.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Examples/CmdClient.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Examples/CmdClient.py
+++ yowsup-0.0~git20140314.938cf1/src/Examples/CmdClient.py
@@ -24,6 +24,7 @@ import time, datetime, sys
 
 if sys.version_info >= (3, 0):
 	raw_input = input
+	long = int
 
 class WhatsappCmdClient:
 	
Description: update the constants used to simulate the local mobile phone.
             This data is used in SSL actions.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/Common/constants.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/Common/constants.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/Common/constants.py
@@ -53,10 +53,10 @@ class Constants:
 	v="0.82"
 
 	tokenData = {
-		"v": "2.12.15",
-		"r": "S40-2.12.15",
-		"u": "WhatsApp/2.12.15 S40Version/14.26 Device/Nokia302",
-		"t": "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1391039105258{phone}",
+		"v": "2.12.49",
+		"r": "S40-2.12.49",
+		"u": "WhatsApp/2.12.49 S40Version/14.26 Device/Nokia302",
+		"t": "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1413401214298{phone}",
 		"d": "Nokia302"
 	}
 
Description: update the bintreenode file.
Author: Tarek Galal <[email protected]>
Reviewed-by: Joao Eriberto Mota Filho <[email protected]>
Origin: https://github.com/tgalal/yowsup/tree/legacy
Last-Update: 2014-12-02
Index: yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/bintreenode.py
===================================================================
--- yowsup-0.0~git20140314.938cf1.orig/src/Yowsup/ConnectionIO/bintreenode.py
+++ yowsup-0.0~git20140314.938cf1/src/Yowsup/ConnectionIO/bintreenode.py
@@ -22,7 +22,7 @@ OR THE USE OR OTHER DEALINGS IN THE SOFT
 from Yowsup.Common.debugger import Debugger
 from Yowsup.Common.datastructures import ByteArray
 from Yowsup.Common.constants import Constants
-
+from .tokenmap import TokenDictionary
 
 from .protocoltreenode import ProtocolTreeNode
 from .ioexceptions import InvalidReadException
@@ -35,30 +35,26 @@ class BinTreeNodeReader():
         self.inputKey = None
         
         self._d('Reader init');
-        self.tokenMap = Constants.dictionary;
         self.rawIn = inputstream;
         self.inn = ByteArray();
         self.buf = []#bytearray(1024);
         self.bufSize = 0;
         self.readSize = 1;
-        
+        self.tokenDictionary = TokenDictionary()
 
     def readStanza(self):
 
-        num = self.readInt8(self.rawIn)
-        stanzaSize = self.readInt16(self.rawIn,1);
+        firstByte = self.readInt8(self.rawIn)
+        stanzaFlag = (firstByte & 0xF0) >> 4
+        stanzaSize = self.readInt16(self.rawIn) | ((firstByte & 0x0F) << 16)
+
+        isEncrypted = ((stanzaFlag & 8) != 0)
 
-        header = (num << 16) + stanzaSize#self.readInt24(self.rawIn)
-        
-        flags = (header >> 20);
-        #stanzaSize =  ((header & 0xF0000) >> 16) | ((header & 0xFF00) >> 8) | (header & 0xFF);
-        isEncrypted = ((flags & 8) != 0)
-        
         self.fillBuffer(stanzaSize);
         
         if self.inputKey is not None and isEncrypted:
             #self.inn.buf = bytearray(self.inn.buf)
-            self.inn.buf = self.inputKey.decodeMessage(self.inn.buf, 0, 4, len(self.inn.buf)-4)[4:]
+            self.inn.buf = self.inputKey.decodeMessage(self.inn.buf, 0, 4, len(self.inn.buf)-4)
 
     def streamStart(self):
 
@@ -68,7 +64,12 @@ class BinTreeNodeReader():
         size = self.readListSize(tag);
         tag = self.inn.read();
         if tag != 1:
-            raise Exception("expecting STREAM_START in streamStart");
+            if tag == 236:
+                tag = self.inn.read + 237
+
+            token = self.tokenDictionary.getToken(tag)
+
+            raise Exception("expecting STREAM_START in streamStart, instead got token: %s" % token);
         attribCount = (size - 2 + size % 2) / 2;
         self.readAttributes(attribCount);
     
@@ -119,22 +120,15 @@ class BinTreeNodeReader():
             attribs[key]=value;
         return attribs;
     
-    def getToken(self,token):
-        if (token >= 0 and token < len(self.tokenMap)):
-            ret = self.tokenMap[token];
-        else:
-            raise Exception("invalid token/length in getToken %i "%token);
-        
-        return ret;
-        
-    
     def readString(self,token):
         
         if token == -1:
             raise Exception("-1 token in readString");
         
-        if token > 4 and token < 245:
-            return self.getToken(token);
+        if token > 2 and token < 245:
+            if token == 236:
+              token = 237 + self.inn.read()
+            return self.tokenDictionary.getToken(token)
         
         if token == 0:
             return None;
@@ -158,7 +152,7 @@ class BinTreeNodeReader():
             
         if token == 254:
             token = self.inn.read();
-            return self.getToken(245+token);
+            return self.tokenMapper.getToken(245+token);
         if token == 250:
             user = self.readString(self.inn.read());
             server = self.readString(self.inn.read());
@@ -254,36 +248,25 @@ class BinTreeNodeWriter():
     TOKEN_8 = 254;
     #socket out; #FunXMPP.WAByteArrayOutputStream
     #socket realOut;
-    tokenMap={}
     
     def __init__(self,o):
         Debugger.attach(self)
 
         self.outputKey = None
 
-        dictionary = Constants.dictionary
         self.realOut = o;
         #self.out = o;
         self.tokenMap = {}
         self.out = ByteArray();
-        #this.tokenMap = new Hashtable(dictionary.length);
-        for i in range(0,len(dictionary)):
-            if dictionary[i] is not None:
-                self.tokenMap[dictionary[i]]=i
-        
-        #Utilities.debug(self.tokenMap);
-        '''
-        for (int i = 0; i < dictionary.length; i++)
-            if (dictionary[i] != null)
-                this.tokenMap.put(dictionary[i], new Integer(i));
-        '''
+
+        self.tokenDictionary = TokenDictionary()
 
     def streamStart(self,domain,resource):
         
         self.realOut.write(87);
         self.realOut.write(65);
         self.realOut.write(1);
-        self.realOut.write(2);
+        self.realOut.write(4);
 
         streamOpenAttributes  = {"to":domain,"resource":resource};
         self.writeListStart(len(streamOpenAttributes )*2+1);
@@ -299,7 +282,7 @@ class BinTreeNodeWriter():
             self.out.write(0);
         else:
             self._d("Outgoing");
-            self._d("\n %s" % node.toString());
+            self._d("\n%s"%node.toString());
             self.writeInternal(node);
 
         self.flushBuffer(needsFlush);
@@ -309,21 +292,17 @@ class BinTreeNodeWriter():
     def processBuffer(self):
         buf = self.out.getBuffer()
 
-        prep = [0,0,0]
-        prep.extend(buf)
-
         length1 = len(self.out.buf)
-        num = 0
 
         if self.outputKey is not None:
-            num = 1
-            prep.extend([0,0,0,0])
             length1 += 4
 
             #prep = bytearray(prep)
-            res = self.outputKey.encodeMessage(prep, len(prep) - 4 , 3, len(prep)-4-3)
+            buf = self.outputKey.encodeMessage(buf, len(buf), 0, len(buf))
 
-            res[0] = ((num << 4) | (length1 & 16711680) >> 16) % 256
+            res = [0,0,0]
+            res.extend(buf)
+            res[0] = ((8 << 4) | (length1 & 16711680) >> 16) % 256
             res[1] = ((length1 & 65280) >> 8) % 256
             res[2] = (length1 & 255) % 256
 
@@ -331,7 +310,9 @@ class BinTreeNodeWriter():
 
             return
         else:
-            prep[0] = ((num << 4) | (length1 & 16711680) >> 16) % 256
+            prep = [0,0,0]
+            prep.extend(buf)
+            prep[0] = ((0 << 4) | (length1 & 16711680) >> 16) % 256
             prep[1] = ((length1 & 65280) >> 8) % 256
             prep[2] = (length1 & 255) % 256
             self.out.buf = prep
@@ -437,8 +418,12 @@ class BinTreeNodeWriter():
     
     def writeString(self,tag):
         try:
-            key = self.tokenMap[tag];
-            self.writeToken(key);
+            key = self.tokenDictionary.getIndex(tag);
+            if key > 235:
+                self.writeToken(236);
+                self.writeToken(key - 237);
+            else:
+                self.writeToken(key);
         except KeyError:
             try:
 

--- End Message ---
--- Begin Message ---
Source: yowsup
Source-Version: 2.2.78-1

We believe that the bug you reported is fixed in the latest version of
yowsup, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Joao Eriberto Mota Filho <[email protected]> (supplier of updated yowsup 
package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.8
Date: Wed, 29 Apr 2015 14:48:27 -0300
Source: yowsup
Binary: python-yowsup yowsup-cli
Architecture: source all
Version: 2.2.78-1
Distribution: unstable
Urgency: medium
Maintainer: Joao Eriberto Mota Filho <[email protected]>
Changed-By: Joao Eriberto Mota Filho <[email protected]>
Description:
 python-yowsup - library to implement a WhatsApp client
 yowsup-cli - command line tool that acts as WhatsApp client
Closes: 773005 775835
Changes:
 yowsup (2.2.78-1) unstable; urgency=medium
 .
   * New upstream release. (Closes: #773005, #775835)
   * debian/clean: removed. The upstream fixed the source code.
   * debian/control:
       - Added python-axolotl, python-dateutil, python-pil and python-setuptools
         to Build-Depends field.
       - Removed python-dateutil from Depends field in yowsup-cli binary.
       - Updated the Vcs-Browser field.
   * debian/copyright:
       - Changed the main license because the upstream is using GPL-3 now.
       - Updated the copyright years for packaging and upstream source code.
   * yowsup-cli.install: useless now. Removed.
   * yowsup-cli.examples: useless now. Removed.
   * debian/man/:
       - Renamed the directory to manpage.
       - Renamed file header.txt to yowsup-cli.header.
       - Using genallman.sh instead of genman.sh.
       - Updated all manpage (the upstream did several changes in yowsup-cli).
   * debian/patches/:
       - Added a patch (fix-ssl) to avoid a SSL certificate verify failed on
         Python 2.7.9. Thanks a lot to Tarek Galal (upstream).
       - Removed some patches unnecessary for new upstream version:
          ~ add-missing-variable
          ~ add-PictureClient
          ~ add-the-tokenmap
          ~ add-whatsapp-auth-v2
          ~ update-bintreenode
          ~ update-connection-manager
          ~ update-protocoltreenode
          ~ update-the-interface-messages
          ~ update-user-agent
   * debian/README.Debian: updated.
   * debian/rules: using pybuild now.
   * debian/yowsup-cli.dirs: created to provide /usr/bin.
   * debian/yowsup-cli.manpages: updated.
Checksums-Sha1:
 7870a64c8a15894928562b1249ac41e3f9fd5528 1969 yowsup_2.2.78-1.dsc
 e13f1d505e02201cf2e99da7be55c3c4fcba8a2c 92956 yowsup_2.2.78.orig.tar.gz
 d9624c137074ab98d8474176fc2c0512cc40c37e 10704 yowsup_2.2.78-1.debian.tar.xz
 d43ab36b081f49de38cb01809c3d4da22bcbcbcc 73222 python-yowsup_2.2.78-1_all.deb
 3b2008b2b67f83a7fee4b0e3284641290ad6a356 10136 yowsup-cli_2.2.78-1_all.deb
Checksums-Sha256:
 fe9e190f06c9ee315003423fdb7912887e55fbb1400804e5e41bef71afd8591f 1969 
yowsup_2.2.78-1.dsc
 5affe877fee3ea0d4a9cee0e7223c55d570f873802ea796036ede5d0672b43f6 92956 
yowsup_2.2.78.orig.tar.gz
 428c433b93c39ac01c4c476cd844e87264ee70d16702369fd2f33232febcce85 10704 
yowsup_2.2.78-1.debian.tar.xz
 3967ffe70be76bfbb6d0d80c40e3b03f211330f624d0c2a8f33d66fbff2b996e 73222 
python-yowsup_2.2.78-1_all.deb
 5eef4dc0395f4ba5c113d41f7b09455ed6062ed0e1c4e46c122c9c1f71accf9d 10136 
yowsup-cli_2.2.78-1_all.deb
Files:
 0314e4d39acec5e8405bb4636e7d17c6 1969 python optional yowsup_2.2.78-1.dsc
 63a22f344ff1402dcf99f79e229fe65c 92956 python optional 
yowsup_2.2.78.orig.tar.gz
 75365dcf38804361713e6a73c58bf3ea 10704 python optional 
yowsup_2.2.78-1.debian.tar.xz
 1b911b0b57a2ab34bd22a605e6addd01 73222 python optional 
python-yowsup_2.2.78-1_all.deb
 0f6dd8dbf684d59eb9e80e5f118ff2a3 10136 net optional yowsup-cli_2.2.78-1_all.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJVQpr0AAoJEN5juccE6+nvXDsQAJgZCUkWdonKpHdJO7uJhbpG
kb9KlZ/sxJPKkp4gd7AvNFOtgWP5wX1/7mdAfCdwAlYc8/AL1Lf+8JKg2Ft28ytF
Gzr1ycS85GDgBO8Sz73F7mOX65kNSoAC8wEPSO91rk5Vpb50SImxgG6XlFz5jHJM
GIieUsi8mqPyreNuWv1moF6dPw1VS0OmoQlLdqFvTeg3/mE6SSs7iU3JPCvyo3jh
budouIY7kR8WhFO9RjIzuUqeGbS9gZgPcczprFBwN65CMCNlZwS+4Qrn04clw5jZ
jLycFCC9N0gXm6eC+MHYfye1fUeKf9mulDJxS2J2aybxeGtfusqZ64UlxZIlfsAA
6hcZxJO5fqrKEO3n20pqaRwXLIHETONn0b2au1H434EEX0XHlqbSO4QStS9dSlvj
nNk29MzqogJZLHMq421Ru9FYBIxC8PuKSgoLiTGwq06ZdhYd5tpR+vPsNeLQujvm
Vr3megHhJJGS7QTBB9IOsEvz1hyYVyYJrh4t0TYvZCdkcNzUuCDIUChcalvTnG53
ykJ1I6nIKkUXq84RSL5CeBgGR17mirpQt/hFQoBw/2I9wR9Q9PzI3Qaf4mLop4lI
LVr7wwH0rWBir09NcviUdI8Cw6EXRZ0PuimDkTOeWs4cbt07le/h8aofrnqTlU8r
c1a9Gbo91+lB4B844IfG
=QmvI
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to