From d16d69e7b86095c1493f4a7062751768c31a58fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Mon, 19 Oct 2015 20:11:55 +0000 Subject: Omegle: Various improvements * Remove typing weirdness * Fix resetting "stranger is typing" on receiving message * Make option "hi message" choose randomly from more messages git-svn-id: http://svn.miranda-ng.org/main/trunk@15571 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Omegle/src/client.h | 3 +- protocols/Omegle/src/communication.cpp | 1654 ++++++++++++++++---------------- protocols/Omegle/src/messages.cpp | 156 ++- protocols/Omegle/src/stdafx.h | 1 + protocols/Omegle/src/utils.cpp | 24 +- protocols/Omegle/src/utils.h | 1 + 6 files changed, 930 insertions(+), 909 deletions(-) (limited to 'protocols/Omegle/src') diff --git a/protocols/Omegle/src/client.h b/protocols/Omegle/src/client.h index d3a6bf6856..b33c05350c 100644 --- a/protocols/Omegle/src/client.h +++ b/protocols/Omegle/src/client.h @@ -42,7 +42,7 @@ public: send_message_lock_ = NULL; state_ = STATE_INACTIVE; - old_typing_ = typing_ = spy_mode_ = false; + typing_ = spy_mode_ = false; error_count_ = 0; @@ -74,7 +74,6 @@ public: // State of client int state_; bool typing_; - bool old_typing_; bool spy_mode_; // Data storage diff --git a/protocols/Omegle/src/communication.cpp b/protocols/Omegle/src/communication.cpp index 9b0ba9f3d5..a869a47391 100644 --- a/protocols/Omegle/src/communication.cpp +++ b/protocols/Omegle/src/communication.cpp @@ -1,824 +1,830 @@ -/* - -Omegle plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2011-15 Robert Pösel - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include "stdafx.h" - -http::response Omegle_client::flap(const int request_type, std::string *post_data, std::string *get_data) -{ - http::response resp; - - // Prepare the request - NETLIBHTTPREQUEST nlhr = { sizeof(NETLIBHTTPREQUEST) }; - - // Set request URL - std::string url = choose_server(request_type) + choose_action(request_type, get_data); - nlhr.szUrl = (char*)url.c_str(); - - // Set timeout (bigger for channel request) - nlhr.timeout = 1000 * ((request_type == OMEGLE_REQUEST_EVENTS) ? 65 : 20); - - // Set request type (GET/POST) and eventually also POST data - if (post_data != NULL) { - nlhr.requestType = REQUEST_POST; - nlhr.pData = (char*)(*post_data).c_str(); - nlhr.dataLength = (int)post_data->length(); - } - else { - nlhr.requestType = REQUEST_GET; - } - - // Set headers - it depends on requestType so it must be after setting that - nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount); - - // Set flags - nlhr.flags = NLHRF_HTTP11; - -#ifdef _DEBUG - nlhr.flags |= NLHRF_DUMPASTEXT; -#else - nlhr.flags |= NLHRF_NODUMP; -#endif - - // Set persistent connection (or not) - switch (request_type) - { - case OMEGLE_REQUEST_HOME: - nlhr.nlc = NULL; - break; - - case OMEGLE_REQUEST_EVENTS: - nlhr.nlc = hEventsConnection; - nlhr.flags |= NLHRF_PERSISTENT; - break; - - default: - WaitForSingleObject(connection_lock_, INFINITE); - nlhr.nlc = hConnection; - nlhr.flags |= NLHRF_PERSISTENT; - break; - } - - parent->debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl); - - // Send the request - NETLIBHTTPREQUEST *pnlhr = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)handle_, (LPARAM)&nlhr); - - mir_free(nlhr.headers); - - // Remember the persistent connection handle (or not) - switch ( request_type ) - { - case OMEGLE_REQUEST_HOME: - break; - - case OMEGLE_REQUEST_EVENTS: - hEventsConnection = pnlhr ? pnlhr->nlc : NULL; - break; - - default: - ReleaseMutex(connection_lock_); - hConnection = pnlhr ? pnlhr->nlc : NULL; - break; - } - - // Check and copy response data - if (pnlhr != NULL) - { - parent->debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode); - store_headers(&resp, pnlhr->headers, pnlhr->headersCount); - resp.code = pnlhr->resultCode; - resp.data = pnlhr->pData ? pnlhr->pData : ""; - - parent->debugLogA("&&&&& Got response: %s", resp.data.c_str()); - - CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)pnlhr); - } else { - parent->debugLogA("!!!!! No response from server (time-out)"); - resp.code = HTTP_CODE_FAKE_DISCONNECTED; - // Better to have something set explicitely as this value is compaired in all communication requests - } - - return resp; -} - -bool Omegle_client::handle_entry(const std::string &method ) -{ - parent->debugLogA(" >> Entering %s()", method.c_str()); - return true; -} - -bool Omegle_client::handle_success(const std::string &method ) -{ - parent->debugLogA(" << Quitting %s()", method.c_str()); - reset_error(); - return true; -} - -bool Omegle_client::handle_error(const std::string &method, bool force_disconnect ) -{ - bool result; - increment_error(); - parent->debugLogA("!!!!! %s(): Something with Omegle went wrong", method.c_str()); - - if ( force_disconnect ) - result = false; - else if ( error_count_ <= (UINT)db_get_b(NULL,parent->m_szModuleName,OMEGLE_KEY_TIMEOUTS_LIMIT,OMEGLE_TIMEOUTS_LIMIT)) - result = true; - else - result = false; - - if ( result == false ) - { - reset_error(); - parent->UpdateChat(NULL, TranslateT("Connection error.")); - parent->StopChat(false); - } - - return result; -} - -////////////////////////////////////////////////////////////////////////////// - -std::string Omegle_client::get_server( bool not_last ) -{ - int q = not_last ? 1 : 0; - - int server = db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_SERVER, 0); - if (server < 0 || server >= (int)(_countof(servers)-q)) - server = 0; - - if (server == 0) { - srand(::time(NULL)); - server = (rand() % (_countof(servers)-1-q))+1; - } - - return servers[server]; -} - -std::string Omegle_client::get_language() -{ - int language = db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_LANGUAGE, 0); - if (language < 0 || language >= (_countof(languages))) - language = 0; - - return language > 0 ? languages[language].id : "en"; -} - -std::string Omegle_client::choose_server(int request_type) -{ - switch ( request_type ) - { - case OMEGLE_REQUEST_HOME: - return OMEGLE_SERVER_REGULAR; - -/* case OMEGLE_REQUEST_START: - case OMEGLE_REQUEST_STOP: - case OMEGLE_REQUEST_SEND: - case OMEGLE_REQUEST_EVENTS: - case OMEGLE_REQUEST_TYPING_START: - case OMEGLE_REQUEST_TYPING_STOP: - case OMEGLE_REQUEST_RECAPTCHA: - case OMEGLE_REQUEST_COUNT: -*/ default: - std::string server = OMEGLE_SERVER_CHAT; - utils::text::replace_first( &server, "%s", this->server_ ); - return server; - } -} - -std::string Omegle_client::choose_action(int request_type, std::string* get_data) -{ - switch ( request_type ) - { - case OMEGLE_REQUEST_START: - { - std::string action = "/start?rcs=1&spid=&lang="; - action += get_language(); - if (get_data != NULL) - action += (*get_data); - - return action; - } - - case OMEGLE_REQUEST_STOP: - return "/disconnect"; - - case OMEGLE_REQUEST_SEND: - return "/send"; - - case OMEGLE_REQUEST_EVENTS: - return "/events"; - - case OMEGLE_REQUEST_TYPING_START: - return "/typing"; - - case OMEGLE_REQUEST_TYPING_STOP: - return "/stoppedtyping"; - - case OMEGLE_REQUEST_RECAPTCHA: - return "/recaptcha"; - - case OMEGLE_REQUEST_COUNT: - return "/count"; - - // "/stoplookingforcommonlikes" - -/* case OMEGLE_REQUEST_HOME: -*/ default: - return "/"; - } -} - - -NETLIBHTTPHEADER* Omegle_client::get_request_headers( int request_type, int* headers_count ) -{ - if (request_type == REQUEST_POST) - *headers_count = 4; - else - *headers_count = 3; - - NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count)); - - if (request_type == REQUEST_POST) { - headers[3].szName = "Content-Type"; - headers[3].szValue = "application/x-www-form-urlencoded; charset=utf-8"; - } - - headers[2].szName = "User-Agent"; - headers[2].szValue = (char *)g_strUserAgent.c_str(); - headers[1].szName = "Accept"; - headers[1].szValue = "*/*"; - headers[0].szName = "Accept-Language"; - headers[0].szValue = "en,en-US;q=0.9"; - - return headers; -} - -void Omegle_client::store_headers( http::response* resp, NETLIBHTTPHEADER* headers, int headersCount ) -{ - for ( size_t i = 0; i < (size_t)headersCount; i++ ) - { - std::string header_name = headers[i].szName; - std::string header_value = headers[i].szValue; - - // TODO RM: (un)comment - //parent->debugLogA("----- Got header '%s': %s", header_name.c_str(), header_value.c_str()); - resp->headers[header_name] = header_value; - } -} - -////////////////////////////////////////////////////////////////////////////// - -bool Omegle_client::start() -{ - handle_entry( "start" ); - - this->server_ = get_server(); - //parent->debugLogA("Chosing server %s", this->server_.c_str()); - //std::string log = Translate("Chosing server: ") + this->server_; - //parent->UpdateChat(NULL, log.c_str()); - - std::string data; - - if (this->spy_mode_) { - //// get last server from list, which is for spy mode - //this->server_ = servers[_countof(servers)-1]; - - if (this->question_.empty()) { - data = "&wantsspy=1"; - } else { - data = "&ask=" + utils::url::encode(this->question_); - data += "&cansavequestion="; - data += db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_REUSE_QUESTION, 0) ? "1" : "0"; - } - } - else if ( db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_MEET_COMMON, 0)) - { - DBVARIANT dbv; - if (!db_get_utf(NULL, parent->m_szModuleName, OMEGLE_KEY_INTERESTS, &dbv)) - { - std::string topics = dbv.pszVal; - std::string topic; - - db_free(&dbv); - - std::string::size_type pos = 0; - std::string::size_type pos2 = 0; - while ((pos2 = topics.find(",", pos)) != std::string::npos) { - topic = topics.substr(pos, pos2 - pos); - topic = utils::text::trim(topic); - - if (!topic.empty()) { - if (pos > 0) - data += ","; - - data += "\"" + topic + "\""; - } - - pos = pos2 + 1; - } - - topic = topics.substr(pos); - topic = utils::text::trim(topic); - if (!topic.empty()) { - if (pos > 0) - data += ","; - data += "\"" + topic + "\""; - } - - parent->debugLogA("TOPICS: %s", data.c_str()); - - if (!data.empty()) { - data = "[" + data + "]"; - data = "&topics=" + utils::url::encode(data); - } - - //// get any server but last, which is for spy mode - //this->server_ = get_server(true); - } - } - - if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_SERVER_INFO, 0)) - { - std::string count = get_page( OMEGLE_REQUEST_COUNT ); - if (!count.empty()) { - char str[255]; - mir_snprintf(str, Translate("Connected to server %s. There are %s users online now."), server_.c_str(), count.c_str()); - - TCHAR *msg = mir_a2t(str); - parent->UpdateChat(NULL, msg); - mir_free(msg); - } - } else { - char str[255]; - mir_snprintf(str, Translate("Connected to server %s."), server_.c_str()); - - TCHAR *msg = mir_a2t(str); - parent->UpdateChat(NULL, msg); - mir_free(msg); - } - - // Send validation - http::response resp = flap( OMEGLE_REQUEST_START, NULL, &data ); - - switch ( resp.code ) - { - case HTTP_CODE_FAKE_DISCONNECTED: - { - // If is is only timeout error, try login once more - if ( handle_error( "start" )) - return start(); - else - return false; - } - - case HTTP_CODE_OK: - { - if (!resp.data.empty()) { - this->chat_id_ = resp.data.substr(1,resp.data.length()-2); - this->state_ = STATE_WAITING; - - return handle_success( "start" ); - } else { - return handle_error( "start", FORCE_DISCONNECT ); - } - } - - default: - return handle_error( "start", FORCE_DISCONNECT ); - } -} - -bool Omegle_client::stop() -{ - if ( parent->isOffline()) - return true; - - handle_entry( "stop" ); - - std::string data = "id=" + this->chat_id_; - - http::response resp = flap( OMEGLE_REQUEST_STOP, &data ); - - if (hConnection) - Netlib_CloseHandle(hConnection); - hConnection = NULL; - - if (hEventsConnection) - Netlib_CloseHandle(hEventsConnection); - hEventsConnection = NULL; - - if (resp.data == "win") { - return handle_success( "stop" ); - } else { - return handle_error( "stop" ); - } - -/* switch ( resp.code ) - { - case HTTP_CODE_OK: - case HTTP_CODE_FOUND: - - default: - - }*/ -} - -bool Omegle_client::events() -{ - handle_entry( "events" ); - - std::string data = "id=" + this->chat_id_; - - // Get update - http::response resp = flap( OMEGLE_REQUEST_EVENTS, &data ); - - // Return - switch ( resp.code ) - { - case HTTP_CODE_OK: - { - if ( resp.data == "null" ) { - // Everything is OK, no new message received -- OR it is a problem - // TODO: if we are waiting for Stranger with common likes, then we should try standard Stranger if this takes too long - return handle_error( "events" ); - } else if ( resp.data == "fail" ) { - // Something went wrong - return handle_error( "events" ); - } - - std::string::size_type pos = 0; - bool newStranger = false; - bool waiting = false; - - if ( resp.data.find( "[\"waiting\"]" ) != std::string::npos ) { - // We are just waiting for new Stranger - waiting = true; - } - - /*if ( (pos = resp.data.find( "[\"count\"," )) != std::string::npos ) { - // We got info about count of connected people there - pos += 9; - - std::string count = utils::text::trim( resp.data.substr(pos, resp.data.find("]", pos) - pos)); - - char str[255]; - mir_snprintf(str, Translate("On whole Omegle are %s strangers online now."), count.c_str()); - - TCHAR *msg = mir_a2t_cp(str,CP_UTF8); - parent->UpdateChat(NULL, msg); - mir_free(msg); - }*/ - - if ( (pos = resp.data.find( "[\"serverMessage\"," )) != std::string::npos ) { - // We got server message - pos += 18; - - std::string message = utils::text::trim( resp.data.substr(pos, resp.data.find("\"]", pos) - pos)); - TCHAR *tstr = Langpack_PcharToTchar(message.c_str()); - parent->UpdateChat(NULL, tstr); - mir_free(tstr); - } - - if ( resp.data.find( "[\"connected\"]" ) != std::string::npos ) { - // Stranger connected - if (this->spy_mode_ && !this->question_.empty()) { - parent->AddChatContact(TranslateT("Stranger 1")); - parent->AddChatContact(TranslateT("Stranger 2")); - this->state_ = STATE_SPY; - } else { - parent->AddChatContact(TranslateT("Stranger")); - this->state_ = STATE_ACTIVE; - } - - newStranger = true; - waiting = false; - } - - if ( (pos = resp.data.find( "[\"commonLikes\"," )) != std::string::npos ) { - pos += 17; - std::string like = resp.data.substr(pos, resp.data.find("\"]", pos) - pos); - utils::text::replace_all(&like, "\", \"", ", "); - - parent->debugLogA("Got common likes: '%s'", like.c_str()); - - like = Translate("You and the Stranger both like: ") + like; - - TCHAR *msg = mir_a2t(like.c_str()); - parent->SetTopic(msg); - mir_free(msg); - } - - if ( (pos = resp.data.find( "[\"question\"," )) != std::string::npos ) { - pos += 13; - - std::string question = utils::text::trim( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( - resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); - - TCHAR *msg = mir_a2t_cp(question.c_str(),CP_UTF8); - parent->SetTopic(msg); - mir_free(msg); - } - - if ( resp.data.find( "[\"typing\"]" ) != std::string::npos - || resp.data.find( "[\"spyTyping\"," ) != std::string::npos ) - { - // Stranger is typing, not supported by chat module yet - SkinPlaySound( "StrangerTyp" ); - - - StatusTextData st = { 0 }; - st.cbSize = sizeof(st); - // st.hIcon = IcoLib_GetIconByHandle(GetIconHandle("typing_on")); // TODO: typing icon - - mir_sntprintf(st.tszText, TranslateT("%s is typing."), TranslateT("Stranger")); - - CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), (LPARAM)&st); - } - - if ( resp.data.find( "[\"stoppedTyping\"]" ) != std::string::npos - || resp.data.find( "[\"spyStoppedTyping\"," ) != std::string::npos ) - { - // Stranger stopped typing, not supported by chat module yet - SkinPlaySound( "StrangerTypStop" ); - - StatusTextData st = { 0 }; - st.cbSize = sizeof(st); - // st.hIcon = IcoLib_GetIconByHandle(GetIconHandle("typing_off")); // TODO: typing icon - - mir_sntprintf(st.tszText, TranslateT("%s stopped typing."), TranslateT("Stranger")); - - CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), (LPARAM)&st); - } - - pos = 0; - while ( (pos = resp.data.find( "[\"gotMessage\",", pos )) != std::string::npos ) { - pos += 15; - - std::string message = utils::text::trim( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( - resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); - - if (state_ == STATE_ACTIVE) { - TCHAR *msg = mir_a2t_cp(message.c_str(),CP_UTF8); - parent->UpdateChat(TranslateT("Stranger"), msg); - mir_free(msg); - - CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), 0); - } - } - - pos = 0; - while ( (pos = resp.data.find( "[\"spyMessage\",", pos )) != std::string::npos ) { - pos += 15; - - std::string message = resp.data.substr(pos, resp.data.find("\"]", pos) - pos); - - if (state_ == STATE_SPY) { - std::string stranger = message.substr(0, message.find("\"")); - message = message.substr(stranger.length() + 4); - - message = utils::text::trim( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( message )) ); - - stranger = Translate(stranger.c_str()); - - TCHAR *str = mir_a2t_cp(stranger.c_str(), CP_UTF8); - TCHAR *msg = mir_a2t_cp(message.c_str(), CP_UTF8); - - parent->UpdateChat(str, msg); - - mir_free(msg); - mir_free(str); - } - } - - if ( resp.data.find( "[\"strangerDisconnected\"]" ) != std::string::npos ) { - // Stranger disconnected - if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_DONT_STOP, 0)) - { - SkinPlaySound( "StrangerChange" ); - parent->NewChat(); - } - else - parent->StopChat(false); - } - - if ( (pos = resp.data.find( "[\"spyDisconnected\"," )) != std::string::npos ) { - pos += 20; - - std::string stranger = utils::text::trim( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( - resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); - - char str[255]; - mir_snprintf(str, Translate("%s disconnected."), Translate(stranger.c_str())); - - TCHAR *msg = mir_a2t(str); - parent->UpdateChat(NULL, msg); - mir_free(msg); - - // Stranger disconnected - if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_DONT_STOP, 0)) - { - SkinPlaySound( "StrangerChange" ); - parent->NewChat(); - } - else - parent->StopChat(false); - } - - if ( resp.data.find( "[\"recaptchaRequired\"" ) != std::string::npos ) { - // Nothing to do with recaptcha - parent->UpdateChat(NULL, TranslateT("Recaptcha is required.\nOpen http://omegle.com , solve Recaptcha and try again.")); - parent->StopChat(false); - } - - if ( resp.data.find( "[\"recaptchaRejected\"]" ) != std::string::npos ) { - // Nothing to do with recaptcha - parent->StopChat(false); - } - - if ( (pos = resp.data.find( "[\"error\"," )) != std::string::npos ) { - pos += 10; - - std::string error = utils::text::trim( - utils::text::special_expressions_decode( - utils::text::slashu_to_utf8( - resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); - - error = Translate("Error: ") + error; - - TCHAR *msg = mir_a2t(error.c_str()); - parent->UpdateChat(NULL, msg); - mir_free(msg); - } - - if (newStranger && state_ != STATE_SPY) { - // We got new stranger in this event, lets say him "Hi message" if enabled - if ( db_get_b( NULL, parent->m_szModuleName, OMEGLE_KEY_HI_ENABLED, 0 )) { - DBVARIANT dbv; - if ( !db_get_utf( NULL, parent->m_szModuleName, OMEGLE_KEY_HI, &dbv )) { - std::string *message = new std::string(dbv.pszVal); - db_free(&dbv); - - parent->debugLogA("**Chat - saying Hi! message"); - parent->ForkThread(&OmegleProto::SendMsgWorker, message); - } - else parent->debugLogA("**Chat - Hi message is enabled but not used"); - } - } - - if (waiting) { - // If we are only waiting in this event... - parent->UpdateChat(NULL, TranslateT("We are still waiting...")); - } - - return handle_success( "events" ); - } - - case HTTP_CODE_FAKE_DISCONNECTED: - // timeout - return handle_success( "events" ); - - case HTTP_CODE_FAKE_ERROR: - default: - return handle_error( "events" ); - } -} - -bool Omegle_client::send_message(const std::string &message_text ) -{ - handle_entry( "send_message" ); - - std::string data = "msg=" + utils::url::encode( message_text ); - data += "&id=" + this->chat_id_; - - http::response resp = flap( OMEGLE_REQUEST_SEND, &data ); - - switch ( resp.code ) - { - case HTTP_CODE_OK: - if (resp.data == "win") { - return handle_success( "send_message" ); - } - - case HTTP_CODE_FAKE_ERROR: - case HTTP_CODE_FAKE_DISCONNECTED: - default: - return handle_error( "send_message" ); - } -} - -bool Omegle_client::typing_start() -{ - handle_entry( "typing_start" ); - - std::string data = "id=" + this->chat_id_; - - http::response resp = flap( OMEGLE_REQUEST_TYPING_START, &data ); - - switch ( resp.code ) - { - case HTTP_CODE_OK: - if (resp.data == "win") { - return handle_success( "typing_start" ); - } - - case HTTP_CODE_FAKE_ERROR: - case HTTP_CODE_FAKE_DISCONNECTED: - default: - return handle_error( "typing_start" ); - } -} - -bool Omegle_client::typing_stop() -{ - handle_entry( "typing_stop" ); - - std::string data = "id=" + this->chat_id_; - - http::response resp = flap( OMEGLE_REQUEST_TYPING_STOP, &data ); - - switch ( resp.code ) - { - case HTTP_CODE_OK: - if (resp.data == "win") { - return handle_success( "typing_stop" ); - } - - case HTTP_CODE_FAKE_ERROR: - case HTTP_CODE_FAKE_DISCONNECTED: - default: - return handle_error( "typing_stop" ); - } -} - -bool Omegle_client::recaptcha() -{ - // TODO: Implement! - - handle_entry( "recaptcha" ); - - // data:{id:this.clientID,challenge:b,response:a}} - //std::string data = "?id=...&challenge= ..., &response= ..."; - - http::response resp = flap( OMEGLE_REQUEST_RECAPTCHA ); - - switch ( resp.code ) - { - case HTTP_CODE_OK: -/* if (resp.data == "win") { - return handle_success( "typing_start" ); - }*/ - - case HTTP_CODE_FAKE_ERROR: - case HTTP_CODE_FAKE_DISCONNECTED: - default: - return handle_error( "typing_start" ); - } -} - -std::string Omegle_client::get_page(const int request_type) -{ - handle_entry("get_page"); - - http::response resp = flap(request_type); - - switch ( resp.code ) - { - case HTTP_CODE_OK: - handle_success("get_page"); - break; - - case HTTP_CODE_FAKE_ERROR: - case HTTP_CODE_FAKE_DISCONNECTED: - default: - handle_error("get_page"); - } - - return resp.data; -} +/* + +Omegle plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2011-15 Robert Pösel + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +http::response Omegle_client::flap(const int request_type, std::string *post_data, std::string *get_data) +{ + http::response resp; + + // Prepare the request + NETLIBHTTPREQUEST nlhr = { sizeof(NETLIBHTTPREQUEST) }; + + // Set request URL + std::string url = choose_server(request_type) + choose_action(request_type, get_data); + nlhr.szUrl = (char*)url.c_str(); + + // Set timeout (bigger for channel request) + nlhr.timeout = 1000 * ((request_type == OMEGLE_REQUEST_EVENTS) ? 65 : 20); + + // Set request type (GET/POST) and eventually also POST data + if (post_data != NULL) { + nlhr.requestType = REQUEST_POST; + nlhr.pData = (char*)(*post_data).c_str(); + nlhr.dataLength = (int)post_data->length(); + } + else { + nlhr.requestType = REQUEST_GET; + } + + // Set headers - it depends on requestType so it must be after setting that + nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount); + + // Set flags + nlhr.flags = NLHRF_HTTP11; + +#ifdef _DEBUG + nlhr.flags |= NLHRF_DUMPASTEXT; +#else + nlhr.flags |= NLHRF_NODUMP; +#endif + + // Set persistent connection (or not) + switch (request_type) + { + case OMEGLE_REQUEST_HOME: + nlhr.nlc = NULL; + break; + + case OMEGLE_REQUEST_EVENTS: + nlhr.nlc = hEventsConnection; + nlhr.flags |= NLHRF_PERSISTENT; + break; + + default: + WaitForSingleObject(connection_lock_, INFINITE); + nlhr.nlc = hConnection; + nlhr.flags |= NLHRF_PERSISTENT; + break; + } + + parent->debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl); + + // Send the request + NETLIBHTTPREQUEST *pnlhr = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)handle_, (LPARAM)&nlhr); + + mir_free(nlhr.headers); + + // Remember the persistent connection handle (or not) + switch ( request_type ) + { + case OMEGLE_REQUEST_HOME: + break; + + case OMEGLE_REQUEST_EVENTS: + hEventsConnection = pnlhr ? pnlhr->nlc : NULL; + break; + + default: + ReleaseMutex(connection_lock_); + hConnection = pnlhr ? pnlhr->nlc : NULL; + break; + } + + // Check and copy response data + if (pnlhr != NULL) + { + parent->debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode); + store_headers(&resp, pnlhr->headers, pnlhr->headersCount); + resp.code = pnlhr->resultCode; + resp.data = pnlhr->pData ? pnlhr->pData : ""; + + parent->debugLogA("&&&&& Got response: %s", resp.data.c_str()); + + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)pnlhr); + } else { + parent->debugLogA("!!!!! No response from server (time-out)"); + resp.code = HTTP_CODE_FAKE_DISCONNECTED; + // Better to have something set explicitely as this value is compaired in all communication requests + } + + return resp; +} + +bool Omegle_client::handle_entry(const std::string &method ) +{ + parent->debugLogA(" >> Entering %s()", method.c_str()); + return true; +} + +bool Omegle_client::handle_success(const std::string &method ) +{ + parent->debugLogA(" << Quitting %s()", method.c_str()); + reset_error(); + return true; +} + +bool Omegle_client::handle_error(const std::string &method, bool force_disconnect ) +{ + bool result; + increment_error(); + parent->debugLogA("!!!!! %s(): Something with Omegle went wrong", method.c_str()); + + if ( force_disconnect ) + result = false; + else if ( error_count_ <= (UINT)db_get_b(NULL,parent->m_szModuleName,OMEGLE_KEY_TIMEOUTS_LIMIT,OMEGLE_TIMEOUTS_LIMIT)) + result = true; + else + result = false; + + if ( result == false ) + { + reset_error(); + parent->UpdateChat(NULL, TranslateT("Connection error.")); + parent->StopChat(false); + } + + return result; +} + +////////////////////////////////////////////////////////////////////////////// + +std::string Omegle_client::get_server( bool not_last ) +{ + int q = not_last ? 1 : 0; + + int server = db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_SERVER, 0); + if (server < 0 || server >= (int)(_countof(servers)-q)) + server = 0; + + if (server == 0) { + srand(::time(NULL)); + server = (rand() % (_countof(servers)-1-q))+1; + } + + return servers[server]; +} + +std::string Omegle_client::get_language() +{ + int language = db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_LANGUAGE, 0); + if (language < 0 || language >= (_countof(languages))) + language = 0; + + return language > 0 ? languages[language].id : "en"; +} + +std::string Omegle_client::choose_server(int request_type) +{ + switch ( request_type ) + { + case OMEGLE_REQUEST_HOME: + return OMEGLE_SERVER_REGULAR; + +/* case OMEGLE_REQUEST_START: + case OMEGLE_REQUEST_STOP: + case OMEGLE_REQUEST_SEND: + case OMEGLE_REQUEST_EVENTS: + case OMEGLE_REQUEST_TYPING_START: + case OMEGLE_REQUEST_TYPING_STOP: + case OMEGLE_REQUEST_RECAPTCHA: + case OMEGLE_REQUEST_COUNT: +*/ default: + std::string server = OMEGLE_SERVER_CHAT; + utils::text::replace_first( &server, "%s", this->server_ ); + return server; + } +} + +std::string Omegle_client::choose_action(int request_type, std::string* get_data) +{ + switch ( request_type ) + { + case OMEGLE_REQUEST_START: + { + std::string action = "/start?rcs=1&spid=&lang="; + action += get_language(); + if (get_data != NULL) + action += (*get_data); + + return action; + } + + case OMEGLE_REQUEST_STOP: + return "/disconnect"; + + case OMEGLE_REQUEST_SEND: + return "/send"; + + case OMEGLE_REQUEST_EVENTS: + return "/events"; + + case OMEGLE_REQUEST_TYPING_START: + return "/typing"; + + case OMEGLE_REQUEST_TYPING_STOP: + return "/stoppedtyping"; + + case OMEGLE_REQUEST_RECAPTCHA: + return "/recaptcha"; + + case OMEGLE_REQUEST_COUNT: + return "/count"; + + // "/stoplookingforcommonlikes" + +/* case OMEGLE_REQUEST_HOME: +*/ default: + return "/"; + } +} + + +NETLIBHTTPHEADER* Omegle_client::get_request_headers( int request_type, int* headers_count ) +{ + if (request_type == REQUEST_POST) + *headers_count = 4; + else + *headers_count = 3; + + NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count)); + + if (request_type == REQUEST_POST) { + headers[3].szName = "Content-Type"; + headers[3].szValue = "application/x-www-form-urlencoded; charset=utf-8"; + } + + headers[2].szName = "User-Agent"; + headers[2].szValue = (char *)g_strUserAgent.c_str(); + headers[1].szName = "Accept"; + headers[1].szValue = "*/*"; + headers[0].szName = "Accept-Language"; + headers[0].szValue = "en,en-US;q=0.9"; + + return headers; +} + +void Omegle_client::store_headers( http::response* resp, NETLIBHTTPHEADER* headers, int headersCount ) +{ + for ( size_t i = 0; i < (size_t)headersCount; i++ ) + { + std::string header_name = headers[i].szName; + std::string header_value = headers[i].szValue; + + // TODO RM: (un)comment + //parent->debugLogA("----- Got header '%s': %s", header_name.c_str(), header_value.c_str()); + resp->headers[header_name] = header_value; + } +} + +////////////////////////////////////////////////////////////////////////////// + +bool Omegle_client::start() +{ + handle_entry( "start" ); + + this->server_ = get_server(); + //parent->debugLogA("Chosing server %s", this->server_.c_str()); + //std::string log = Translate("Chosing server: ") + this->server_; + //parent->UpdateChat(NULL, log.c_str()); + + std::string data; + + if (this->spy_mode_) { + //// get last server from list, which is for spy mode + //this->server_ = servers[_countof(servers)-1]; + + if (this->question_.empty()) { + data = "&wantsspy=1"; + } else { + data = "&ask=" + utils::url::encode(this->question_); + data += "&cansavequestion="; + data += db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_REUSE_QUESTION, 0) ? "1" : "0"; + } + } + else if ( db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_MEET_COMMON, 0)) + { + DBVARIANT dbv; + if (!db_get_utf(NULL, parent->m_szModuleName, OMEGLE_KEY_INTERESTS, &dbv)) + { + std::string topics = dbv.pszVal; + std::string topic; + + db_free(&dbv); + + std::string::size_type pos = 0; + std::string::size_type pos2 = 0; + while ((pos2 = topics.find(",", pos)) != std::string::npos) { + topic = topics.substr(pos, pos2 - pos); + topic = utils::text::trim(topic); + + if (!topic.empty()) { + if (pos > 0) + data += ","; + + data += "\"" + topic + "\""; + } + + pos = pos2 + 1; + } + + topic = topics.substr(pos); + topic = utils::text::trim(topic); + if (!topic.empty()) { + if (pos > 0) + data += ","; + data += "\"" + topic + "\""; + } + + parent->debugLogA("TOPICS: %s", data.c_str()); + + if (!data.empty()) { + data = "[" + data + "]"; + data = "&topics=" + utils::url::encode(data); + } + + //// get any server but last, which is for spy mode + //this->server_ = get_server(true); + } + } + + if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_SERVER_INFO, 0)) + { + std::string count = get_page( OMEGLE_REQUEST_COUNT ); + if (!count.empty()) { + char str[255]; + mir_snprintf(str, Translate("Connected to server %s. There are %s users online now."), server_.c_str(), count.c_str()); + + TCHAR *msg = mir_a2t(str); + parent->UpdateChat(NULL, msg); + mir_free(msg); + } + } else { + char str[255]; + mir_snprintf(str, Translate("Connected to server %s."), server_.c_str()); + + TCHAR *msg = mir_a2t(str); + parent->UpdateChat(NULL, msg); + mir_free(msg); + } + + // Send validation + http::response resp = flap( OMEGLE_REQUEST_START, NULL, &data ); + + switch ( resp.code ) + { + case HTTP_CODE_FAKE_DISCONNECTED: + { + // If is is only timeout error, try login once more + if ( handle_error( "start" )) + return start(); + else + return false; + } + + case HTTP_CODE_OK: + { + if (!resp.data.empty()) { + this->chat_id_ = resp.data.substr(1,resp.data.length()-2); + this->state_ = STATE_WAITING; + + return handle_success( "start" ); + } else { + return handle_error( "start", FORCE_DISCONNECT ); + } + } + + default: + return handle_error( "start", FORCE_DISCONNECT ); + } +} + +bool Omegle_client::stop() +{ + if ( parent->isOffline()) + return true; + + handle_entry( "stop" ); + + std::string data = "id=" + this->chat_id_; + + http::response resp = flap( OMEGLE_REQUEST_STOP, &data ); + + if (hConnection) + Netlib_CloseHandle(hConnection); + hConnection = NULL; + + if (hEventsConnection) + Netlib_CloseHandle(hEventsConnection); + hEventsConnection = NULL; + + if (resp.data == "win") { + return handle_success( "stop" ); + } else { + return handle_error( "stop" ); + } + +/* switch ( resp.code ) + { + case HTTP_CODE_OK: + case HTTP_CODE_FOUND: + + default: + + }*/ +} + +bool Omegle_client::events() +{ + handle_entry( "events" ); + + std::string data = "id=" + this->chat_id_; + + // Get update + http::response resp = flap( OMEGLE_REQUEST_EVENTS, &data ); + + // Return + switch ( resp.code ) + { + case HTTP_CODE_OK: + { + if ( resp.data == "null" ) { + // Everything is OK, no new message received -- OR it is a problem + // TODO: if we are waiting for Stranger with common likes, then we should try standard Stranger if this takes too long + return handle_error( "events" ); + } else if ( resp.data == "fail" ) { + // Something went wrong + return handle_error( "events" ); + } + + std::string::size_type pos = 0; + bool newStranger = false; + bool waiting = false; + + if ( resp.data.find( "[\"waiting\"]" ) != std::string::npos ) { + // We are just waiting for new Stranger + waiting = true; + } + + /*if ( (pos = resp.data.find( "[\"count\"," )) != std::string::npos ) { + // We got info about count of connected people there + pos += 9; + + std::string count = utils::text::trim( resp.data.substr(pos, resp.data.find("]", pos) - pos)); + + char str[255]; + mir_snprintf(str, Translate("On whole Omegle are %s strangers online now."), count.c_str()); + + TCHAR *msg = mir_a2t_cp(str,CP_UTF8); + parent->UpdateChat(NULL, msg); + mir_free(msg); + }*/ + + if ( (pos = resp.data.find( "[\"serverMessage\"," )) != std::string::npos ) { + // We got server message + pos += 18; + + std::string message = utils::text::trim( resp.data.substr(pos, resp.data.find("\"]", pos) - pos)); + TCHAR *tstr = Langpack_PcharToTchar(message.c_str()); + parent->UpdateChat(NULL, tstr); + mir_free(tstr); + } + + if ( resp.data.find( "[\"connected\"]" ) != std::string::npos ) { + // Stranger connected + if (this->spy_mode_ && !this->question_.empty()) { + parent->AddChatContact(TranslateT("Stranger 1")); + parent->AddChatContact(TranslateT("Stranger 2")); + this->state_ = STATE_SPY; + } else { + parent->AddChatContact(TranslateT("Stranger")); + this->state_ = STATE_ACTIVE; + } + + newStranger = true; + waiting = false; + } + + if ( (pos = resp.data.find( "[\"commonLikes\"," )) != std::string::npos ) { + pos += 17; + std::string like = resp.data.substr(pos, resp.data.find("\"]", pos) - pos); + utils::text::replace_all(&like, "\", \"", ", "); + + parent->debugLogA("Got common likes: '%s'", like.c_str()); + + like = Translate("You and the Stranger both like: ") + like; + + TCHAR *msg = mir_a2t(like.c_str()); + parent->SetTopic(msg); + mir_free(msg); + } + + if ( (pos = resp.data.find( "[\"question\"," )) != std::string::npos ) { + pos += 13; + + std::string question = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( + resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); + + TCHAR *msg = mir_a2t_cp(question.c_str(),CP_UTF8); + parent->SetTopic(msg); + mir_free(msg); + } + + if ( resp.data.find( "[\"typing\"]" ) != std::string::npos + || resp.data.find( "[\"spyTyping\"," ) != std::string::npos ) + { + // Stranger is typing, not supported by chat module yet + SkinPlaySound( "StrangerTyp" ); + + + StatusTextData st = { 0 }; + st.cbSize = sizeof(st); + // st.hIcon = IcoLib_GetIconByHandle(GetIconHandle("typing_on")); // TODO: typing icon + + mir_sntprintf(st.tszText, TranslateT("%s is typing."), TranslateT("Stranger")); + + CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), (LPARAM)&st); + } + + if ( resp.data.find( "[\"stoppedTyping\"]" ) != std::string::npos + || resp.data.find( "[\"spyStoppedTyping\"," ) != std::string::npos ) + { + // Stranger stopped typing, not supported by chat module yet + SkinPlaySound( "StrangerTypStop" ); + + StatusTextData st = { 0 }; + st.cbSize = sizeof(st); + // st.hIcon = IcoLib_GetIconByHandle(GetIconHandle("typing_off")); // TODO: typing icon + + mir_sntprintf(st.tszText, TranslateT("%s stopped typing."), TranslateT("Stranger")); + + CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), (LPARAM)&st); + } + + pos = 0; + while ( (pos = resp.data.find( "[\"gotMessage\",", pos )) != std::string::npos ) { + pos += 15; + + std::string message = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( + resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); + + if (state_ == STATE_ACTIVE) { + TCHAR *msg = mir_a2t_cp(message.c_str(),CP_UTF8); + parent->UpdateChat(TranslateT("Stranger"), msg); + mir_free(msg); + } + + CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), 0); + } + + pos = 0; + while ( (pos = resp.data.find( "[\"spyMessage\",", pos )) != std::string::npos ) { + pos += 15; + + std::string message = resp.data.substr(pos, resp.data.find("\"]", pos) - pos); + + if (state_ == STATE_SPY) { + std::string stranger = message.substr(0, message.find("\"")); + message = message.substr(stranger.length() + 4); + + message = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( message )) ); + + stranger = Translate(stranger.c_str()); + + TCHAR *str = mir_a2t_cp(stranger.c_str(), CP_UTF8); + TCHAR *msg = mir_a2t_cp(message.c_str(), CP_UTF8); + + parent->UpdateChat(str, msg); + + mir_free(msg); + mir_free(str); + } + } + + if ( resp.data.find( "[\"strangerDisconnected\"]" ) != std::string::npos ) { + CallService(MS_MSG_SETSTATUSTEXT, (WPARAM)parent->GetChatHandle(), NULL); + + // Stranger disconnected + if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_DONT_STOP, 0)) + { + SkinPlaySound( "StrangerChange" ); + parent->NewChat(); + } + else + parent->StopChat(false); + } + + if ( (pos = resp.data.find( "[\"spyDisconnected\"," )) != std::string::npos ) { + pos += 20; + + std::string stranger = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( + resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); + + char str[255]; + mir_snprintf(str, Translate("%s disconnected."), Translate(stranger.c_str())); + + TCHAR *msg = mir_a2t(str); + parent->UpdateChat(NULL, msg); + mir_free(msg); + + // Stranger disconnected + if (db_get_b(NULL, parent->m_szModuleName, OMEGLE_KEY_DONT_STOP, 0)) + { + SkinPlaySound( "StrangerChange" ); + parent->NewChat(); + } + else + parent->StopChat(false); + } + + if ( resp.data.find( "[\"recaptchaRequired\"" ) != std::string::npos ) { + // Nothing to do with recaptcha + parent->UpdateChat(NULL, TranslateT("Recaptcha is required.\nOpen http://omegle.com , solve Recaptcha and try again.")); + parent->StopChat(false); + } + + if ( resp.data.find( "[\"recaptchaRejected\"]" ) != std::string::npos ) { + // Nothing to do with recaptcha + parent->StopChat(false); + } + + if ( (pos = resp.data.find( "[\"error\"," )) != std::string::npos ) { + pos += 10; + + std::string error = utils::text::trim( + utils::text::special_expressions_decode( + utils::text::slashu_to_utf8( + resp.data.substr(pos, resp.data.find("\"]", pos) - pos) )) ); + + error = Translate("Error: ") + error; + + TCHAR *msg = mir_a2t(error.c_str()); + parent->UpdateChat(NULL, msg); + mir_free(msg); + } + + if (newStranger && state_ != STATE_SPY) { + // We got new stranger in this event, lets say him "Hi message" if enabled + if ( db_get_b( NULL, parent->m_szModuleName, OMEGLE_KEY_HI_ENABLED, 0 )) { + DBVARIANT dbv; + if ( !db_get_utf( NULL, parent->m_szModuleName, OMEGLE_KEY_HI, &dbv )) { + std::vector messages; + utils::text::explode(std::string(dbv.pszVal), "\r\n", &messages); + db_free(&dbv); + + int pos = rand() % messages.size(); + std::string *message = new std::string(messages.at(pos)); + + parent->debugLogA("**Chat - saying Hi! message"); + parent->ForkThread(&OmegleProto::SendMsgWorker, message); + } + else parent->debugLogA("**Chat - Hi message is enabled but not used"); + } + } + + if (waiting) { + // If we are only waiting in this event... + parent->UpdateChat(NULL, TranslateT("We are still waiting...")); + } + + return handle_success( "events" ); + } + + case HTTP_CODE_FAKE_DISCONNECTED: + // timeout + return handle_success( "events" ); + + case HTTP_CODE_FAKE_ERROR: + default: + return handle_error( "events" ); + } +} + +bool Omegle_client::send_message(const std::string &message_text ) +{ + handle_entry( "send_message" ); + + std::string data = "msg=" + utils::url::encode( message_text ); + data += "&id=" + this->chat_id_; + + http::response resp = flap( OMEGLE_REQUEST_SEND, &data ); + + switch ( resp.code ) + { + case HTTP_CODE_OK: + if (resp.data == "win") { + return handle_success( "send_message" ); + } + + case HTTP_CODE_FAKE_ERROR: + case HTTP_CODE_FAKE_DISCONNECTED: + default: + return handle_error( "send_message" ); + } +} + +bool Omegle_client::typing_start() +{ + handle_entry( "typing_start" ); + + std::string data = "id=" + this->chat_id_; + + http::response resp = flap( OMEGLE_REQUEST_TYPING_START, &data ); + + switch ( resp.code ) + { + case HTTP_CODE_OK: + if (resp.data == "win") { + return handle_success( "typing_start" ); + } + + case HTTP_CODE_FAKE_ERROR: + case HTTP_CODE_FAKE_DISCONNECTED: + default: + return handle_error( "typing_start" ); + } +} + +bool Omegle_client::typing_stop() +{ + handle_entry( "typing_stop" ); + + std::string data = "id=" + this->chat_id_; + + http::response resp = flap( OMEGLE_REQUEST_TYPING_STOP, &data ); + + switch ( resp.code ) + { + case HTTP_CODE_OK: + if (resp.data == "win") { + return handle_success( "typing_stop" ); + } + + case HTTP_CODE_FAKE_ERROR: + case HTTP_CODE_FAKE_DISCONNECTED: + default: + return handle_error( "typing_stop" ); + } +} + +bool Omegle_client::recaptcha() +{ + // TODO: Implement! + + handle_entry( "recaptcha" ); + + // data:{id:this.clientID,challenge:b,response:a}} + //std::string data = "?id=...&challenge= ..., &response= ..."; + + http::response resp = flap( OMEGLE_REQUEST_RECAPTCHA ); + + switch ( resp.code ) + { + case HTTP_CODE_OK: +/* if (resp.data == "win") { + return handle_success( "typing_start" ); + }*/ + + case HTTP_CODE_FAKE_ERROR: + case HTTP_CODE_FAKE_DISCONNECTED: + default: + return handle_error( "typing_start" ); + } +} + +std::string Omegle_client::get_page(const int request_type) +{ + handle_entry("get_page"); + + http::response resp = flap(request_type); + + switch ( resp.code ) + { + case HTTP_CODE_OK: + handle_success("get_page"); + break; + + case HTTP_CODE_FAKE_ERROR: + case HTTP_CODE_FAKE_DISCONNECTED: + default: + handle_error("get_page"); + } + + return resp.data; +} diff --git a/protocols/Omegle/src/messages.cpp b/protocols/Omegle/src/messages.cpp index 5eea9b5893..666229ebfd 100644 --- a/protocols/Omegle/src/messages.cpp +++ b/protocols/Omegle/src/messages.cpp @@ -1,79 +1,77 @@ -/* - -Omegle plugin for Miranda Instant Messenger -_____________________________________________ - -Copyright © 2011-15 Robert Pösel - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -*/ - -#include "stdafx.h" - -void OmegleProto::SendMsgWorker(void *p) -{ - if(p == NULL) - return; - - ScopedLock s( facy.send_message_lock_ ); - - std::string data = *(std::string*)p; - delete (std::string*)p; - - data = utils::text::trim(data); - - if (facy.state_ == STATE_ACTIVE && data.length() && facy.send_message( data )) - { - TCHAR *msg = mir_a2t_cp(data.c_str(), CP_UTF8); - UpdateChat(facy.nick_, msg); - mir_free(msg); - } -} - -void OmegleProto::SendTypingWorker(void *p) -{ - if (p == NULL) - return; - - // Save typing info - bool typ = (*static_cast(p) == PROTOTYPE_SELFTYPING_ON); - delete (int*)p; - - // Ignore same typing info - if (facy.typing_ == typ) - return; - - facy.typing_ = typ; - // Wait for eventually changes to typing info by other thread and ignore if changed - SleepEx(2000, true); - if (facy.typing_ != typ || facy.old_typing_ == typ || facy.state_ != STATE_ACTIVE) - return; - - facy.old_typing_ = typ; - if (typ) - facy.typing_start(); - else - facy.typing_stop(); -} - -void OmegleProto::NewChatWorker(void*) -{ - NewChat(); -} - -void OmegleProto::StopChatWorker(void*) -{ - StopChat(); -} +/* + +Omegle plugin for Miranda Instant Messenger +_____________________________________________ + +Copyright © 2011-15 Robert Pösel + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "stdafx.h" + +void OmegleProto::SendMsgWorker(void *p) +{ + if(p == NULL) + return; + + ScopedLock s( facy.send_message_lock_ ); + + std::string data = *(std::string*)p; + delete (std::string*)p; + + data = utils::text::trim(data); + + if (facy.state_ == STATE_ACTIVE && data.length() && facy.send_message( data )) + { + TCHAR *msg = mir_a2t_cp(data.c_str(), CP_UTF8); + UpdateChat(facy.nick_, msg); + mir_free(msg); + } +} + +void OmegleProto::SendTypingWorker(void *p) +{ + if (p == NULL) + return; + + // Save typing info + bool typ = (*static_cast(p) == PROTOTYPE_SELFTYPING_ON); + delete (int*)p; + + // Ignore same typing info + if (facy.typing_ == typ) + return; + + if (facy.state_ != STATE_ACTIVE) + return; + + facy.typing_ = typ; + + if (typ) + facy.typing_start(); + else + facy.typing_stop(); +} + +void OmegleProto::NewChatWorker(void*) +{ + NewChat(); +} + +void OmegleProto::StopChatWorker(void*) +{ + StopChat(); +} diff --git a/protocols/Omegle/src/stdafx.h b/protocols/Omegle/src/stdafx.h index 722a3520fe..58bd9ed275 100644 --- a/protocols/Omegle/src/stdafx.h +++ b/protocols/Omegle/src/stdafx.h @@ -29,6 +29,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include diff --git a/protocols/Omegle/src/utils.cpp b/protocols/Omegle/src/utils.cpp index 86db3feec1..0e5b4b2153 100644 --- a/protocols/Omegle/src/utils.cpp +++ b/protocols/Omegle/src/utils.cpp @@ -108,13 +108,29 @@ std::string utils::text::slashu_to_utf8(const std::string &data ) return new_string; } -std::string utils::text::trim(const std::string &data ) +std::string utils::text::trim(const std::string &data) { std::string spaces = " \t\r\n"; - std::string::size_type begin = data.find_first_not_of( spaces ); - std::string::size_type end = data.find_last_not_of( spaces ) + 1; + std::string::size_type begin = data.find_first_not_of(spaces); + std::string::size_type end = data.find_last_not_of(spaces); - return (begin != std::string::npos) ? data.substr( begin, end - begin ) : ""; + return (end != std::string::npos) ? data.substr(begin, end + 1 - begin) : ""; +} + +void utils::text::explode(std::string str, std::string separator, std::vector* results) +{ + std::string::size_type pos; + pos = str.find_first_of(separator); + while (pos != std::string::npos) { + if (pos > 0) { + results->push_back(str.substr(0, pos)); + } + str = str.substr(pos + 1); + pos = str.find_first_of(separator); + } + if (str.length() > 0) { + results->push_back(str); + } } int utils::debug::log(const std::string &file_name, const std::string &text) diff --git a/protocols/Omegle/src/utils.h b/protocols/Omegle/src/utils.h index cd7dacbcd0..578d2874a7 100644 --- a/protocols/Omegle/src/utils.h +++ b/protocols/Omegle/src/utils.h @@ -37,6 +37,7 @@ namespace utils std::string special_expressions_decode( std::string data ); std::string slashu_to_utf8(const std::string &data ); std::string trim(const std::string &data ); + void explode(std::string str, std::string separator, std::vector* results); }; namespace debug -- cgit v1.2.3