Skip to content

Commit

Permalink
Merge branch 'release/2.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
tgalal committed Sep 6, 2015
2 parents 77330b8 + 5a2f794 commit ead1923
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 109 deletions.
5 changes: 4 additions & 1 deletion README.md
Expand Up @@ -2,7 +2,10 @@

<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9KKEUVYEY6BN" target="_blank"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" /></a>

## Updates (August 01, 2015)
## Updates (September 07, 2015)
Yowsup v2.4 is out, See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.4)

### Updates (August 01, 2015)
Yowsup v2.3.185 is out, contains fixes in axolotl integration. See [release notes](https://github.com/tgalal/yowsup/releases/tag/v2.3.185)

### Updates (July 27, 2015)
Expand Down
17 changes: 6 additions & 11 deletions yowsup-cli
@@ -1,5 +1,5 @@
#!/usr/bin/env python
__version__ = "2.0.12"
__version__ = "2.0.13"
__author__ = "Tarek Galal"

import sys, argparse, yowsup, logging
Expand Down Expand Up @@ -205,8 +205,7 @@ class DemosArgParser(YowArgParser):
credentialsOpts.add_argument("-c", "--config", action="store",
help = "Path to config file containing authentication info. For more info about config format use --help-config")

configGroup.add_argument("-m", "--moxie", action="store_true", help="Enable experimental support for the"
" new WhatsApp encryption")
configGroup.add_argument("-M", "--unmoxie", action="store_true", help="Disable E2E Encryption")

cmdopts = self.add_argument_group("Command line interface demo")
cmdopts.add_argument('-y', '--yowsup', action = "store_true", help = "Start the Yowsup command line client")
Expand All @@ -224,9 +223,6 @@ class DemosArgParser(YowArgParser):
def process(self):
super(DemosArgParser, self).process()

if self.args["moxie"]:
logger.warning("--moxie/-m is deprecated and will be removed soon as e2e encryption is now almost mandatory.")

if self.args["yowsup"]:
self.startCmdline()
elif self.args["echo"]:
Expand Down Expand Up @@ -255,7 +251,7 @@ class DemosArgParser(YowArgParser):
if not credentials:
print("Error: You must specify a configuration method")
sys.exit(1)
stack = cli.YowsupCliStack(credentials, self.args["moxie"])
stack = cli.YowsupCliStack(credentials, not self.args["unmoxie"])
stack.start()

def startEcho(self):
Expand All @@ -265,7 +261,7 @@ class DemosArgParser(YowArgParser):
print("Error: You must specify a configuration method")
sys.exit(1)
try:
stack = echoclient.YowsupEchoStack(credentials, self.args["moxie"])
stack = echoclient.YowsupEchoStack(credentials, not self.args["unmoxie"])
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
Expand All @@ -280,7 +276,7 @@ class DemosArgParser(YowArgParser):

try:
stack = sendclient.YowsupSendStack(credentials, [([self.args["send"][0], self.args["send"][1]])],
self.args["moxie"])
not self.args["unmoxie"])
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
Expand All @@ -293,7 +289,7 @@ class DemosArgParser(YowArgParser):
print("Error: You must specify a configuration method")
sys.exit(1)
try:
stack = contacts.YowsupSyncStack(credentials,self.args["sync"].split(','),self.args["moxie"])
stack = contacts.YowsupSyncStack(credentials,self.args["sync"].split(','), not self.args["unmoxie"])
stack.start()
except KeyboardInterrupt:
print("\nYowsdown")
Expand Down Expand Up @@ -326,4 +322,3 @@ if __name__ == "__main__":
parser = modeDict[mode]()
if not parser.process():
parser.print_help()

2 changes: 1 addition & 1 deletion yowsup/__init__.py
@@ -1,2 +1,2 @@
__version__ = "2.3.185"
__version__ = "2.4"
__author__ = "Tarek Galal"
21 changes: 11 additions & 10 deletions yowsup/demos/cli/layer.py
Expand Up @@ -48,6 +48,7 @@ def __init__(self):
self.username = None
self.sendReceipts = True
self.disconnectAction = self.__class__.DISCONNECT_ACTION_PROMPT
self.credentials = None

#add aliases to make it user to use commands. for example you can then do:
# /message send foobar "HI"
Expand Down Expand Up @@ -77,6 +78,9 @@ def normalizeJid(self, number):

return "%s@s.whatsapp.net" % number

def setCredentials(self, username, password):
self.getLayerInterface(YowAuthenticationProtocolLayer).setCredentials(username, password)

def onEvent(self, layerEvent):
if layerEvent.getName() == self.__class__.EVENT_START:
self.startInput()
Expand Down Expand Up @@ -406,23 +410,20 @@ def contacts_sync(self, contacts):
@clicmd("Disconnect")
def disconnect(self):
if self.assertConnected():

self.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT))

@clicmd("Quick login")
def L(self):
return self.login(*self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS))

@clicmd("Login to WhatsApp", 0)
def login(self, username, b64password):

if self.connected:
return self.output("Already connected, disconnect first")
self.getLayerInterface(YowNetworkLayer).connect()
return True

self.getStack().setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, (username, b64password))
connectEvent = YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT)
self.broadcastEvent(connectEvent)
return True #prompt will wait until notified

@clicmd("Login to WhatsApp", 0)
def login(self, username, b64password):
self.setCredentials(username, b64password)
return self.L()

######## receive #########

Expand Down
8 changes: 4 additions & 4 deletions yowsup/demos/cli/stack.py
@@ -1,9 +1,8 @@
from yowsup.stacks import YowStack, YowStackBuilder
from yowsup.stacks import YowStackBuilder
from .layer import YowsupCliLayer
from yowsup.layers.auth import AuthError
from yowsup.layers import YowLayerEvent
from yowsup import env
from yowsup.env import S40YowsupEnv
from yowsup.layers.auth import YowAuthenticationProtocolLayer
import sys

class YowsupCliStack(object):
Expand All @@ -15,6 +14,7 @@ def __init__(self, credentials, encryptionEnabled = True):
.push(YowsupCliLayer)\
.build()

# self.stack.setCredentials(credentials)
self.stack.setCredentials(credentials)

def start(self):
Expand All @@ -27,4 +27,4 @@ def start(self):
print("Auth Error, reason %s" % e)
except KeyboardInterrupt:
print("\nYowsdown")
sys.exit(0)
sys.exit(0)
5 changes: 2 additions & 3 deletions yowsup/env/env_s40.py
Expand Up @@ -2,11 +2,11 @@
import base64
import hashlib
class S40YowsupEnv(YowsupEnv):
_VERSION = "2.12.89"
_VERSION = "2.12.96"
_OS_NAME= "S40"
_OS_VERSION = "14.26"
_DEVICE_NAME = "Nokia302"
_TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1435688727801{phone}"
_TOKEN_STRING = "PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1439921717185{phone}"
_AXOLOTL = True

def getVersion(self):
Expand Down Expand Up @@ -34,4 +34,3 @@ def getUserAgent(self):
OS_VERSION = self.getOSVersion(),
DEVICE_NAME = self.getDeviceName()
)

13 changes: 13 additions & 0 deletions yowsup/layers/__init__.py
Expand Up @@ -33,6 +33,10 @@ class YowLayer(object):

def __init__(self):
self.setLayers(None, None)
self.interface = None

def getLayerInterface(self, YowLayerClass = None):
return self.interface if YowLayerClass is None else self.__stack.getLayerInterface(YowLayerClass)

def setStack(self, stack):
self.__stack = stack
Expand Down Expand Up @@ -149,6 +153,11 @@ def __init__(self, sublayers = None):
s.emitEvent = self.subEmitEvent


def getLayerInterface(self, YowLayerClass):
for s in self.sublayers:
if s.__class__ == YowLayerClass:
return s

def setStack(self, stack):
super(YowParallelLayer, self).setStack(stack)
for s in self.sublayers:
Expand Down Expand Up @@ -182,6 +191,10 @@ def onEvent(self, yowLayerEvent):
def __str__(self):
return " - ".join([l.__str__() for l in self.sublayers])

class YowLayerInterface(object):
def __init__(self, layer):
self._layer = layer


class YowLayerTest(unittest.TestCase):
def __init__(self, *args):
Expand Down
30 changes: 20 additions & 10 deletions yowsup/layers/auth/layer_authentication.py
@@ -1,11 +1,12 @@
from yowsup.layers import YowLayer, YowLayerEvent, YowProtocolLayer
from yowsup.layers import YowLayerEvent, YowProtocolLayer
from .keystream import KeyStream
from yowsup.common.tools import TimeTools
from .layer_crypt import YowCryptLayer
from yowsup.layers.network import YowNetworkLayer
from .autherror import AuthError
from .protocolentities import *
from yowsup.common.tools import StorageTools
from .layer_interface_authentication import YowAuthenticationProtocolLayerInterface
import base64
class YowAuthenticationProtocolLayer(YowProtocolLayer):
EVENT_LOGIN = "org.openwhatsapp.yowsup.event.auth.login"
Expand All @@ -22,29 +23,38 @@ def __init__(self):
"stream:error": (self.handleStreamError, None),
}
super(YowAuthenticationProtocolLayer, self).__init__(handleMap)
self.credentials = None
self.interface = YowAuthenticationProtocolLayerInterface(self)
self.credentials = None #left for backwards-compat
self._credentials = None #new style set

def __str__(self):
return "Authentication Layer"

def __getCredentials(self):
u, pb64 = self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS)
def __getCredentials(self, credentials = None):
u, pb64 = credentials or self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS)
if type(pb64) is str:
pb64 = pb64.encode()
password = base64.b64decode(pb64)
return (u, bytearray(password))

def setCredentials(self, credentials):
self.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS, credentials) #keep for now
self._credentials = self.__getCredentials(credentials)

def getUsername(self, full = False):
if self._credentials:
return self._credentials[0] if not full else ("%s@s.whatsapp.net" % self._credentials[0])
else:
prop = self.getProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS)
return prop[0] if prop else None

def onEvent(self, event):
if event.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED:
self.login()
elif event.getName() == YowNetworkLayer.EVENT_STATE_CONNECT:
self.credentials = self.__getCredentials()
if not self.credentials:
raise AuthError("Auth stopped connection signal as no credentials have been set")

## general methods
def login(self):

self.credentials = self._credentials or self.__getCredentials()
self._sendFeatures()
self._sendAuth()

Expand Down Expand Up @@ -102,7 +112,7 @@ def _sendResponse(self,nonce):
responseEntity = ResponseProtocolEntity(authBlob)

#to prevent enr whole response
self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, None)))
self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, None)))
self.entityToLower(responseEntity)
self.broadcastEvent(YowLayerEvent(YowCryptLayer.EVENT_KEYS_READY, keys = (inputKey, outputKey)))
#YowCryptLayer.setProp("outputKey", outputKey)
Expand Down
2 changes: 1 addition & 1 deletion yowsup/layers/auth/layer_crypt.py
Expand Up @@ -13,7 +13,7 @@ def __init__(self):
self.keys = (None,None)

def onEvent(self, yowLayerEvent):
if yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_CONNECT:
if yowLayerEvent.getName() == YowNetworkLayer.EVENT_STATE_CONNECTED:
self.keys = (None,None)
elif yowLayerEvent.getName() == YowCryptLayer.EVENT_KEYS_READY:
self.keys = yowLayerEvent.getArg("keys")
Expand Down
8 changes: 8 additions & 0 deletions yowsup/layers/auth/layer_interface_authentication.py
@@ -0,0 +1,8 @@
from yowsup.layers import YowLayerInterface

class YowAuthenticationProtocolLayerInterface(YowLayerInterface):
def setCredentials(self, phone, password):
self._layer.setCredentials(phone, password)

def getUsername(self, full = False):
return self._layer.getUsername(full)

0 comments on commit ead1923

Please sign in to comment.