diff options
20 files changed, 181 insertions, 237 deletions
| diff --git a/protocols/WhatsApp/src/WASocketConnection.cpp b/protocols/WhatsApp/src/WASocketConnection.cpp index c688492e4e..2ff362b9bf 100644 --- a/protocols/WhatsApp/src/WASocketConnection.cpp +++ b/protocols/WhatsApp/src/WASocketConnection.cpp @@ -58,15 +58,10 @@ int WASocketConnection::waitForRead()  	int fd = 0;
  	FD_ZERO(&rfds);
 -	// _LOGDATA("preparando select");
 -	//fd = (this->socket)->channel; //#!?
 -	// _LOGDATA("socket %d", fd);
  	FD_SET(fd, &rfds);
  	tv.tv_sec = 600; //ApplicationData::SELECT_TIMEOUT;
  	tv.tv_usec = 0; // 5000000;
  	tvp = &tv;
 -	//if (ApplicationData::SELECT_TIMEOUT == -1) #TODO
 -	//	tvp = NULL;
  	int retval = select(/*fd + 1*/ 0, &rfds, NULL, NULL, tvp);
  	if (!FD_ISSET(fd, &rfds))
 @@ -83,7 +78,7 @@ void WASocketConnection::write(const std::vector<unsigned char>& bytes, int offs  	std::string tmpBuf = std::string(bytes.begin(), bytes.end());
  	nlb.buf = (char*)&(tmpBuf.c_str()[offset]);
  	nlb.len = length;
 -	nlb.flags = 0; //MSG_NOHTTPGATEWAYWRAP | MSG_NODUMP;
 +	nlb.flags = MSG_NODUMP;
  	int result = CallService(MS_NETLIB_SEND, reinterpret_cast<WPARAM>(this->hConn),
  									 reinterpret_cast<LPARAM>(&nlb));
 @@ -154,6 +149,11 @@ void WASocketConnection::dump(const void *pData, int length)  	}
  }
 +void WASocketConnection::log(const char *str)
 +{
 +	Netlib_Logf(WASocketConnection::hNetlibUser, "STR: %s", str);
 +}
 +
  WASocketConnection::~WASocketConnection()
  {
  	this->forceShutdown();
 diff --git a/protocols/WhatsApp/src/WASocketConnection.h b/protocols/WhatsApp/src/WASocketConnection.h index c585e98b3d..1f0034471b 100644 --- a/protocols/WhatsApp/src/WASocketConnection.h +++ b/protocols/WhatsApp/src/WASocketConnection.h @@ -34,7 +34,9 @@ public:  	void makeNonBlock();
  	int waitForRead();
  	void forceShutdown();
 +	
  	void dump(const void *buf, int length);
 +	void log(const char *str);
  	static void initNetwork(HANDLE hNetlibUser) throw (WAException);
  	static void quitNetwork();
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp index 227857a522..7ec854878a 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.cpp @@ -12,7 +12,7 @@  BinTreeNodeWriter::BinTreeNodeWriter(WAConnection* conn, ISocketConnection* connection, IMutex* mutex)
  {
 -	this->bLoggedIn = false;
 +	this->bSecure = false;
  	this->mutex = mutex;
  	this->conn = conn;
  	this->out = new ByteArrayOutputStream(2048);
 @@ -31,25 +31,26 @@ void BinTreeNodeWriter::writeDummyHeader()  void BinTreeNodeWriter::processBuffer()
  {
 -	unsigned int num = 0u;
 -	if (bLoggedIn) {
 +	unsigned char num = 0;
 +	if (bSecure) {
  		long num2 = (long)this->out->getLength() + 4L;
  		this->out->setLength(num2);
  		this->out->setPosition(num2);
 -		num |= 1u;
 +		num = 8;
  	}
  	long num3 = (long)this->out->getLength() - 3L - (long) this->dataBegin;
  	if (num3 >= 1048576L)
  		throw WAException("Buffer too large: " + num3, WAException::CORRUPT_STREAM_EX, 0);
 -	std::vector<unsigned char>* buffer = this->out->getBuffer();
 -	if (bLoggedIn) {
 +	std::vector<unsigned char>& buffer = this->out->getBuffer();
 +	this->realOut->dump(buffer.data(), (int)buffer.size());
 +	if (bSecure) {
  		int num4 = (int)num3 - 4;
 -		this->conn->outputKey.encodeMessage(buffer->data(), this->dataBegin + 3 + num4, this->dataBegin + 3, num4);
 +		this->conn->outputKey.encodeMessage(buffer.data(), this->dataBegin + 3 + num4, this->dataBegin + 3, num4);
  	}
 -	(*buffer)[this->dataBegin] = (unsigned char)((unsigned long)((unsigned long)num << 4) | (unsigned long)((num3 & 16711680L) >> 16));
 -	(*buffer)[this->dataBegin + 1] = (unsigned char)((num3 & 65280L) >> 8);
 -	(*buffer)[this->dataBegin + 2] = (unsigned char)(num3 & 255L);
 +	buffer[dataBegin] = (unsigned char)((unsigned long)((unsigned long)num << 4) | (unsigned long)((num3 & 16711680L) >> 16));
 +	buffer[dataBegin + 1] = (unsigned char)((num3 & 65280L) >> 8);
 +	buffer[dataBegin + 2] = (unsigned char)(num3 & 255L);
  }
  void BinTreeNodeWriter::streamStart(std::string domain, std::string resource)
 @@ -220,17 +221,18 @@ void BinTreeNodeWriter::flushBuffer(bool flushNetwork, int startingOffset)  		throw ex;
  	}
 -	// _LOGDATA("buffer size %d, buffer position %d, dataBegin %d", this->out->getLength(), this->out->getPosition(), this->dataBegin);
 -
 -	std::vector<unsigned char> buffer(this->out->getBuffer()->begin(), this->out->getBuffer()->end());
 +	std::vector<unsigned char> buffer(this->out->getBuffer().begin(), this->out->getBuffer().end());
  	int num = (int)(this->out->getLength() - (long)startingOffset);
  	if (flushNetwork && ((long)this->out->getCapacity() - this->out->getLength() < 3L || this->out->getLength() > 4096L)) {
  		delete this->out;
  		this->out = new ByteArrayOutputStream(4096);
  	}
 -	if (flushNetwork)
 +	if (flushNetwork) {
  		this->realOut->write(buffer, startingOffset, num);
 +		this->out->setPosition(0);
 +		this->out->setLength(0);
 +	}
  }
  void BinTreeNodeWriter::streamEnd()
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h index 66d9cbb991..fa5d7f68b0 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h +++ b/protocols/WhatsApp/src/WhatsAPI++/BinTreeNodeWriter.h @@ -39,7 +39,7 @@ private:  	ByteArrayOutputStream *out;
  	IMutex* mutex;
  	int dataBegin;
 -	bool bLoggedIn;
 +	bool bSecure;
  	void writeListStart(int i);
  	void writeInt8(int v);
 @@ -67,7 +67,7 @@ public:  	void write(const ProtocolTreeNode &node);
  	void write(const ProtocolTreeNode &node, bool needsFlush);
 -	void setLoggedIn() { bLoggedIn = true; }
 +	void setSecure() { bSecure = true; }
  };
  #endif /* BINTREENODEWRITER_H_ */
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp index 579dd58516..7e98847cff 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.cpp @@ -13,57 +13,33 @@  ByteArrayOutputStream::ByteArrayOutputStream(int size)
  {
 -	this->buf = new std::vector<unsigned char>();
 -	this->buf->reserve(size);
 -	this->position = 0;
 +	buf.reserve(size);
 +	position = 0;
  }
  void ByteArrayOutputStream::setLength(size_t length)
  {
 -	this->buf->resize(length);
 -}
 -
 -size_t ByteArrayOutputStream::getLength()
 -{
 -	return this->buf->size();
 -}
 -
 -size_t ByteArrayOutputStream::getCapacity()
 -{
 -	return this->buf->capacity();
 -}
 -
 -size_t ByteArrayOutputStream::getPosition()
 -{
 -	return this->position;
 +	buf.resize(length);
  }
  void ByteArrayOutputStream::setPosition(size_t count)
  {
 -	this->position = count;
 +	position = count;
  }
 -std::vector<unsigned char>* ByteArrayOutputStream::toByteArray()
 -{
 -	std::vector<unsigned char>* array = new std::vector<unsigned char>(this->buf->size());
 -	for (size_t i = 0; i < this->buf->size(); i++)
 -		(*array)[i] = (*this->buf)[i];
 -	return array;
 -}
 -
 -std::vector<unsigned char>* ByteArrayOutputStream::getBuffer()
 +std::vector<unsigned char>& ByteArrayOutputStream::getBuffer()
  {
 -	return this->buf;
 +	return buf;
  }
  void ByteArrayOutputStream::write(int i)
  {
 -	if (this->position == this->buf->size())
 -		this->buf->push_back((unsigned char)i);
 +	if (this->position == this->buf.size())
 +		buf.push_back((unsigned char)i);
  	else
 -		(*this->buf)[this->position] = (unsigned char)i;
 -	this->position = this->position + 1;
 +		buf[position] = (unsigned char)i;
 +	position++;
  }
  void ByteArrayOutputStream::write(unsigned char* b, size_t len)
 @@ -81,13 +57,10 @@ void ByteArrayOutputStream::write(const std::string& s)  		write((unsigned char)s[i]);
  }
 -
  ByteArrayOutputStream::~ByteArrayOutputStream()
  {
 -	delete this->buf;
  }
 -
  ByteArrayInputStream::ByteArrayInputStream(std::vector<unsigned char>* buf, size_t off, size_t length)
  {
  	this->buf = buf;
 @@ -138,31 +111,3 @@ int ByteArrayInputStream::read(std::vector<unsigned char>& b, size_t  off, size_  ByteArrayInputStream::~ByteArrayInputStream()
  {}
 -
 -void ByteArrayInputStream::print()
 -{
 -	std::cout << "[";
 -	for (size_t i = 0; i < this->count; i++)
 -		std::cout << (*this->buf)[i] << " ";
 -
 -	std::cout << std::endl;
 -	for (size_t i = 0; i < this->count; i++)
 -		std::cout << (int)((signed char)(*this->buf)[i]) << " ";
 -
 -	std::cout << "]" << std::endl;
 -}
 -
 -void ByteArrayOutputStream::print()
 -{
 -	_LOGDATA("[");
 -
 -	std::string chars(this->buf->begin(), this->buf->end());
 -	_LOGDATA("%s ", chars.c_str());
 -
 -	std::string numbers = "";
 -	for (size_t i = 0; i < this->buf->size(); i++)
 -		numbers += Utilities::intToStr((int)((signed char)(*this->buf)[i])) + " ";
 -
 -	_LOGDATA("%s", numbers.c_str());
 -	_LOGDATA("]");
 -}
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h index 57ac503020..5a3f90d221 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ByteArray.h @@ -15,24 +15,23 @@  class ByteArrayOutputStream {
  protected:
 -	std::vector<unsigned char>* buf;
 +	std::vector<unsigned char> buf;
  	size_t position;
  public:
  	ByteArrayOutputStream(int size = 32);
 -	std::vector<unsigned char>* toByteArray();
 -	std::vector<unsigned char>* getBuffer();
 -	size_t getPosition();
 +	virtual ~ByteArrayOutputStream();
 +
 +	std::vector<unsigned char>& getBuffer();
  	void setPosition(size_t count);
  	void write(int i);
  	void write(unsigned char* c, size_t length);
  	void write(const std::string& s);
 -	void print();
  	void setLength(size_t length);
 -	size_t getLength();
 -	size_t getCapacity();
 -	virtual ~ByteArrayOutputStream();
 +	__forceinline size_t getCapacity() const { return buf.capacity(); }
 +	__forceinline size_t getLength() const { return buf.size(); }
 +	__forceinline size_t getPosition() const { return position; }
  };
  class ByteArrayInputStream {
 @@ -47,7 +46,6 @@ public:  	ByteArrayInputStream(std::vector<unsigned char>* buf);
  	int read();
  	int read(std::vector<unsigned char>& b, size_t off, size_t length);
 -	void print();
  	virtual ~ByteArrayInputStream();
  };
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/ISocketConnection.h b/protocols/WhatsApp/src/WhatsAPI++/ISocketConnection.h index b9fa3d5faa..82123f2fd8 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ISocketConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ISocketConnection.h @@ -21,6 +21,7 @@ public:  	virtual void forceShutdown() = 0;
  	virtual void dump(const void *buf, int length) = 0;
 +	virtual void log(const char *str) = 0;
  };
  #endif /* ISOCKETCONNECTION_H_ */
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp index 5929d43b20..cb3bc19258 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.cpp @@ -44,14 +44,14 @@ ProtocolTreeNode::~ProtocolTreeNode()  }
 -string ProtocolTreeNode::toString()
 +string ProtocolTreeNode::toString() const
  {
  	string out;
  	out += "<" + this->tag;
  	if (this->attributes != NULL) {
  		map<string, string>::iterator ii;
  		for (ii = attributes->begin(); ii != attributes->end(); ii++)
 -			out += "" + ii->first + "=\"" + ii->second + "\"";
 +			out += " " + ii->first + "=\"" + ii->second + "\"";
  	}
  	out += ">\n";
  	out += getDataAsString();
 @@ -110,7 +110,7 @@ vector<ProtocolTreeNode*> ProtocolTreeNode::getAllChildren()  	return *this->children;
  }
 -std::string ProtocolTreeNode::getDataAsString()
 +std::string ProtocolTreeNode::getDataAsString() const
  {
  	if (this->data == NULL)
  		return nilstr;
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h index 0731d97ab1..6be09cef8d 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h +++ b/protocols/WhatsApp/src/WhatsAPI++/ProtocolTreeNode.h @@ -54,14 +54,14 @@ public:     ProtocolTreeNode(const string& tag, ProtocolTreeNode* child);
     ProtocolTreeNode(const string& tag, vector<unsigned char>* data = NULL, vector<ProtocolTreeNode*> *children = NULL);
 -   string toString();
 +   string toString() const; 
     ProtocolTreeNode* getChild(const string& id);
     ProtocolTreeNode* getChild(size_t id);
     const string& getAttributeValue(const string& attribute);
     vector<ProtocolTreeNode*> getAllChildren();
     vector<ProtocolTreeNode*> getAllChildren(const string& tag);
 -   std::string getDataAsString();
 +	std::string getDataAsString() const;
     static bool tagEquals(ProtocolTreeNode *node, const string& tag);
     static void require(ProtocolTreeNode *node, const string& tag);
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp index 270c329085..ceb308763d 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.cpp @@ -11,52 +11,52 @@  #include "utilities.h"
  const char* 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", "groups_v2", "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", "readreceipts", "reason", -	"receipt", "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: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", "xmlns:stream", "xmlns", "1", "chatstate", "crypto", "phash", "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" +	"", "", "", "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", "groups_v2", "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", "readreceipts", "reason",
 +	"receipt", "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: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", "xmlns:stream", "xmlns", "1", "chatstate", "crypto", "phash", "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"
  };
 -const char* extended_dict[] = { -	"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", "410", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt", "asampfreq", "audio", "clear", "conflict", -	"conn_no_nna", "cost", "currency", "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "gone", "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", -	"max_list_recipients", "en-AU", "en-GB", "es-MX", "pt-PT", "zh-Hans", "zh-Hant", "relayelection", "relaylatency", "interruption", -	"Apex.m4r", "Beacon.m4r", "Bulletin.m4r", "By The Seaside.m4r", "Chimes.m4r", "Circuit.m4r", "Constellation.m4r", "Cosmic.m4r", -	"Crystals.m4r", "Hillside.m4r", "Illuminate.m4r", "Night Owl.m4r", "Opening.m4r", "Playtime.m4r", "Presto.m4r", "Radar.m4r", -	"Radiate.m4r", "Ripples.m4r", "Sencha.m4r", "Signal.m4r", "Silk.m4r", "Slow Rise.m4r", "Stargaze.m4r", "Summit.m4r", "Twinkle.m4r", -	"Uplift.m4r", "Waves.m4r", "voip", "eligible", "upgrade", "planned", "current", "future", "disable", "expire", "start", "stop", -	"accuracy", "speed", "bearing", "recording", "encrypt", "key", "identity", "w:gp2", "admin", "locked", "unlocked", "new", "battery", -	"archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id" -}; +const char* extended_dict[] = {
 +	"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", "410", "500", "501", "503", "504", "abitrate", "acodec", "app_uptime", "asampfmt", "asampfreq", "audio", "clear", "conflict",
 +	"conn_no_nna", "cost", "currency", "duration", "extend", "file", "fps", "g_notify", "g_sound", "gcm", "gone", "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",
 +	"max_list_recipients", "en-AU", "en-GB", "es-MX", "pt-PT", "zh-Hans", "zh-Hant", "relayelection", "relaylatency", "interruption",
 +	"Apex.m4r", "Beacon.m4r", "Bulletin.m4r", "By The Seaside.m4r", "Chimes.m4r", "Circuit.m4r", "Constellation.m4r", "Cosmic.m4r",
 +	"Crystals.m4r", "Hillside.m4r", "Illuminate.m4r", "Night Owl.m4r", "Opening.m4r", "Playtime.m4r", "Presto.m4r", "Radar.m4r",
 +	"Radiate.m4r", "Ripples.m4r", "Sencha.m4r", "Signal.m4r", "Silk.m4r", "Slow Rise.m4r", "Stargaze.m4r", "Summit.m4r", "Twinkle.m4r",
 +	"Uplift.m4r", "Waves.m4r", "voip", "eligible", "upgrade", "planned", "current", "future", "disable", "expire", "start", "stop",
 +	"accuracy", "speed", "bearing", "recording", "encrypt", "key", "identity", "w:gp2", "admin", "locked", "unlocked", "new", "battery",
 +	"archive", "adm", "plaintext_size", "compressed_size", "delivered", "msg", "pkmsg", "everyone", "v", "transport", "call-id"
 +};
  static map<string, int> tokenMap1, tokenMap2;
 @@ -85,6 +85,17 @@ int WAConnection::tokenLookup(const std::string &str)  /////////////////////////////////////////////////////////////////////////////////////////
 +void WAConnection::logData(const char *format, ...)
 +{
 +	va_list args;
 +	va_start(args, format);
 +	char tmp[4000];
 +	vsprintf_s(tmp, format, args);
 +	rawConn->log(tmp);
 +}
 +
 +/////////////////////////////////////////////////////////////////////////////////////////
 +
  WAConnection::WAConnection(const std::string &user, const std::string &resource, IMutex *mutex, WAListener *event_handler, WAGroupListener *group_event_handler)
  {
  	this->mutex = mutex;
 @@ -119,8 +130,9 @@ WAConnection::~WAConnection()  		delete it->second;
  }
 -void WAConnection::init(IMutex *mutex, WASocketConnection *conn)
 +void WAConnection::init(IMutex *mutex, ISocketConnection *conn)
  {
 +	rawConn = conn;
  	in = new BinTreeNodeReader(this, conn);
  	out = new BinTreeNodeWriter(this, conn, mutex);
  }
 @@ -136,8 +148,8 @@ void WAConnection::setLogin(WALogin* login)  void WAConnection::sendMessageWithMedia(FMessage* message)  throw (WAException)
  {
 -	_LOGDATA("Send message with media %s %d", message->media_name.c_str(), message->media_size);
 -	_LOGDATA("media-url:%s", message->media_url.c_str());
 +	logData("Send message with media %s %d", message->media_name.c_str(), message->media_size);
 +	logData("media-url:%s", message->media_url.c_str());
  	if (message->media_wa_type == FMessage::WA_TYPE_SYSTEM)
  		throw new WAException("Cannot send system message over the network");
 @@ -223,9 +235,15 @@ bool WAConnection::read() throw(WAException)  		throw WAException(ex.what(), WAException::CORRUPT_STREAM_EX, 0);
  	}
 -	if (node == NULL) {
 +	if (node == NULL)
  		return false;
 +
 +	#ifdef _DEBUG
 +	{
 +		string tmp = node->toString();
 +		rawConn->log(tmp.c_str());
  	}
 +	#endif
  	if (ProtocolTreeNode::tagEquals(node, "iq")) {
  		const string &type = node->getAttributeValue("type");
 @@ -595,7 +613,7 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag  					if (encoding.empty() || encoding == "text")
  						fmessage->data = childNode->getDataAsString();
  					else {
 -						_LOGDATA("Media data encoding type '%s'", encoding.empty() ? "text" : encoding.c_str());
 +						logData("Media data encoding type '%s'", encoding.empty() ? "text" : encoding.c_str());
  						fmessage->data = (childNode->data == NULL ? "" : std::string(base64_encode(childNode->data->data(), childNode->data->size())));
  					}
  				}
 @@ -656,7 +674,7 @@ void WAConnection::parseMessageInitialTagAlreadyChecked(ProtocolTreeNode* messag  		delete fmessage;
  	}
  	else if (typeAttribute == "notification") {
 -		_LOGDATA("Notification node %s", messageNode->toString().c_str());
 +		logData("Notification node %s", messageNode->toString().c_str());
  		bool flag = false;
  		std::vector<ProtocolTreeNode*> children(messageNode->getAllChildren());
  		for (size_t i = 0; i < children.size(); i++) {
 @@ -822,7 +840,7 @@ void WAConnection::readAttributeList(ProtocolTreeNode* node, std::vector<std::st  void WAConnection::sendCreateGroupChat(const std::string& subject) throw (WAException)
  {
 -	_LOGDATA("sending create group: %s", subject.c_str());
 +	logData("sending create group: %s", subject.c_str());
  	std::string id = makeId("create_group_");
  	this->pending_server_requests[id] = new IqResultCreateGroupChatHandler(this);
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h index 697542e32c..365c1e2d3d 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h +++ b/protocols/WhatsApp/src/WhatsAPI++/WAConnection.h @@ -103,7 +103,7 @@ class WAConnection {  		IqResultHandler(WAConnection* con) {this->con = con;}
  		virtual void parse(ProtocolTreeNode* paramProtocolTreeNode, const std::string& paramString) throw (WAException)=0;
  		void error(ProtocolTreeNode* node, int code) {
 -			_LOGDATA("WAConnection: error node %s: code = %d", node->getAttributeValue("id").c_str(), code);
 +			con->logData("WAConnection: error node %s: code = %d", node->getAttributeValue("id").c_str(), code);
  		}
  		void error(ProtocolTreeNode* node) throw (WAException) {
  			std::vector<ProtocolTreeNode*> nodes(node->getAllChildren("error"));
 @@ -303,7 +303,7 @@ class WAConnection {  	public:
  		IqResultGetPictureIdsHandler(WAConnection* con):IqResultHandler(con) {}
  		virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
 -			// _LOGDATA("onGetPhotoIds %s", node->toString().c_str());
 +			// logData("onGetPhotoIds %s", node->toString().c_str());
  			ProtocolTreeNode* groupNode = node->getChild("list");
  			std::vector<ProtocolTreeNode*> children(groupNode->getAllChildren("user"));
  			std::map<std::string, std::string> ids;
 @@ -344,17 +344,18 @@ class WAConnection {  	public:
  		IqSendClientConfigHandler(WAConnection* con):IqResultHandler(con) {}
  		virtual void parse(ProtocolTreeNode* node, const std::string& from) throw (WAException) {
 -			_LOGDATA("Clientconfig response %s", node->toString().c_str());
 +			con->logData("Clientconfig response %s", node->toString().c_str());
  		}
  		void error(ProtocolTreeNode* node) throw (WAException) {
 -			_LOGDATA("Clientconfig response error %s", node->toString().c_str());
 +			con->logData("Clientconfig response error %s", node->toString().c_str());
  		}
  	};
  	friend class WALogin;
  private:
 +	ISocketConnection *rawConn;
  	BinTreeNodeReader *in;
  	BinTreeNodeWriter *out;
  	WAListener *event_handler;
 @@ -382,7 +383,7 @@ private:  public:
  	WAConnection(const std::string& user, const std::string& resource, IMutex* mutex, WAListener* event_handler, WAGroupListener* group_event_handler);
  	virtual ~WAConnection();
 -	void init(IMutex* mutex, WASocketConnection*);
 +	void init(IMutex* mutex, ISocketConnection*);
  	std::string user;
  	std::string domain;
 @@ -400,6 +401,8 @@ public:  	static void globalInit(void);
  	static int  tokenLookup(const std::string&);
 +	void logData(const char *format, ...);
 +
  	static MessageStore* message_store;
  	KeyStream inputKey, outputKey;
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp index e009968b59..40471ae559 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp @@ -32,19 +32,19 @@ std::vector<unsigned char>* WALogin::login(const std::vector<unsigned char>& aut  {
  	connection->out->streamStart(connection->domain, connection->resource);
 -	_LOGDATA("sent stream start");
 +	connection->logData("sent stream start");
  	sendFeatures();
 -	_LOGDATA("sent features");
 +	connection->logData("sent features");
  	sendAuth(authBlob);
 -	_LOGDATA("send auth, auth blob size %d", authBlob.size());
 +	connection->logData("send auth, auth blob size %d", authBlob.size());
  	connection->in->streamStart();
 -	_LOGDATA("read stream start");
 +	connection->logData("read stream start");
  	return this->readFeaturesUntilChallengeOrSuccess();
  }
 @@ -99,6 +99,12 @@ std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char  std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()
  {
  	while (ProtocolTreeNode *root = connection->in->nextTree()) {
 +		#ifdef _DEBUG
 +			{
 +				string tmp = root->toString();
 +				connection->logData(tmp.c_str());
 +			}
 +		#endif
  		if (ProtocolTreeNode::tagEquals(root, "stream:features")) {
  			connection->supports_receipt_acks = root->getChild("receipt_acks") != NULL;
  			delete root;
 @@ -108,9 +114,9 @@ std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()  			std::vector<unsigned char> challengedata(root->data->begin(), root->data->end());
  			delete root;
  			this->sendResponse(challengedata);
 -			_LOGDATA("Send response");
 +			connection->logData("Send response");
  			std::vector<unsigned char> data = this->readSuccess();
 -			_LOGDATA("Read success");
 +			connection->logData("Read success");
  			return new std::vector<unsigned char>(data.begin(), data.end());
  		}
  		if (ProtocolTreeNode::tagEquals(root, "success")) {
 @@ -125,7 +131,7 @@ std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()  void WALogin::parseSuccessNode(ProtocolTreeNode* node)
  {
 -	connection->out->setLoggedIn();
 +	connection->out->setSecure();
  	const string &expiration = node->getAttributeValue("expiration");
  	if (!expiration.empty()) {
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp index 491a39e3e4..0734c34210 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.cpp @@ -21,7 +21,6 @@ std::string reverseString(const std::string& str)  std::string itoa(int value, unsigned int base)
  {
 -
  	const char digitMap[] = "0123456789abcdef";
  	std::string buf;
 @@ -139,7 +138,6 @@ std::string doubleToStr(double d)  time_t parseBBDate(const string& s)
  {
 -	_LOGDATA("parse DATE %s", s.c_str());
  	if (s.length() < 17)
  		return time(NULL);
 @@ -155,19 +153,6 @@ time_t parseBBDate(const string& s)  	return mktime(&timeinfo);
  }
 -void logData(const char *format, ...)
 -{
 -	va_list args;
 -	va_start(args, format);
 -#ifdef _LOGWIN32
 -	std::string formatLine = std::string(format).append("\n");
 -	vprintf(formatLine.c_str(), args); fflush(stdout);
 -#else
 -	vsyslog(LOG_ERR, format, args);
 -#endif
 -
 -}
 -
  long long parseLongLong(const std::string& str)
  {
  	std::stringstream sstr(str);
 diff --git a/protocols/WhatsApp/src/WhatsAPI++/utilities.h b/protocols/WhatsApp/src/WhatsAPI++/utilities.h index d0096489e2..4df6fde13d 100644 --- a/protocols/WhatsApp/src/WhatsAPI++/utilities.h +++ b/protocols/WhatsApp/src/WhatsAPI++/utilities.h @@ -34,14 +34,6 @@  #include <syslog.h>
  #endif
 -#ifdef _DEBUG
 -	#define _DEBUGENABLED true
 -#else
 -	#define _DEBUGENABLED false
 -#endif
 -
 -#define _LOGDATA(format, ...) if (_DEBUGENABLED) Utilities::logData(format, ##__VA_ARGS__)
 -
  using namespace std;
  // these functions must be declared somewhere in the same linking module
 @@ -61,7 +53,6 @@ namespace Utilities{  	std::string doubleToStr(double d);
  	long long parseLongLong(const std::string& str);
  	time_t parseBBDate(const string& s);
 -	void logData(const char *msg, ...);
  	long long getCurrentTimeMillis();
  	std::string bytesToHex(unsigned char* bytes, int length);
  	unsigned char forDigit(int b);
 diff --git a/protocols/WhatsApp/src/connection.cpp b/protocols/WhatsApp/src/connection.cpp index 8c1f16c456..af7ca81d6e 100644 --- a/protocols/WhatsApp/src/connection.cpp +++ b/protocols/WhatsApp/src/connection.cpp @@ -1,36 +1,5 @@  #include "common.h"
 -void WhatsAppProto::ChangeStatus(void*)
 -{
 -	if (m_iDesiredStatus != ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) {
 -		ResetEvent(update_loop_lock_);
 -		ForkThread(&WhatsAppProto::sentinelLoop, this);
 -		ForkThread(&WhatsAppProto::stayConnectedLoop, this);
 -	}
 -	else if (m_iStatus == ID_STATUS_INVISIBLE && m_iDesiredStatus == ID_STATUS_ONLINE) {
 -		if (this->connection != NULL) {
 -			this->connection->sendAvailableForChat();
 -			m_iStatus = ID_STATUS_ONLINE;
 -			ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_INVISIBLE);
 -		}
 -	}
 -	else if (m_iStatus == ID_STATUS_ONLINE && m_iDesiredStatus == ID_STATUS_INVISIBLE) {
 -		if (this->connection != NULL) {
 -			this->connection->sendClose();
 -			m_iStatus = ID_STATUS_INVISIBLE;
 -			SetAllContactStatuses(ID_STATUS_OFFLINE, true);
 -			ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_ONLINE);
 -		}
 -	}
 -	else if (m_iDesiredStatus == ID_STATUS_OFFLINE) {
 -		if (this->conn != NULL) {
 -			SetEvent(update_loop_lock_);
 -			this->conn->forceShutdown();
 -			debugLogA("Forced shutdown");
 -		}
 -	}
 -}
 -
  void WhatsAppProto::stayConnectedLoop(void*)
  {
  	std::string cc, in, pass;
 @@ -104,8 +73,6 @@ void WhatsAppProto::stayConnectedLoop(void*)  		}
  		debugLogA("Connecting...");
 -		this->m_iStatus = ID_STATUS_CONNECTING;
 -		ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_OFFLINE, m_iStatus);
  		try {
  			unsigned passLen;
 @@ -123,13 +90,13 @@ void WhatsAppProto::stayConnectedLoop(void*)  			{
  				WALogin login(connection, password);
 -				std::vector<unsigned char>* nextChallenge = login.login(*this->challenge);
 +				std::vector<unsigned char> *nextChallenge = login.login(*this->challenge);
  				delete this->challenge;
  				this->challenge = nextChallenge;
  				connection->setLogin(&login);
  			}
  			connection->nick = this->nick;
 -			connection->setVerboseId(true); // ?
 +			connection->setVerboseId(true);
  			if (desiredStatus != ID_STATUS_INVISIBLE)
  				connection->sendAvailableForChat();
 @@ -138,13 +105,13 @@ void WhatsAppProto::stayConnectedLoop(void*)  			ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)m_iStatus, ID_STATUS_CONNECTING);
  			this->ToggleStatusMenuItems(true);
 -			ForkThread(&WhatsAppProto::ProcessBuddyList, this);
 +			// ProcessBuddyList(0);
  			// #TODO Move out of try block. Exception is expected on disconnect
 -			bool cont = true;
 -			while (cont == true) {
 +			while (true) {
  				this->lastPongTime = time(NULL);
 -				cont = connection->read();
 +				if (!connection->read())
 +					break;
  			}
  			debugLogA("Exit from read-loop");
  		}
 diff --git a/protocols/WhatsApp/src/contacts.cpp b/protocols/WhatsApp/src/contacts.cpp index bdef80ad8d..d9db3e0d43 100644 --- a/protocols/WhatsApp/src/contacts.cpp +++ b/protocols/WhatsApp/src/contacts.cpp @@ -132,6 +132,7 @@ void WhatsAppProto::ProcessBuddyList(void*)  					// Do not request picture for inactive groups - this would make the group visible again
  					jids.push_back(string(jid));
  				}
 +				
  				if (getByte(hContact, "SimpleChatRoom", 0) == 0) {
  					this->connection->sendQueryLastOnline((char*)jid);
  					this->connection->sendPresenceSubscriptionRequest((char*)jid);
 diff --git a/protocols/WhatsApp/src/main.cpp b/protocols/WhatsApp/src/main.cpp index 9bc53ce6de..1681132790 100644 --- a/protocols/WhatsApp/src/main.cpp +++ b/protocols/WhatsApp/src/main.cpp @@ -81,6 +81,7 @@ extern "C" int __declspec(dllexport) Load(void)  	WORD v[4];
  	CallService(MS_SYSTEM_GETFILEVERSION, 0, LPARAM(&v));
 +	WAConnection::globalInit();
  	return 0;
  }
 diff --git a/protocols/WhatsApp/src/proto.cpp b/protocols/WhatsApp/src/proto.cpp index d4eda7f973..e889854871 100644 --- a/protocols/WhatsApp/src/proto.cpp +++ b/protocols/WhatsApp/src/proto.cpp @@ -86,6 +86,10 @@ DWORD_PTR WhatsAppProto::GetCaps(int type, MCONTACT hContact)  int WhatsAppProto::SetStatus(int new_status)
  {
 +	if (m_iDesiredStatus == new_status)
 +		return 0;
 +
 +	int oldStatus = m_iStatus;
  	debugLogA("===== Beginning SetStatus process");
  	// Routing statuses not supported by WhatsApp
 @@ -106,17 +110,38 @@ int WhatsAppProto::SetStatus(int new_status)  		break;
  	}
 -	if (m_iStatus == ID_STATUS_CONNECTING) {
 -		debugLogA("===== Status is connecting, no change");
 -		return 0;
 -	}
 +	if (m_iDesiredStatus == ID_STATUS_OFFLINE) {
 +		if (this->conn != NULL) {
 +			SetEvent(update_loop_lock_);
 +			this->conn->forceShutdown();
 +			debugLogA("Forced shutdown");
 +		}
 -	if (m_iStatus == m_iDesiredStatus) {
 -		debugLogA("===== Statuses are same, no change");
 -		return 0;
 +		m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
 +		ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
  	}
 +	else if (this->conn == NULL && !(m_iStatus >= ID_STATUS_CONNECTING && m_iStatus < ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES)) {
 +		m_iStatus = ID_STATUS_CONNECTING;
 +		ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
 -	ForkThread(&WhatsAppProto::ChangeStatus, this);
 +		ResetEvent(update_loop_lock_);
 +		ForkThread(&WhatsAppProto::sentinelLoop, this);
 +		ForkThread(&WhatsAppProto::stayConnectedLoop, this);
 +	}
 +	else if (this->connection != NULL) {
 +		if (m_iDesiredStatus == ID_STATUS_ONLINE) {
 +			this->connection->sendAvailableForChat();
 +			m_iStatus = ID_STATUS_ONLINE;
 +			ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
 +		}
 +		else if (m_iStatus == ID_STATUS_ONLINE && m_iDesiredStatus == ID_STATUS_INVISIBLE) {
 +			this->connection->sendClose();
 +			m_iStatus = ID_STATUS_INVISIBLE;
 +			SetAllContactStatuses(ID_STATUS_OFFLINE, true);
 +			ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
 +		}
 +	}
 +	else ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
  	return 0;
  }
 diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h index 5f5416671f..099e89de03 100644 --- a/protocols/WhatsApp/src/proto.h +++ b/protocols/WhatsApp/src/proto.h @@ -108,7 +108,6 @@ public:  	void __cdecl SearchAckThread(void*);
  	// Worker Threads
 -	void __cdecl ChangeStatus(void*);
  	void __cdecl SendMsgWorker(void*);
  	void __cdecl RecvMsgWorker(void*);
  	void __cdecl SendTypingWorker(void*);
 diff --git a/protocols/WhatsApp/src/version.h b/protocols/WhatsApp/src/version.h index 0a73307133..3f05a927e9 100644 --- a/protocols/WhatsApp/src/version.h +++ b/protocols/WhatsApp/src/version.h @@ -1,6 +1,6 @@  #define __MAJOR_VERSION          0
  #define __MINOR_VERSION          1
 -#define __RELEASE_NUM            1
 +#define __RELEASE_NUM            2
  #define __BUILD_NUM              0
  #include <stdver.h>
 | 
