summaryrefslogtreecommitdiff
path: root/protocols/Omegle
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Omegle')
-rw-r--r--protocols/Omegle/res/omegle.rc11
-rw-r--r--protocols/Omegle/src/client.h3
-rw-r--r--protocols/Omegle/src/communication.cpp1654
-rw-r--r--protocols/Omegle/src/messages.cpp156
-rw-r--r--protocols/Omegle/src/stdafx.h1
-rw-r--r--protocols/Omegle/src/utils.cpp24
-rw-r--r--protocols/Omegle/src/utils.h1
7 files changed, 935 insertions, 915 deletions
diff --git a/protocols/Omegle/res/omegle.rc b/protocols/Omegle/res/omegle.rc
index c8169d10cd..b48b175db7 100644
--- a/protocols/Omegle/res/omegle.rc
+++ b/protocols/Omegle/res/omegle.rc
@@ -71,10 +71,10 @@ BEGIN
EDITTEXT IDC_NAME,84,22,79,14,ES_AUTOHSCROLL
CONTROL "Meet strangers with common interests (separated by commas):",IDC_MEET_COMMON,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,39,288,10
- EDITTEXT IDC_INTERESTS,14,49,288,20,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
- CONTROL "Automatically send this message to stranger after connection:",IDC_HI_ENABLED,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,72,288,10
- EDITTEXT IDC_HI_MESSAGE,14,82,288,20,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
+ EDITTEXT IDC_INTERESTS,14,49,288,14,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
+ CONTROL "Automatically send one of these messages (each on new line) to stranger after connection:",IDC_HI_ENABLED,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,14,65,288,15
+ EDITTEXT IDC_HI_MESSAGE,14,82,288,20,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
LTEXT "This text will be sent when you use ""/asl"" message:",IDC_STATIC,14,105,288,8
EDITTEXT IDC_ASL_MESSAGE,14,114,288,20,ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL
LTEXT "Last used question (Question mode):",IDC_STATIC,14,136,288,8
@@ -150,8 +150,7 @@ END
//
// Generated from the TEXTINCLUDE 3 resource.
//
-
-
+
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
+*/
+
+#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<std::string> 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 <http://www.gnu.org/licenses/>.
-
-*/
-
-#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<int*>(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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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<int*>(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 <http://www.gnu.org/licenses/>.
#include <sstream>
#include <fstream>
#include <map>
+#include <vector>
#include <stdarg.h>
#include <time.h>
#include <assert.h>
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<std::string>* 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<std::string>* results);
};
namespace debug