Guest User

mydiff

a guest
Aug 18th, 2017
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.83 KB | None | 0 0
  1. diff --git a/yowsup/common/tools.py b/yowsup/common/tools.py
  2. index 328fbb1..edf95c0 100644
  3. --- a/yowsup/common/tools.py
  4. +++ b/yowsup/common/tools.py
  5. @@ -46,7 +46,17 @@ class WATools:
  6. f.close()
  7. b64Hash = base64.b64encode(sha1.digest())
  8. return b64Hash if type(b64Hash) is str else b64Hash.decode()
  9. -
  10. +
  11. + @staticmethod
  12. + def getFileHashForUpload2(filePath):
  13. + sha1 = hashlib.sha256()
  14. + f = open(filePath, 'rb')
  15. + try:
  16. + hash = hashlib.sha256(f.read()).hexdigest()
  17. + finally:
  18. + f.close()
  19. + return hash
  20. +
  21. class StorageTools:
  22. @staticmethod
  23. def constructPath(*path):
  24. diff --git a/yowsup/demos/cli/layer.py b/yowsup/demos/cli/layer.py
  25. index e6b319d..c56fa6d 100644
  26. --- a/yowsup/demos/cli/layer.py
  27. +++ b/yowsup/demos/cli/layer.py
  28. @@ -22,7 +22,13 @@ from yowsup.layers.protocol_profiles.protocolentities import *
  29. from yowsup.common.tools import Jid
  30. from yowsup.common.optionalmodules import PILOptionalModule, AxolotlOptionalModule
  31.  
  32. -logger = logging.getLogger(__name__)
  33. +logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s] %(message)s")
  34. +logger = logging.getLogger()
  35. +
  36. +fileHandler = logging.FileHandler("{0}/{1}.log".format("/tmp", "yowsup"))
  37. +fileHandler.setFormatter(logFormatter)
  38. +logger.addHandler(fileHandler)
  39. +
  40. class YowsupCliLayer(Cli, YowInterfaceLayer):
  41. PROP_RECEIPT_AUTO = "org.openwhatsapp.yowsup.prop.cli.autoreceipt"
  42. PROP_RECEIPT_KEEPALIVE = "org.openwhatsapp.yowsup.prop.cli.keepalive"
  43. @@ -404,7 +410,6 @@ class YowsupCliLayer(Cli, YowInterfaceLayer):
  44. errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity)
  45. self._sendIq(entity, successFn, errorFn)
  46.  
  47. - self._sendIq(entity, successFn, errorFn)
  48. @clicmd("Send typing state")
  49. def state_typing(self, jid):
  50. if self.assertConnected():
  51. @@ -508,7 +513,8 @@ class YowsupCliLayer(Cli, YowInterfaceLayer):
  52. output = self.__class__.MESSAGE_FORMAT.format(
  53. FROM = sender,
  54. TIME = formattedDate,
  55. - MESSAGE = messageOut.encode('latin-1').decode() if sys.version_info >= (3, 0) else messageOut,
  56. + MESSAGE = messageOut,
  57. + #MESSAGE = messageOut if sys.version_info >= (3, 0) else messageOut,
  58. MESSAGE_ID = message.getId()
  59. )
  60.  
  61. diff --git a/yowsup/layers/axolotl/layer_send.py b/yowsup/layers/axolotl/layer_send.py
  62. index bbeacd8..55296cf 100644
  63. --- a/yowsup/layers/axolotl/layer_send.py
  64. +++ b/yowsup/layers/axolotl/layer_send.py
  65. @@ -9,7 +9,7 @@ from axolotl.axolotladdress import AxolotlAddress
  66. from axolotl.protocol.whispermessage import WhisperMessage
  67. from axolotl.groups.senderkeyname import SenderKeyName
  68. from axolotl.groups.groupsessionbuilder import GroupSessionBuilder
  69. -
  70. +import binascii
  71. import logging
  72. from random import randint
  73.  
  74. @@ -42,21 +42,49 @@ class AxolotlSendLayer(AxolotlBaseLayer):
  75. def __str__(self):
  76. return "Axolotl Layer"
  77.  
  78. + def handleEncNode(self, node):
  79. + recipient_id = node["to"].split('@')[0]
  80. + v2 = node["to"]
  81. + if node.getChild("enc"): # media enc is only for v2 messsages
  82. + messageData = self.serializeToProtobuf(node)
  83. + # print (messageData)
  84. + if messageData:
  85. + sessionCipher = self.getSessionCipher(recipient_id)
  86. + messageData = messageData.SerializeToString() + self.getPadding()
  87. + ciphertext = sessionCipher.encrypt(messageData)
  88. + print ("masuk ENC")
  89. +
  90. + mediaType = node.getChild("enc")["type"] if node.getChild("enc") else None
  91. +
  92. + encEntity = EncryptedMessageProtocolEntity(
  93. + [
  94. + EncProtocolEntity(
  95. + EncProtocolEntity.TYPE_MSG if ciphertext.__class__ == WhisperMessage else EncProtocolEntity.TYPE_PKMSG,
  96. + 2 if v2 else 1,
  97. + ciphertext.serialize(), mediaType)],
  98. + "text" if not mediaType else "media",
  99. + _id=node["id"],
  100. + to=node["to"],
  101. + notify=node["notify"],
  102. + timestamp=node["timestamp"],
  103. + participant=node["participant"],
  104. + offline=node["offline"],
  105. + retry=node["retry"]
  106. + )
  107. + self.toLower(encEntity.toProtocolTreeNode())
  108. + else: # case of unserializable messages (audio, video) ?
  109. + print ("kok masuk sini?")
  110. + self.toLower(node)
  111. + else:
  112. + self.toLower(node)
  113.  
  114. +
  115. def send(self, node):
  116. if node.tag == "message" and node["to"] not in self.skipEncJids and not node.getChild("enc") and (not node.getChild("media") or node.getChild("media")["mediakey"]):
  117. self.processPlaintextNodeAndSend(node)
  118. - # elif node.tag == "iq" and node["xmlns"] == "w:m":
  119. - # mediaNode = node.getChild("media")
  120. - # if mediaNode and mediaNode["type"] == "image":
  121. - # iqNode = IqProtocolEntity.fromProtocolTreeNode(node).toProtocolTreeNode()
  122. - # iqNode.addChild(ProtocolTreeNode(
  123. - # "encr_media", {
  124. - # "type": mediaNode["type"],
  125. - # "hash": mediaNode["hash"]
  126. - # }
  127. - # ))
  128. - # self.toLower(iqNode)
  129. + elif node.getChild("enc"):
  130. + print ("Masuk enc")
  131. + self.handleEncNode(node)
  132. else:
  133. self.toLower(node)
  134.  
  135. @@ -229,8 +257,8 @@ class AxolotlSendLayer(AxolotlBaseLayer):
  136. def serializeToProtobuf(self, node, message = None):
  137. if node.getChild("body"):
  138. return self.serializeTextToProtobuf(node, message)
  139. - elif node.getChild("media"):
  140. - return self.serializeMediaToProtobuf(node.getChild("media"), message)
  141. + elif node.getChild("enc"):
  142. + return self.serializeMediaToProtobuf(node.getChild("enc"), message)
  143. else:
  144. raise ValueError("No body or media nodes found")
  145.  
  146. @@ -279,14 +307,20 @@ class AxolotlSendLayer(AxolotlBaseLayer):
  147. image_message.width = int(mediaNode["width"])
  148. image_message.height = int(mediaNode["height"])
  149. image_message.mime_type = mediaNode["mimetype"]
  150. - image_message.file_sha256 = mediaNode["filehash"]
  151. + image_message.file_sha256 = binascii.unhexlify(mediaNode["filehash"].encode())
  152. image_message.file_length = int(mediaNode["size"])
  153. + image_message.media_key = binascii.unhexlify(mediaNode["anu"])
  154. + #image_message.media_key = mediaNode["anu"]
  155. image_message.caption = mediaNode["caption"] or ""
  156. image_message.jpeg_thumbnail = mediaNode.getData()
  157. +
  158. + print ("mimeType: "+ mediaNode["mimetype"])
  159.  
  160. m.image_message.MergeFrom(image_message)
  161.  
  162. return m
  163. + # return
  164. + # return image_message
  165.  
  166. def serializeUrlToProtobuf(self, node, message = None):
  167. pass
  168. diff --git a/yowsup/layers/protocol_media/mediauploader.py b/yowsup/layers/protocol_media/mediauploader.py
  169. index da9b3d1..3eeeeba 100644
  170. --- a/yowsup/layers/protocol_media/mediauploader.py
  171. +++ b/yowsup/layers/protocol_media/mediauploader.py
  172. @@ -1,3 +1,11 @@
  173. +import base64
  174. +import hmac
  175. +from Crypto.Cipher import AES
  176. +import binascii
  177. +from axolotl.kdf.hkdfv3 import HKDFv3
  178. +from axolotl.sessioncipher import pad
  179. +from axolotl.util.byteutil import ByteUtil
  180. +
  181. from yowsup.common.http.warequest import WARequest
  182. from yowsup.common.http.waresponseparser import JSONResponseParser
  183. import socket, ssl, os, hashlib, sys
  184. @@ -36,6 +44,17 @@ class MediaUploader(WARequest, threading.Thread):
  185. else:
  186. self.run()
  187.  
  188. + def encryptImg(self,img, refkey):
  189. + img = pad(img)
  190. + derivative = HKDFv3().deriveSecrets(binascii.unhexlify(refkey),
  191. + binascii.unhexlify("576861747341707020496d616765204b657973"), 112)
  192. + parts = ByteUtil.split(derivative, 16, 32)
  193. + iv = parts[0]
  194. + cipherKey = parts[1]
  195. + cipher = AES.new(key=cipherKey, mode=AES.MODE_CBC, IV=iv)
  196. + imgEnc = cipher.encrypt(img)
  197. + return imgEnc[:-22]
  198. +
  199. def run(self):
  200.  
  201. sourcePath = self.sourcePath
  202. @@ -48,7 +67,24 @@ class MediaUploader(WARequest, threading.Thread):
  203. try:
  204. filename = os.path.basename(sourcePath)
  205. filetype = MimeTools.getMIME(filename)
  206. - filesize = os.path.getsize(sourcePath)
  207. + f = open(sourcePath, 'rb')
  208. + stream = f.read()
  209. + f.close()
  210. + refkey = binascii.hexlify(os.urandom(32))
  211. + print (refkey)
  212. + stream=self.encryptImg(stream,refkey)
  213. + fenc = open(filename+".enc", 'wb') # bahtiar
  214. + fenc.write(stream)
  215. + fenc.seek(0, 2)
  216. + filesize=fenc.tell()
  217. + fenc.close()
  218. +
  219. + sha1 = hashlib.sha256()
  220. + sha1.update(stream)
  221. + b64Hash = base64.b64encode(sha1.digest())
  222. + # b64Hash = base64.b64encode(sha1.hexdigest())
  223. +
  224. + # filesize = os.path.getsize(sourcePath)
  225.  
  226. self.sock.connect((self.url, self.port))
  227. ssl_sock = ssl.wrap_socket(self.sock)
  228. @@ -60,16 +96,25 @@ class MediaUploader(WARequest, threading.Thread):
  229. boundary = "zzXXzzYYzzXXzzQQ"#"-------" + m.hexdigest() #"zzXXzzYYzzXXzzQQ"
  230. contentLength = 0
  231.  
  232. + digTo = hmac.new("".encode("utf-8"), self.jid.replace("@s.whatsapp.net", "@c.us").encode("utf-8"),
  233. + hashlib.sha256).digest()[:20]
  234. + refTo = base64.b64encode(digTo).decode()
  235. + digFrom = hmac.new("".encode("utf-8"), self.accountJid.replace("@s.whatsapp.net", "@c.us").encode("utf-8"),
  236. + hashlib.sha256).digest()[:20]
  237. + refFrom = base64.b64encode(digFrom).decode()
  238. +
  239. hBAOS = "--" + boundary + "\r\n"
  240. - hBAOS += "Content-Disposition: form-data; name=\"to\"\r\n\r\n"
  241. - hBAOS += self.jid + "\r\n"
  242. + hBAOS += "Content-Disposition: form-data; name=\"hash\"\r\n\r\n"
  243. + hBAOS += b64Hash.decode() + "\r\n"
  244. +
  245. hBAOS += "--" + boundary + "\r\n"
  246. - hBAOS += "Content-Disposition: form-data; name=\"from\"\r\n\r\n"
  247. - hBAOS += self.accountJid.replace("@whatsapp.net","") + "\r\n"
  248. + hBAOS += "Content-Disposition: form-data; name=\"refs\"\r\n\r\n"
  249. + hBAOS += refFrom + "\r\n"
  250. + hBAOS += refTo + "\r\n"
  251.  
  252. hBAOS += "--" + boundary + "\r\n"
  253. - hBAOS += "Content-Disposition: form-data; name=\"file\"; filename=\"" + crypto + "\"\r\n"
  254. - hBAOS += "Content-Type: " + filetype + "\r\n\r\n"
  255. + hBAOS += "Content-Disposition: form-data; name=\"file\"; filename=\"" + "blob" + "\"\r\n"
  256. + hBAOS += "Content-Type: " + "application/octet-stream" + "\r\n\r\n"
  257.  
  258. fBAOS = "\r\n--" + boundary + "--\r\n"
  259.  
  260. @@ -88,9 +133,6 @@ class MediaUploader(WARequest, threading.Thread):
  261.  
  262. totalsent = 0
  263. buf = 1024
  264. - f = open(sourcePath, 'rb')
  265. - stream = f.read()
  266. - f.close()
  267. status = 0
  268. lastEmit = 0
  269.  
  270. @@ -118,6 +160,9 @@ class MediaUploader(WARequest, threading.Thread):
  271. if self.progressCallback:
  272. self.progressCallback(self.sourcePath, self.jid, uploadUrl, 100)
  273.  
  274. + # f = open("/tmp/data.log", 'wb') #bahtiar
  275. + # f.write("\n"+hBAOS.encode()+"\nRESPONSE:\n"+data)
  276. + # f.close()
  277.  
  278. lines = data.decode().splitlines()
  279.  
  280. @@ -135,7 +180,10 @@ class MediaUploader(WARequest, threading.Thread):
  281.  
  282. if result["url"] is not None:
  283. if self.successCallback:
  284. - self.successCallback(sourcePath, self.jid, result["url"])
  285. + # self.successCallback(sourcePath, self.jid, result["url"])
  286. + print (result)
  287. + result["mediaKey"]=refkey
  288. + self.successCallback(sourcePath, self.jid, result)
  289. else:
  290. logger.exception("uploadUrl: %s, result of uploading media has no url" % uploadUrl)
  291. if self.errorCallback:
  292. diff --git a/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py b/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py
  293. index bdd1e69..7a2a1a8 100644
  294. --- a/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py
  295. +++ b/yowsup/layers/protocol_media/protocolentities/iq_requestupload.py
  296. @@ -62,7 +62,7 @@ class RequestUploadIqProtocolEntity(IqProtocolEntity):
  297. }
  298. if self.origHash:
  299. attribs["orighash"] = self.origHash
  300. - mediaNode = ProtocolTreeNode("media", attribs)
  301. + mediaNode = ProtocolTreeNode("encr_media", attribs)
  302. node.addChild(mediaNode)
  303. return node
  304.  
  305. @@ -71,7 +71,7 @@ class RequestUploadIqProtocolEntity(IqProtocolEntity):
  306. assert node.getAttributeValue("type") == "set", "Expected set as iq type in request upload, got %s" % node.getAttributeValue("type")
  307. entity = IqProtocolEntity.fromProtocolTreeNode(node)
  308. entity.__class__ = RequestUploadIqProtocolEntity
  309. - mediaNode = node.getChild("media")
  310. + mediaNode = node.getChild("encr_media")
  311. entity.setRequestArguments(
  312. mediaNode.getAttributeValue("type"),
  313. mediaNode.getAttributeValue("hash"),
  314. diff --git a/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py b/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py
  315. index 45e7eb8..2ca58c4 100644
  316. --- a/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py
  317. +++ b/yowsup/layers/protocol_media/protocolentities/iq_requestupload_result.py
  318. @@ -35,7 +35,7 @@ class ResultRequestUploadIqProtocolEntity(ResultIqProtocolEntity):
  319. node = super(ResultRequestUploadIqProtocolEntity, self).toProtocolTreeNode()
  320.  
  321. if not self.isDuplicate():
  322. - mediaNode = ProtocolTreeNode("media", {"url": self.url})
  323. + mediaNode = ProtocolTreeNode("encr_media", {"url": self.url})
  324. if self.ip:
  325. mediaNode["ip"] = self.ip
  326.  
  327. @@ -51,7 +51,7 @@ class ResultRequestUploadIqProtocolEntity(ResultIqProtocolEntity):
  328. def fromProtocolTreeNode(node):
  329. entity= ResultIqProtocolEntity.fromProtocolTreeNode(node)
  330. entity.__class__ = ResultRequestUploadIqProtocolEntity
  331. - mediaNode = node.getChild("media")
  332. + mediaNode = node.getChild("encr_media")
  333. if mediaNode:
  334. entity.setUploadProps(mediaNode["url"], mediaNode["ip"], mediaNode["resume"])
  335. else:
  336. diff --git a/yowsup/layers/protocol_media/protocolentities/message_media.py b/yowsup/layers/protocol_media/protocolentities/message_media.py
  337. index b86c3d5..15499dc 100644
  338. --- a/yowsup/layers/protocol_media/protocolentities/message_media.py
  339. +++ b/yowsup/layers/protocol_media/protocolentities/message_media.py
  340. @@ -124,7 +124,7 @@ class MediaMessageProtocolEntity(MessageProtocolEntity):
  341.  
  342. def toProtocolTreeNode(self):
  343. node = super(MediaMessageProtocolEntity, self).toProtocolTreeNode()
  344. - mediaNode = ProtocolTreeNode("media", {"type": self.mediaType}, None, None)
  345. + mediaNode = ProtocolTreeNode("enc", {"type": self.mediaType}, None, None)
  346. node.addChild(mediaNode)
  347. if self.preview:
  348. mediaNode.setData(self.preview)
  349. diff --git a/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py b/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py
  350. index 2694fa3..5ef7310 100644
  351. --- a/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py
  352. +++ b/yowsup/layers/protocol_media/protocolentities/message_media_downloadable.py
  353. @@ -34,6 +34,8 @@ class DownloadableMediaMessageProtocolEntity(MediaMessageProtocolEntity):
  354. out += "IP: %s\n" % self.ip
  355. out += "File Size: %s\n" % self.size
  356. out += "File name: %s\n" % self.fileName
  357. + print (out)
  358. +
  359. return out
  360.  
  361. def getMediaSize(self):
  362. @@ -56,18 +58,22 @@ class DownloadableMediaMessageProtocolEntity(MediaMessageProtocolEntity):
  363.  
  364. def toProtocolTreeNode(self):
  365. node = super(DownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode()
  366. - mediaNode = node.getChild("media")
  367. + mediaNode = node.getChild("enc")
  368. mediaNode.setAttribute("mimetype", self.mimeType)
  369. mediaNode.setAttribute("filehash", self.fileHash)
  370. - mediaNode.setAttribute("url", self.url)
  371. + mediaNode.setAttribute("url", self.url["url"].encode())
  372. if self.ip:
  373. mediaNode.setAttribute("ip", self.ip)
  374. mediaNode.setAttribute("size", str(self.size))
  375. mediaNode.setAttribute("file", self.fileName)
  376. - if self.mediaKey:
  377. - mediaNode.setAttribute("mediakey", self.mediaKey)
  378. -
  379. + mediaNode.setAttribute("mediakey", self.url["mediaKey"])
  380. + mediaNode.setAttribute("anu", self.url["mediaKey"])
  381. + print ("MEDIAKEY:" + str(self.url["mediaKey"]))
  382. + print ("MIMETYPE:" + self.mimeType)
  383. + print ("FILEHASH:" + self.fileHash)
  384. + print ("FILEHASH:" + self.fileHash)
  385. return node
  386. + # return node
  387.  
  388. def isEncrypted(self):
  389. return self.mediaKey is not None
  390. @@ -93,8 +99,17 @@ class DownloadableMediaMessageProtocolEntity(MediaMessageProtocolEntity):
  391. url = builder.get("url")
  392. ip = builder.get("ip")
  393. assert url, "Url is required"
  394. - mimeType = builder.get("mimetype", MimeTools.getMIME(builder.getOriginalFilepath())[0])
  395. - filehash = WATools.getFileHashForUpload(builder.getFilepath())
  396. + mimeType = builder.get("mimetype", MimeTools.getMIME(builder.getOriginalFilepath()))
  397. + filehash = WATools.getFileHashForUpload2(builder.getFilepath())
  398. size = os.path.getsize(builder.getFilepath())
  399. fileName = os.path.basename(builder.getFilepath())
  400. return DownloadableMediaMessageProtocolEntity(builder.mediaType, mimeType, filehash, url, ip, size, fileName, to = builder.jid, preview = builder.get("preview"))
  401. +
  402. + @staticmethod
  403. + def fromFilePath(fpath, url, mediaType, ip, to, mimeType = None, preview = None, filehash = None, filesize = None):
  404. + mimeType = mimeType or MimeTools.getMIME(fpath)
  405. + filehash = filehash or WATools.getFileHashForUpload(fpath)
  406. + size = filesize or os.path.getsize(fpath)
  407. + fileName = os.path.basename(fpath)
  408. +
  409. + return DownloadableMediaMessageProtocolEntity(mediaType, mimeType, filehash, url, ip, size, fileName, to = to, preview = preview)
  410. diff --git a/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py b/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py
  411. index cc7b2e5..66e421c 100644
  412. --- a/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py
  413. +++ b/yowsup/layers/protocol_media/protocolentities/message_media_downloadable_image.py
  414. @@ -56,7 +56,8 @@ class ImageDownloadableMediaMessageProtocolEntity(DownloadableMediaMessageProtoc
  415.  
  416. def toProtocolTreeNode(self):
  417. node = super(ImageDownloadableMediaMessageProtocolEntity, self).toProtocolTreeNode()
  418. - mediaNode = node.getChild("media")
  419. + mediaNode = node.getChild("enc")
  420. + print ("MIME:" + self.mimeType)
  421.  
  422. mediaNode.setAttribute("encoding", self.encoding)
  423. mediaNode.setAttribute("width", str(self.width))
Add Comment
Please, Sign In to add comment