summaryrefslogtreecommitdiff
path: root/protocols/Omegle/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Omegle/src')
-rw-r--r--protocols/Omegle/src/chat.cpp405
-rw-r--r--protocols/Omegle/src/client.h123
-rw-r--r--protocols/Omegle/src/common.h85
-rw-r--r--protocols/Omegle/src/communication.cpp816
-rw-r--r--protocols/Omegle/src/connection.cpp179
-rw-r--r--protocols/Omegle/src/constants.h55
-rw-r--r--protocols/Omegle/src/db.h55
-rw-r--r--protocols/Omegle/src/dialogs.cpp231
-rw-r--r--protocols/Omegle/src/dialogs.h26
-rw-r--r--protocols/Omegle/src/events.cpp39
-rw-r--r--protocols/Omegle/src/http.cpp23
-rw-r--r--protocols/Omegle/src/http.h48
-rw-r--r--protocols/Omegle/src/main.cpp146
-rw-r--r--protocols/Omegle/src/messages.cpp92
-rw-r--r--protocols/Omegle/src/process.cpp77
-rw-r--r--protocols/Omegle/src/proto.cpp259
-rw-r--r--protocols/Omegle/src/proto.h150
-rw-r--r--protocols/Omegle/src/resource.h31
-rw-r--r--protocols/Omegle/src/stubs.cpp173
-rw-r--r--protocols/Omegle/src/theme.cpp115
-rw-r--r--protocols/Omegle/src/theme.h30
-rw-r--r--protocols/Omegle/src/utils.cpp150
-rw-r--r--protocols/Omegle/src/utils.h103
23 files changed, 3411 insertions, 0 deletions
diff --git a/protocols/Omegle/src/chat.cpp b/protocols/Omegle/src/chat.cpp
new file mode 100644
index 0000000000..7b16ccdfc3
--- /dev/null
+++ b/protocols/Omegle/src/chat.cpp
@@ -0,0 +1,405 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+void OmegleProto::UpdateChat(const TCHAR *name, const TCHAR *message, bool addtolog)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.ptszText = message;
+ gce.time = ::time(NULL);
+ gce.dwFlags = GC_TCHAR;
+ gcd.iType = GC_EVENT_MESSAGE;
+
+ if (name == NULL) {
+ gcd.iType = GC_EVENT_INFORMATION;
+ name = TranslateT("Server");
+ gce.bIsMe = false;
+ } else {
+ gce.bIsMe = !_tcscmp(name, this->facy.nick_);
+ }
+
+ if (addtolog)
+ gce.dwFlags |= GCEF_ADDTOLOG;
+
+ gce.ptszNick = name;
+ gce.ptszUID = gce.ptszNick;
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+}
+
+int OmegleProto::OnChatEvent(WPARAM wParam,LPARAM lParam)
+{
+ GCHOOK *hook = reinterpret_cast<GCHOOK*>(lParam);
+
+ if(strcmp(hook->pDest->pszModule,m_szModuleName))
+ return 0;
+
+ switch(hook->pDest->iType)
+ {
+ case GC_USER_MESSAGE:
+ {
+ std::string text = mir_t2a_cp(hook->ptszText,CP_UTF8);
+
+ if (text.empty())
+ break;
+
+ if (text.substr(0,1) == "/")
+ { // Process commands
+
+ std::string command = "";
+ std::string params = "";
+
+ std::string::size_type pos = 0;
+ if ((pos = text.find(" ")) != std::string::npos) {
+ command = text.substr(1, pos-1);
+ params = text.substr(pos+1);
+ } else {
+ command = text.substr(1);
+ }
+
+ if (!stricmp(command.c_str(), "new"))
+ {
+ facy.spy_mode_ = false;
+ facy.question_ = "";
+
+ ForkThread(&OmegleProto::NewChatWorker, this, NULL);
+ break;
+ }
+ else if (!stricmp(command.c_str(), "quit"))
+ {
+ ForkThread(&OmegleProto::StopChatWorker, this, NULL);
+ break;
+ }
+ else if (!stricmp(command.c_str(), "spy"))
+ {
+ facy.spy_mode_ = true;
+ facy.question_ = "";
+
+ ForkThread(&OmegleProto::NewChatWorker, this, NULL);
+ break;
+ }
+ else if (!stricmp(command.c_str(), "ask"))
+ {
+ if (params.empty()) {
+ // Load last question
+ DBVARIANT dbv;
+ if ( !getU8String( OMEGLE_KEY_LAST_QUESTION,&dbv )) {
+ params = dbv.pszVal;
+ DBFreeVariant(&dbv);
+ }
+
+ if (params.empty()) {
+ UpdateChat(NULL, TranslateT("Last question is empty."), false);
+ break;
+ }
+ } else {
+ // Save actual question as last question
+ if (strlen(params.c_str()) >= OMEGLE_QUESTION_MIN_LENGTH)
+ {
+ setU8String( OMEGLE_KEY_LAST_QUESTION, params.c_str());
+ }
+ }
+
+ if (strlen(params.c_str()) < OMEGLE_QUESTION_MIN_LENGTH)
+ {
+ UpdateChat(NULL, TranslateT("Your question is too short."), false);
+ break;
+ }
+
+ facy.spy_mode_ = true;
+ facy.question_ = params;
+ ForkThread(&OmegleProto::NewChatWorker, this, NULL);
+ break;
+ }
+ else if (!stricmp(command.c_str(), "asl"))
+ {
+ DBVARIANT dbv;
+ if ( !getU8String( OMEGLE_KEY_ASL,&dbv )) {
+ text = dbv.pszVal;
+ DBFreeVariant(&dbv);
+ } else {
+ UpdateChat(NULL, TranslateT("Your '/asl' setting is empty."), false);
+ break;
+ }
+ }
+ else if (!stricmp(command.c_str(), "help"))
+ {
+ UpdateChat(NULL, TranslateT("There are three different modes of chatting:\
+\n1) Standard mode\t - You chat with random stranger privately\
+\n2) Question mode\t - You ask two strangers a question and see how they discuss it (you can't join their conversation, only watch)\
+\n3) Spy mode\t - You and stranger got a question to discuss from third stranger (he can't join your conversation, only watch)\
+\n\nSend '/commands' for available commands."), false);
+ }
+ else if (!stricmp(command.c_str(), "commands"))
+ {
+ UpdateChat(NULL, TranslateT("You can use different commands:\
+\n/help\t - show info about chat modes\
+\n/new\t - start standard mode\
+\n/ask <question> - start question mode with your question\
+\n/ask\t - start question mode with your last asked question\
+\n/spy\t - start spy mode\
+\n/quit\t - disconnect from stranger or stop connecting\
+\n/asl\t - send your predefined ASL message\
+\n\nNote: You can reconnect to different stranger without disconnecting from current one."), false);
+ break;
+ }
+ else
+ {
+ UpdateChat(NULL, TranslateT("Unknown command. Send '/commands' for list."), false);
+ break;
+ }
+
+ }
+
+ // Outgoing message
+ switch (facy.state_)
+ {
+ case STATE_ACTIVE:
+ LOG("**Chat - Outgoing message: %s", text.c_str());
+ ForkThread(&OmegleProto::SendMsgWorker, this, (void*)new std::string(text));
+ break;
+
+ case STATE_INACTIVE:
+ UpdateChat(NULL, TranslateT("You aren't connected to any stranger. Send '/help' or '/commands' for help."), false);
+ break;
+
+ case STATE_SPY:
+ UpdateChat(NULL, TranslateT("You can't send messages in question mode."), false);
+ break;
+
+ //case STATE_WAITING:
+ //case STATE_DISCONNECTING:
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case GC_USER_TYPNOTIFY:
+ if ( facy.state_ == STATE_ACTIVE )
+ ForkThread(&OmegleProto::SendTypingWorker, this, (void*)mir_tstrdup(hook->ptszText));
+ break;
+
+ case GC_USER_LEAVE:
+ case GC_SESSION_TERMINATE:
+ mir_free( facy.nick_ );
+ ForkThread(&OmegleProto::StopChatWorker, this, NULL);
+ break;
+ }
+
+ return 0;
+}
+
+/*void OmegleProto::SendChatEvent(int type)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.pDest = &gcd;
+
+ CallServiceSync(MS_GC_EVENT,WINDOW_CLEARLOG,reinterpret_cast<LPARAM>(&gce));
+}*/
+
+void OmegleProto::AddChatContact(const TCHAR *name)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_JOIN;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR | GCEF_ADDTOLOG;
+ gce.ptszNick = name;
+ gce.ptszUID = gce.ptszNick;
+ gce.time = static_cast<DWORD>(time(0));
+
+ if (name == NULL)
+ gce.bIsMe = false;
+ else
+ gce.bIsMe = !_tcscmp(name, this->facy.nick_);
+
+ if (gce.bIsMe)
+ gce.ptszStatus = _T("Admin");
+ else
+ gce.ptszStatus = _T("Normal");
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+}
+
+void OmegleProto::DeleteChatContact(const TCHAR *name)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_PART;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR | GCEF_ADDTOLOG;
+ gce.ptszNick = name;
+ gce.ptszUID = gce.ptszNick;
+ gce.time = static_cast<DWORD>(time(0));
+ if (name == NULL)
+ gce.bIsMe = false;
+ else
+ gce.bIsMe = !_tcscmp(name, this->facy.nick_);
+
+ CallServiceSync(MS_GC_EVENT,0,reinterpret_cast<LPARAM>(&gce));
+}
+
+int OmegleProto::OnJoinChat(WPARAM,LPARAM suppress)
+{
+ GCSESSION gcw = {sizeof(gcw)};
+
+ // Create the group chat session
+ gcw.dwFlags = GC_TCHAR;
+ gcw.iType = GCW_CHATROOM;
+ gcw.pszModule = m_szModuleName;
+ gcw.ptszName = m_tszUserName;
+ gcw.ptszID = m_tszUserName;
+ CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
+
+ if(m_iStatus == ID_STATUS_OFFLINE)
+ return 0;
+
+ // Create a group
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR;
+
+ gcd.iType = GC_EVENT_ADDGROUP;
+
+ gce.ptszStatus = _T("Admin");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
+
+ gce.ptszStatus = _T("Normal");
+ CallServiceSync( MS_GC_EVENT, NULL, reinterpret_cast<LPARAM>(&gce));
+
+ SetTopic();
+
+ // Note: Initialization will finish up in SetChatStatus, called separately
+ if (!suppress)
+ SetChatStatus(m_iStatus);
+
+ return 0;
+}
+
+void OmegleProto::SetTopic(const TCHAR *topic)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_TOPIC;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.pDest = &gcd;
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+
+ if (topic == NULL)
+ gce.ptszText = TranslateT("Omegle is a great way of meeting new friends!");
+ else
+ gce.ptszText = topic;
+
+ CallServiceSync(MS_GC_EVENT,0, reinterpret_cast<LPARAM>(&gce));
+}
+
+int OmegleProto::OnLeaveChat(WPARAM,LPARAM)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+ gce.pDest = &gcd;
+
+ CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE, reinterpret_cast<LPARAM>(&gce));
+ CallServiceSync(MS_GC_EVENT,SESSION_TERMINATE,reinterpret_cast<LPARAM>(&gce));
+
+ return 0;
+}
+
+void OmegleProto::SetChatStatus(int status)
+{
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.time = ::time(NULL);
+ gce.pDest = &gcd;
+
+ if(status == ID_STATUS_ONLINE)
+ {
+ // Free previously loaded name
+ mir_free(facy.nick_);
+
+ // Load actual name from database
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, m_szModuleName, OMEGLE_KEY_NAME, &dbv))
+ {
+ facy.nick_ = mir_tstrdup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else {
+ facy.nick_ = mir_tstrdup(TranslateT("You"));
+ DBWriteContactSettingTString(NULL, m_szModuleName, OMEGLE_KEY_NAME, facy.nick_);
+ }
+
+ // Add self contact
+ AddChatContact(facy.nick_);
+
+ CallServiceSync(MS_GC_EVENT,SESSION_INITDONE,reinterpret_cast<LPARAM>(&gce));
+ CallServiceSync(MS_GC_EVENT,SESSION_ONLINE, reinterpret_cast<LPARAM>(&gce));
+ }
+ else
+ {
+ CallServiceSync(MS_GC_EVENT,SESSION_OFFLINE,reinterpret_cast<LPARAM>(&gce));
+ }
+}
+
+void OmegleProto::ClearChat()
+{
+ if (getByte(OMEGLE_KEY_NO_CLEAR, 0))
+ return;
+
+ GCDEST gcd = { m_szModuleName };
+ gcd.ptszID = const_cast<TCHAR*>(m_tszUserName);
+ gcd.iType = GC_EVENT_CONTROL;
+
+ GCEVENT gce = {sizeof(gce)};
+ gce.dwFlags = GC_TCHAR;
+ gce.pDest = &gcd;
+
+ CallServiceSync(MS_GC_EVENT,WINDOW_CLEARLOG,reinterpret_cast<LPARAM>(&gce));
+} \ No newline at end of file
diff --git a/protocols/Omegle/src/client.h b/protocols/Omegle/src/client.h
new file mode 100644
index 0000000000..be5ec9055c
--- /dev/null
+++ b/protocols/Omegle/src/client.h
@@ -0,0 +1,123 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+#define FORCE_DISCONNECT true
+
+#define STATE_INACTIVE 0 // not connected to any stranger
+#define STATE_WAITING 1 // connecting to stranger
+#define STATE_ACTIVE 2 // active discussion
+#define STATE_DISCONNECTING 3 // disconnecting from stranger
+#define STATE_SPY 4 // spy mode (read-only)
+
+class Omegle_client
+{
+public:
+
+ // Client definition
+ Omegle_client( )
+ {
+ chat_id_ = server_ = question_ = "";
+ nick_ = NULL;
+ //msgid_ = 0;
+ send_message_lock_ = NULL;
+ state_ = STATE_INACTIVE;
+
+ old_typing_ = typing_ = spy_mode_ = false;
+
+ hConnection = NULL;
+ hEventsConnection = NULL;
+ connection_lock_ = NULL;
+ }
+
+ HANDLE hConnection;
+ HANDLE hEventsConnection;
+ HANDLE connection_lock_;
+
+ // Parent handle
+ OmegleProto* parent;
+
+ // Chat data
+ std::string chat_id_;
+ std::string server_;
+ std::string question_;
+ TCHAR *nick_;
+
+ HANDLE send_message_lock_;
+ //int msgid_;
+
+ // State of client
+ int state_;
+ bool typing_;
+ bool old_typing_;
+ bool spy_mode_;
+
+ // Data storage
+ std::map< std::string, std::string > headers;
+ void store_headers( http::response* resp, NETLIBHTTPHEADER* headers, int headers_count );
+
+ std::string get_server( bool not_last = false );
+
+ // Connection handling
+ unsigned int error_count_;
+
+ bool handle_entry( std::string method );
+ bool handle_success( std::string method );
+ bool handle_error( std::string method, bool force_disconnect = false );
+
+ void __inline increment_error( ) { error_count_++; }
+ void __inline decrement_error( ) { if ( error_count_ > 0 ) error_count_--; }
+ void __inline reset_error( ) { error_count_ = 0; }
+
+ bool start( );
+ bool stop( );
+ bool events( );
+
+ bool typing_start( );
+ bool typing_stop( );
+ bool recaptcha( );
+
+ std::string get_page( int );
+
+ bool send_message( std::string message_text );
+
+ // HTTP communication
+ http::response flap( const int request_type, std::string* request_data = NULL, std::string* get_data = NULL );
+
+ int choose_method( int );
+ std::string choose_proto( int );
+ std::string choose_server( int, std::string* data = NULL, std::string* get_data = NULL );
+ std::string choose_action( int, std::string* data = NULL, std::string* get_data = NULL );
+ std::string choose_request_url( int, std::string* data = NULL, std::string* get_data = NULL );
+
+ NETLIBHTTPHEADER* get_request_headers( int request_type, int* headers_count );
+
+ // Netlib handle
+
+ HANDLE handle_;
+
+ void set_handle(HANDLE h)
+ {
+ handle_ = h;
+ }
+};
diff --git a/protocols/Omegle/src/common.h b/protocols/Omegle/src/common.h
new file mode 100644
index 0000000000..acd913f180
--- /dev/null
+++ b/protocols/Omegle/src/common.h
@@ -0,0 +1,85 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+#pragma warning(disable:4996)
+
+#define MIRANDA_VER 0x0A00
+#define _WIN32_WINNT 0x0500
+#define _WIN32_WINDOWS 0x0500
+
+#include <m_stdhdr.h>
+
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <fstream>
+#include <map>
+#include <stdarg.h>
+#include <time.h>
+#include <assert.h>
+#include <io.h>
+
+#include <windows.h>
+#include <win2k.h>
+#include <commctrl.h>
+
+#include <newpluginapi.h>
+#include <m_version.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_chat.h>
+#include <m_clistint.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_netlib.h>
+#include <m_options.h>
+#include <m_popup.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_protoint.h>
+#include <m_protomod.h>
+#include <m_skin.h>
+#include <statusmodes.h>
+#include <m_icolib.h>
+#include <m_utils.h>
+#include <m_hotkeys.h>
+//#include <m_msg_buttonsbar.h>
+
+class OmegleProto;
+
+#define LOG Log
+
+#include "http.h"
+#include "utils.h"
+#include "client.h"
+#include "proto.h"
+#include "db.h"
+#include "constants.h"
+#include "dialogs.h"
+#include "theme.h"
+#include "resource.h"
+
+extern HINSTANCE g_hInstance;
+extern std::string g_strUserAgent;
+extern DWORD g_mirandaVersion; \ No newline at end of file
diff --git a/protocols/Omegle/src/communication.cpp b/protocols/Omegle/src/communication.cpp
new file mode 100644
index 0000000000..047e6177a3
--- /dev/null
+++ b/protocols/Omegle/src/communication.cpp
@@ -0,0 +1,816 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+http::response Omegle_client::flap( const int request_type, std::string* request_data, std::string* get_data )
+{
+ NETLIBHTTPREQUEST nlhr = {sizeof( NETLIBHTTPREQUEST )};
+ nlhr.requestType = choose_method( request_type );
+ std::string url = choose_request_url( request_type, request_data, get_data );
+ nlhr.szUrl = (char*)url.c_str( );
+ nlhr.flags = NLHRF_HTTP11 | NLHRF_NODUMP;
+ nlhr.headers = get_request_headers( request_type, &nlhr.headersCount );
+ nlhr.timeout = 1000 * (( request_type == OMEGLE_REQUEST_EVENTS ) ? 60 : 15);
+
+ if ( request_data != NULL )
+ {
+ nlhr.pData = (char*)(*request_data).c_str();
+ nlhr.dataLength = (int)request_data->length( );
+ }
+
+ parent->Log("@@@@@ Sending request to '%s'", nlhr.szUrl);
+
+ 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;
+ }
+
+ NETLIBHTTPREQUEST* pnlhr = ( NETLIBHTTPREQUEST* )CallService( MS_NETLIB_HTTPTRANSACTION, (WPARAM)handle_, (LPARAM)&nlhr );
+
+ http::response resp;
+
+ 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;
+ }
+
+ if ( pnlhr != NULL )
+ {
+ parent->Log("@@@@@ 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->Log("&&&&& Got response: %s", resp.data.c_str());
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)pnlhr);
+ } else {
+ parent->Log("!!!!! 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( std::string method )
+{
+ parent->Log(" >> Entering %s()", method.c_str());
+ return true;
+}
+
+bool Omegle_client::handle_success( std::string method )
+{
+ parent->Log(" << Quitting %s()", method.c_str());
+ reset_error();
+ return true;
+}
+
+bool Omegle_client::handle_error( std::string method, bool force_disconnect )
+{
+ bool result;
+ increment_error();
+ parent->Log("!!!!! %s(): Something with Omegle went wrong", method.c_str());
+
+ if ( force_disconnect )
+ result = false;
+ else if ( error_count_ <= (UINT)DBGetContactSettingByte(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 )
+{
+ BYTE q = not_last ? 1 : 0;
+
+ BYTE server = DBGetContactSettingByte(NULL, parent->m_szModuleName, OMEGLE_KEY_SERVER, 0);
+ if (server < 0 || server >= (SIZEOF(servers)-q))
+ server = 0;
+
+ if (server == 0) {
+ srand(::time(NULL));
+ server = (rand() % (SIZEOF(servers)-1-q))+1;
+ }
+
+ return servers[server];
+}
+
+int Omegle_client::choose_method( int request_type )
+{
+ switch ( request_type )
+ {
+ case OMEGLE_REQUEST_HOME:
+ case OMEGLE_REQUEST_COUNT:
+ return REQUEST_GET;
+
+/* 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:
+*/ default:
+ return REQUEST_POST;
+ }
+}
+
+std::string Omegle_client::choose_server( int request_type, std::string* data, std::string* get_data )
+{
+ 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* data, std::string* get_data )
+{
+ switch ( request_type )
+ {
+ case OMEGLE_REQUEST_START:
+ {
+ std::string action = "/start?rcs=1&spid=";
+ 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 "/";
+ }
+}
+
+std::string Omegle_client::choose_request_url( int request_type, std::string* data, std::string* get_data )
+{
+ std::string url = "";
+ url.append( choose_server( request_type, data, get_data ));
+ url.append( choose_action( request_type, data, get_data ));
+ return url;
+}
+
+NETLIBHTTPHEADER* Omegle_client::get_request_headers( int request_type, int* headers_count )
+{
+ switch ( request_type )
+ {
+ 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:
+ *headers_count = 4;
+ break;
+
+ case OMEGLE_REQUEST_HOME:
+ case OMEGLE_REQUEST_COUNT:
+ default:
+ *headers_count = 3;
+ break;
+ }
+
+ NETLIBHTTPHEADER* headers = ( NETLIBHTTPHEADER* )utils::mem::allocate( sizeof( NETLIBHTTPHEADER )*( *headers_count ));
+
+ switch ( request_type )
+ {
+ 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:
+ headers[3].szName = "Content-Type";
+ headers[3].szValue = "application/x-www-form-urlencoded; charset=utf-8";
+
+ case OMEGLE_REQUEST_HOME:
+ case OMEGLE_REQUEST_COUNT:
+ default:
+ 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";
+ break;
+ }
+
+ return headers;
+}
+
+void Omegle_client::store_headers( http::response* resp, NETLIBHTTPHEADER* headers, int headersCount )
+{
+ for ( int i = 0; i < headersCount; i++ )
+ {
+ std::string header_name = headers[i].szName;
+ std::string header_value = headers[i].szValue;
+
+ // TODO RM: (un)comment
+ //parent->Log("----- 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->Log("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[SIZEOF(servers)-1];
+
+ if (this->question_.empty()) {
+ data = "&wantsspy=1";
+ } else {
+ data = "&ask=" + utils::url::encode(this->question_);
+ data += "&cansavequestion=";
+ data += DBGetContactSettingByte(NULL, parent->m_szModuleName, OMEGLE_KEY_REUSE_QUESTION, 0) ? "1" : "0";
+ }
+ }
+ else if ( DBGetContactSettingByte(NULL, parent->m_szModuleName, OMEGLE_KEY_MEET_COMMON, 0))
+ {
+ DBVARIANT dbv;
+ if (!DBGetContactSettingUTF8String(NULL, parent->m_szModuleName, OMEGLE_KEY_INTERESTS, &dbv))
+ {
+ std::string topics = dbv.pszVal;
+ std::string topic;
+
+ DBFreeVariant(&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->Log("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 (DBGetContactSettingByte(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, sizeof(str), Translate("Connected to server %s. There are %s users online now."), server_.c_str(), count.c_str());
+
+ TCHAR *msg = mir_a2t_cp(str,CP_UTF8);
+ parent->UpdateChat(NULL, msg);
+ mir_free(msg);
+ }
+ } else {
+ char str[255];
+ mir_snprintf(str, sizeof(str), Translate("Connected to server %s."), server_.c_str());
+
+ TCHAR *msg = mir_a2t_cp(str,CP_UTF8);
+ 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, sizeof(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 ( 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 += 18;
+ std::string like = resp.data.substr(pos, resp.data.find("\"]", pos) - pos);
+ utils::text::replace_all(&like, "\", \"", ", ");
+
+ parent->Log("Got common likes: '%s'", like.c_str());
+
+ like = Translate("You and the Stranger both like: ") + like;
+
+ TCHAR *msg = mir_a2t_cp(like.c_str(),CP_UTF8);
+ parent->SetTopic(msg);
+ mir_free(msg);
+ }
+
+ if ( (pos = resp.data.find( "[\"question\"," )) != std::string::npos ) {
+ pos += 14;
+
+ 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" );
+ }
+
+ 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" );
+ }
+
+ pos = 0;
+ while ( (pos = resp.data.find( "[\"gotMessage\",", pos )) != std::string::npos ) {
+ pos += 16;
+
+ 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);
+ }
+ }
+
+ pos = 0;
+ while ( (pos = resp.data.find( "[\"spyMessage\",", pos )) != std::string::npos ) {
+ pos += 16;
+
+ 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 (DBGetContactSettingByte(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 += 21;
+
+ 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, sizeof(str), Translate("%s disconnected."), Translate(stranger.c_str()));
+
+ TCHAR *msg = mir_a2t_cp(str, CP_UTF8);
+ parent->UpdateChat(NULL, msg);
+ mir_free(msg);
+
+ // Stranger disconnected
+ if (DBGetContactSettingByte(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 += 11;
+
+ 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_cp(error.c_str(),CP_UTF8);
+ 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 ( DBGetContactSettingByte( NULL, parent->m_szModuleName, OMEGLE_KEY_HI_ENABLED, 0 )) {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingUTF8String( NULL, parent->m_szModuleName, OMEGLE_KEY_HI, &dbv )) {
+ std::string *message = new std::string(dbv.pszVal);
+ DBFreeVariant(&dbv);
+
+ parent->Log("**Chat - saying Hi! message");
+ ForkThread(&OmegleProto::SendMsgWorker, parent, (void*)message);
+ } else {
+ parent->Log("**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( 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( OMEGLE_REQUEST_COUNT );
+
+ 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/connection.cpp b/protocols/Omegle/src/connection.cpp
new file mode 100644
index 0000000000..1ce07385d9
--- /dev/null
+++ b/protocols/Omegle/src/connection.cpp
@@ -0,0 +1,179 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+void OmegleProto::SignOn(void*)
+{
+ SYSTEMTIME t;
+ GetLocalTime( &t );
+ Log("[%d.%d.%d] Using Omegle Protocol %s", t.wDay, t.wMonth, t.wYear, __VERSION_STRING);
+
+ ScopedLock s(signon_lock_);
+
+ int old_status = m_iStatus;
+ m_iStatus = m_iDesiredStatus;
+ ProtoBroadcastAck(m_szModuleName,0,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)old_status,m_iStatus);
+
+ setDword( "LogonTS", (DWORD)time(NULL));
+ ClearChat();
+ OnJoinChat(0,false);
+
+ //ToggleStatusMenuItems(true);
+}
+
+void OmegleProto::SignOff(void*)
+{
+ ScopedLock s(signon_lock_);
+
+ int old_status = m_iStatus;
+ m_iStatus = ID_STATUS_OFFLINE;
+
+ Netlib_Shutdown(facy.hEventsConnection);
+
+ OnLeaveChat(NULL, NULL);
+
+ deleteSetting( "LogonTS" );
+
+ ProtoBroadcastAck(m_szModuleName,0,ACKTYPE_STATUS,ACKRESULT_SUCCESS,(HANDLE)old_status,m_iStatus);
+
+ //SetAllContactStatuses( ID_STATUS_OFFLINE );
+ //ToggleStatusMenuItems(false);
+
+ if (facy.hEventsConnection)
+ Netlib_CloseHandle(facy.hEventsConnection);
+ facy.hEventsConnection = NULL;
+}
+
+void OmegleProto::StopChat(bool disconnect)
+{
+ if (facy.state_ == STATE_WAITING) {
+ UpdateChat(NULL, TranslateT("Connecting canceled."), false);
+ } else if (facy.state_ == STATE_ACTIVE || facy.state_ == STATE_SPY) {
+ bool spy = facy.state_ == STATE_SPY;
+
+ if (disconnect)
+ {
+ facy.state_ = STATE_DISCONNECTING;
+ UpdateChat(NULL, TranslateT("Disconnecting..."), true);
+
+ if (facy.stop())
+ LOG("***** Disconnected from stranger %s", facy.chat_id_.c_str());
+ else
+ LOG("***** Error in disconnecting from stranger %s", facy.chat_id_.c_str());
+ }
+
+ if (spy) {
+ DeleteChatContact(TranslateT("Stranger 1"));
+ DeleteChatContact(TranslateT("Stranger 2"));
+ } else {
+ DeleteChatContact(TranslateT("Stranger"));
+ }
+
+ SetTopic(); // reset topic content
+ }
+ else
+ { // disconnecting or inactive
+ return;
+ }
+
+ facy.state_ = STATE_INACTIVE;
+ facy.chat_id_ = "";
+}
+
+void OmegleProto::NewChat()
+{
+ if (facy.state_ == STATE_WAITING)
+ {
+ UpdateChat(NULL, TranslateT("We are already waiting for new stranger..."), false);
+ return;
+ }
+ else if (facy.state_ == STATE_ACTIVE || facy.state_ == STATE_SPY)
+ {
+ UpdateChat(NULL, TranslateT("Disconnecting..."), true);
+
+ if (facy.stop())
+ LOG("***** Disconnected from stranger %s", facy.chat_id_.c_str());
+ else
+ LOG("***** Error in disconnecting from stranger %s", facy.chat_id_.c_str());
+
+ if (facy.state_ == STATE_SPY) {
+ DeleteChatContact(TranslateT("Stranger 1"));
+ DeleteChatContact(TranslateT("Stranger 2"));
+ } else {
+ DeleteChatContact(TranslateT("Stranger"));
+ }
+
+ SetTopic(); // reset topic content
+
+ ClearChat();
+
+ UpdateChat(NULL, TranslateT("Connecting..."), true);
+
+ facy.state_ = STATE_WAITING;
+
+ if (facy.start())
+ {
+ UpdateChat(NULL, TranslateT("Waiting for Stranger..."), true);
+ LOG("***** Waiting for stranger %s", facy.chat_id_.c_str());
+ }
+ }
+ else if (facy.state_ == STATE_DISCONNECTING)
+ {
+ //UpdateChat(NULL, TranslateT("We are disconnecting now, wait..."), false);
+ return;
+ }
+ else
+ {
+ ClearChat();
+ UpdateChat(NULL, TranslateT("Connecting..."), true);
+
+ facy.state_ = STATE_WAITING;
+
+ if (facy.start())
+ {
+ UpdateChat(NULL, TranslateT("Waiting for Stranger..."), true);
+ LOG("***** Waiting for stranger %s", facy.chat_id_.c_str());
+
+ ForkThread( &OmegleProto::EventsLoop, this );
+ }
+ }
+
+}
+
+void OmegleProto::EventsLoop(void *)
+{
+ ScopedLock s(events_loop_lock_);
+
+ time_t tim = ::time(NULL);
+ LOG( ">>>>> Entering Omegle::EventsLoop[%d]", tim );
+
+ while ( facy.events())
+ {
+ if ( facy.state_ == STATE_INACTIVE || facy.state_ == STATE_DISCONNECTING || !isOnline())
+ break;
+ LOG( "***** OmegleProto::EventsLoop[%d] refreshing...", tim );
+ }
+
+ ResetEvent(events_loop_lock_);
+ LOG( "<<<<< Exiting OmegleProto::EventsLoop[%d]", tim );
+}
diff --git a/protocols/Omegle/src/constants.h b/protocols/Omegle/src/constants.h
new file mode 100644
index 0000000000..6f1fbda166
--- /dev/null
+++ b/protocols/Omegle/src/constants.h
@@ -0,0 +1,55 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+// Version management
+#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0,1,0,1)
+#define __VERSION_STRING "0.1.0.1"
+
+// Product management
+#define OMEGLE_NAME "Omegle"
+#define OMEGLE_SERVER_REGULAR "http://www.omegle.com"
+#define OMEGLE_SERVER_CHAT "http://%s.omegle.com"
+
+// Limits
+#define OMEGLE_TIMEOUTS_LIMIT 6
+// There is "no limit" on Omegle, but we should set some wise limit
+#define OMEGLE_MESSAGE_LIMIT 4096
+#define OMEGLE_MESSAGE_LIMIT_TEXT "4096"
+
+#define OMEGLE_QUESTION_MIN_LENGTH 10
+
+// Omegle request types
+#define OMEGLE_REQUEST_HOME 100 // getting server name
+#define OMEGLE_REQUEST_COUNT 105 // get count of connected users
+#define OMEGLE_REQUEST_START 110 // starting conversation
+#define OMEGLE_REQUEST_STOP 120 // ending conversation
+#define OMEGLE_REQUEST_SEND 300 // sending message
+#define OMEGLE_REQUEST_EVENTS 301 // receiving events
+#define OMEGLE_REQUEST_TYPING_START 310 // started typing
+#define OMEGLE_REQUEST_TYPING_STOP 311 // stoped typing
+#define OMEGLE_REQUEST_RECAPTCHA 400 // recaptcha handling
+
+// Servers list
+//static const char *servers[] = {"Random", "bajor", "cardassia", "promenade", "odo-bucket", "ferengi", "quilt", "empok-nor", "quibbler"};
+static const char *servers[] = {"Random", "front1", "front2", "front3", "front4", "qfront1"}; \ No newline at end of file
diff --git a/protocols/Omegle/src/db.h b/protocols/Omegle/src/db.h
new file mode 100644
index 0000000000..fd0d290b3c
--- /dev/null
+++ b/protocols/Omegle/src/db.h
@@ -0,0 +1,55 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+// DB macros
+#define getByte( setting, error ) DBGetContactSettingByte( NULL, m_szModuleName, setting, error )
+#define setByte( setting, value ) DBWriteContactSettingByte( NULL, m_szModuleName, setting, value )
+#define getWord( setting, error ) DBGetContactSettingWord( NULL, m_szModuleName, setting, error )
+#define setWord( setting, value ) DBWriteContactSettingWord( NULL, m_szModuleName, setting, value )
+#define getDword( setting, error ) DBGetContactSettingDword( NULL, m_szModuleName, setting, error )
+#define setDword( setting, value ) DBWriteContactSettingDword( NULL, m_szModuleName, setting, value )
+#define getString( setting, dest ) DBGetContactSettingString( NULL, m_szModuleName, setting, dest )
+#define setString( setting, value ) DBWriteContactSettingString( NULL, m_szModuleName, setting, value )
+#define getTString( setting, dest ) DBGetContactSettingTString( NULL, m_szModuleName, setting, dest )
+#define setTString( setting, value ) DBWriteContactSettingTString( NULL, m_szModuleName, setting, value )
+#define getU8String( setting, dest ) DBGetContactSettingUTF8String( NULL, m_szModuleName, setting, dest )
+#define setU8String( setting, value ) DBWriteContactSettingUTF8String( NULL, m_szModuleName, setting, value )
+#define deleteSetting( setting ) DBDeleteContactSetting( NULL, m_szModuleName, setting )
+
+// DB settings
+#define OMEGLE_KEY_TIMEOUTS_LIMIT "TimeoutsLimit" // [HIDDEN]
+
+#define OMEGLE_KEY_ASL "MessageAsl"
+#define OMEGLE_KEY_HI "MessageHi"
+#define OMEGLE_KEY_HI_ENABLED "MessageHiEnabled"
+#define OMEGLE_KEY_NAME "Nick"
+#define OMEGLE_KEY_DONT_STOP "DontStop"
+#define OMEGLE_KEY_NO_CLEAR "NoClear"
+#define OMEGLE_KEY_MEET_COMMON "MeetCommon"
+#define OMEGLE_KEY_INTERESTS "Interests"
+#define OMEGLE_KEY_REUSE_QUESTION "ReuseQuestion"
+#define OMEGLE_KEY_SERVER "Server"
+#define OMEGLE_KEY_LOGGING "EnableLogging"
+#define OMEGLE_KEY_SERVER_INFO "GetServerInfo"
+#define OMEGLE_KEY_LAST_QUESTION "LastQuestion"
diff --git a/protocols/Omegle/src/dialogs.cpp b/protocols/Omegle/src/dialogs.cpp
new file mode 100644
index 0000000000..8045ea2e43
--- /dev/null
+++ b/protocols/Omegle/src/dialogs.cpp
@@ -0,0 +1,231 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+static BOOL LoadDBCheckState(OmegleProto* ppro, HWND hwnd, int idCtrl, const char* szSetting, BYTE bDef = 0)
+{
+ BOOL state = DBGetContactSettingByte(NULL, ppro->m_szModuleName, szSetting, bDef);
+ CheckDlgButton(hwnd, idCtrl, state);
+ return state;
+}
+
+static BOOL StoreDBCheckState(OmegleProto* ppro, HWND hwnd, int idCtrl, const char* szSetting)
+{
+ BOOL state = IsDlgButtonChecked(hwnd, idCtrl);
+ DBWriteContactSettingByte(NULL, ppro->m_szModuleName, szSetting, (BYTE)state);
+ return state;
+}
+
+static void LoadDBText(OmegleProto* ppro, HWND hwnd, int idCtrl, const char* szSetting)
+{
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, ppro->m_szModuleName, szSetting, &dbv))
+ {
+ SetDlgItemText(hwnd, idCtrl, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+}
+
+static void StoreDBText(OmegleProto* ppro, HWND hwnd, int idCtrl, const char* szSetting)
+{
+ TCHAR tstr[250+1];
+
+ GetDlgItemText(hwnd, idCtrl, tstr, sizeof(tstr));
+ if ( _tcsclen( tstr ) > 0 ) {
+ DBWriteContactSettingTString(NULL, ppro->m_szModuleName, szSetting, tstr);
+ } else {
+ DBDeleteContactSetting(NULL, ppro->m_szModuleName, szSetting);
+ }
+}
+
+
+INT_PTR CALLBACK OmegleAccountProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
+{
+ OmegleProto *proto;
+
+ switch ( message )
+ {
+
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwnd);
+
+ proto = reinterpret_cast<OmegleProto*>(lparam);
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,lparam);
+
+ SendDlgItemMessage(hwnd,IDC_INTERESTS, EM_LIMITTEXT, 512, 0);
+
+ // Server
+ SendDlgItemMessageA(hwnd, IDC_SERVER, CB_INSERTSTRING, 0, reinterpret_cast<LPARAM>(Translate(servers[0])));
+ for(size_t i=1; i<SIZEOF(servers); i++)
+ {
+ SendDlgItemMessageA(hwnd, IDC_SERVER, CB_INSERTSTRING, i, reinterpret_cast<LPARAM>(servers[i]));
+ }
+ SendDlgItemMessage(hwnd, IDC_SERVER, CB_SETCURSEL, DBGetContactSettingByte(NULL, proto->m_szModuleName, OMEGLE_KEY_SERVER, 0), 0);
+
+ LoadDBText(proto, hwnd, IDC_NAME, OMEGLE_KEY_NAME);
+ LoadDBText(proto, hwnd, IDC_INTERESTS, OMEGLE_KEY_INTERESTS);
+ LoadDBCheckState(proto, hwnd, IDC_MEET_COMMON, OMEGLE_KEY_MEET_COMMON);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ switch(LOWORD(wparam))
+ {
+ case IDC_SERVER:
+ if (HIWORD(wparam) == CBN_SELCHANGE) {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ case IDC_NAME:
+ case IDC_INTERESTS:
+ if (HIWORD(wparam) != EN_CHANGE || (HWND) lparam != GetFocus()) {
+ return TRUE;
+ } else {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ case IDC_MEET_COMMON:
+ if (HIWORD(wparam) == BN_CLICKED) {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ if ( reinterpret_cast<NMHDR*>(lparam)->code == PSN_APPLY )
+ {
+ proto = reinterpret_cast<OmegleProto*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
+
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, OMEGLE_KEY_SERVER, SendDlgItemMessage(hwnd, IDC_SERVER, CB_GETCURSEL, 0, 0));
+
+ StoreDBText(proto, hwnd, IDC_NAME, OMEGLE_KEY_NAME);
+ StoreDBText(proto, hwnd, IDC_INTERESTS, OMEGLE_KEY_INTERESTS);
+ StoreDBCheckState(proto, hwnd, IDC_MEET_COMMON, OMEGLE_KEY_MEET_COMMON);
+
+ return TRUE;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+INT_PTR CALLBACK OmegleOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
+{
+ OmegleProto *proto = reinterpret_cast<OmegleProto*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
+
+ switch ( message )
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwnd);
+
+ proto = reinterpret_cast<OmegleProto*>(lparam);
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,lparam);
+
+ SendDlgItemMessage(hwnd,IDC_INTERESTS, EM_LIMITTEXT, 250, 0);
+ SendDlgItemMessage(hwnd,IDC_HI_MESSAGE, EM_LIMITTEXT, 250, 0);
+ SendDlgItemMessage(hwnd,IDC_ASL_MESSAGE, EM_LIMITTEXT, 250, 0);
+
+ // Server
+ SendDlgItemMessageA(hwnd, IDC_SERVER, CB_INSERTSTRING, 0, reinterpret_cast<LPARAM>(Translate(servers[0])));
+ for(size_t i=1; i<SIZEOF(servers); i++)
+ {
+ SendDlgItemMessageA(hwnd, IDC_SERVER, CB_INSERTSTRING, i, reinterpret_cast<LPARAM>(servers[i]));
+ }
+ SendDlgItemMessage(hwnd, IDC_SERVER, CB_SETCURSEL, DBGetContactSettingByte(NULL, proto->m_szModuleName, OMEGLE_KEY_SERVER, 0), 0);
+
+ LoadDBText(proto, hwnd, IDC_NAME, OMEGLE_KEY_NAME);
+ LoadDBText(proto, hwnd, IDC_INTERESTS, OMEGLE_KEY_INTERESTS);
+ LoadDBText(proto, hwnd, IDC_HI_MESSAGE, OMEGLE_KEY_HI);
+ LoadDBText(proto, hwnd, IDC_ASL_MESSAGE, OMEGLE_KEY_ASL);
+ LoadDBText(proto, hwnd, IDC_LAST_QUESTION, OMEGLE_KEY_LAST_QUESTION);
+
+ LoadDBCheckState(proto, hwnd, IDC_MEET_COMMON, OMEGLE_KEY_MEET_COMMON);
+ LoadDBCheckState(proto, hwnd, IDC_HI_ENABLED, OMEGLE_KEY_HI_ENABLED);
+ LoadDBCheckState(proto, hwnd, IDC_NOCLEAR, OMEGLE_KEY_NO_CLEAR);
+ LoadDBCheckState(proto, hwnd, IDC_DONTSTOP, OMEGLE_KEY_DONT_STOP);
+ LoadDBCheckState(proto, hwnd, IDC_REUSE_QUESTIONS, OMEGLE_KEY_REUSE_QUESTION);
+ LoadDBCheckState(proto, hwnd, IDC_SERVER_INFO, OMEGLE_KEY_SERVER_INFO);
+ LoadDBCheckState(proto, hwnd, IDC_LOGGING, OMEGLE_KEY_LOGGING);
+
+ } return TRUE;
+
+ case WM_COMMAND: {
+
+ switch(LOWORD(wparam))
+ {
+ case IDC_SERVER:
+ if (HIWORD(wparam) == CBN_SELCHANGE) {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ case IDC_NAME:
+ case IDC_INTERESTS:
+ case IDC_HI_MESSAGE:
+ case IDC_ASL_MESSAGE:
+ if (HIWORD(wparam) != EN_CHANGE || (HWND) lparam != GetFocus()) {
+ return TRUE;
+ } else {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ case IDC_MEET_COMMON:
+ case IDC_HI_ENABLED:
+ case IDC_NOCLEAR:
+ case IDC_DONTSTOP:
+ case IDC_REUSE_QUESTIONS:
+ case IDC_SERVER_INFO:
+ case IDC_LOGGING:
+ if (HIWORD(wparam) == BN_CLICKED) {
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ } break;
+ }
+
+ } break;
+
+ case WM_NOTIFY:
+ if ( reinterpret_cast<NMHDR*>(lparam)->code == PSN_APPLY )
+ {
+ proto = reinterpret_cast<OmegleProto*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
+
+ DBWriteContactSettingByte(NULL, proto->m_szModuleName, OMEGLE_KEY_SERVER, SendDlgItemMessage(hwnd, IDC_SERVER, CB_GETCURSEL, 0, 0));
+
+ StoreDBText(proto, hwnd, IDC_NAME, OMEGLE_KEY_NAME);
+ StoreDBText(proto, hwnd, IDC_INTERESTS, OMEGLE_KEY_INTERESTS);
+ StoreDBText(proto, hwnd, IDC_HI_MESSAGE, OMEGLE_KEY_HI);
+ StoreDBText(proto, hwnd, IDC_ASL_MESSAGE, OMEGLE_KEY_ASL);
+
+ StoreDBCheckState(proto, hwnd, IDC_MEET_COMMON, OMEGLE_KEY_MEET_COMMON);
+ StoreDBCheckState(proto, hwnd, IDC_HI_ENABLED, OMEGLE_KEY_HI_ENABLED);
+ StoreDBCheckState(proto, hwnd, IDC_NOCLEAR, OMEGLE_KEY_NO_CLEAR);
+ StoreDBCheckState(proto, hwnd, IDC_DONTSTOP, OMEGLE_KEY_DONT_STOP);
+ StoreDBCheckState(proto, hwnd, IDC_REUSE_QUESTIONS, OMEGLE_KEY_REUSE_QUESTION);
+ StoreDBCheckState(proto, hwnd, IDC_SERVER_INFO, OMEGLE_KEY_SERVER_INFO);
+ StoreDBCheckState(proto, hwnd, IDC_LOGGING, OMEGLE_KEY_LOGGING);
+
+ return TRUE;
+ }
+ break;
+
+ }
+
+ return FALSE;
+}
diff --git a/protocols/Omegle/src/dialogs.h b/protocols/Omegle/src/dialogs.h
new file mode 100644
index 0000000000..880f04636b
--- /dev/null
+++ b/protocols/Omegle/src/dialogs.h
@@ -0,0 +1,26 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+INT_PTR CALLBACK OmegleAccountProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
+INT_PTR CALLBACK OmegleOptionsProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam );
diff --git a/protocols/Omegle/src/events.cpp b/protocols/Omegle/src/events.cpp
new file mode 100644
index 0000000000..5e2749e70c
--- /dev/null
+++ b/protocols/Omegle/src/events.cpp
@@ -0,0 +1,39 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+int OmegleProto::Log(const char *fmt,...)
+{
+ if (!getByte(OMEGLE_KEY_LOGGING, 0))
+ return EXIT_SUCCESS;
+
+ va_list va;
+ char text[65535];
+ ScopedLock s(log_lock_);
+
+ va_start(va,fmt);
+ mir_vsnprintf(text,sizeof(text),fmt,va);
+ va_end(va);
+
+ return utils::debug::log( m_szModuleName, text );
+}
diff --git a/protocols/Omegle/src/http.cpp b/protocols/Omegle/src/http.cpp
new file mode 100644
index 0000000000..e360253e1a
--- /dev/null
+++ b/protocols/Omegle/src/http.cpp
@@ -0,0 +1,23 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
diff --git a/protocols/Omegle/src/http.h b/protocols/Omegle/src/http.h
new file mode 100644
index 0000000000..a09e4f903d
--- /dev/null
+++ b/protocols/Omegle/src/http.h
@@ -0,0 +1,48 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+#define HTTP_CODE_OK 200
+#define HTTP_CODE_MOVED_PERMANENTLY 301
+#define HTTP_CODE_FOUND 302
+#define HTTP_CODE_FORBIDDEN 403
+#define HTTP_CODE_NOT_FOUND 404
+#define HTTP_CODE_REQUEST_TIMEOUT 408
+#define HTTP_CODE_INTERNAL_SERVER_ERROR 500
+#define HTTP_CODE_NOT_IMPLEMENTED 501
+#define HTTP_CODE_BAD_GATEWAY 502
+#define HTTP_CODE_SERVICE_UNAVAILABLE 503
+
+#define HTTP_CODE_FAKE_DISCONNECTED 0
+#define HTTP_CODE_FAKE_ERROR 1
+
+namespace http
+{
+ struct response
+ {
+ response() : code(0) {}
+ int code;
+ std::map< std::string, std::string > headers;
+ std::string data;
+ };
+}
diff --git a/protocols/Omegle/src/main.cpp b/protocols/Omegle/src/main.cpp
new file mode 100644
index 0000000000..32771e22be
--- /dev/null
+++ b/protocols/Omegle/src/main.cpp
@@ -0,0 +1,146 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+// TODO: Make following as "globals" structure?
+
+CLIST_INTERFACE* pcli;
+int hLangpack;
+
+HINSTANCE g_hInstance;
+std::string g_strUserAgent;
+DWORD g_mirandaVersion;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Omegle Protocol",
+ __VERSION_DWORD,
+ "Provides basic support for Omegle Chat protocol.",
+ "Robert Posel",
+ "robyer@seznam.cz",
+ "(c) 2011-12 Robert Posel",
+ "http://miranda-ng.org/",
+ UNICODE_AWARE,
+ // {9E1D9244-606C-4ef4-99A0-1D7D23CB7601}
+ { 0x9e1d9244, 0x606c, 0x4ef4, { 0x99, 0xa0, 0x1d, 0x7d, 0x23, 0xcb, 0x76, 0x1 } }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Protocol instances
+static int compare_protos(const OmegleProto *p1, const OmegleProto *p2)
+{
+ return _tcscmp(p1->m_tszUserName, p2->m_tszUserName);
+}
+
+OBJLIST<OmegleProto> g_Instances(1, compare_protos);
+
+DWORD WINAPI DllMain(HINSTANCE hInstance,DWORD,LPVOID)
+{
+ g_hInstance = hInstance;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ g_mirandaVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Interface information
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Load
+
+static PROTO_INTERFACE* protoInit(const char *proto_name,const TCHAR *username )
+{
+ OmegleProto *proto = new OmegleProto(proto_name, username);
+ g_Instances.insert(proto);
+ return proto;
+}
+
+static int protoUninit(PROTO_INTERFACE* proto)
+{
+ g_Instances.remove(( OmegleProto* )proto);
+ return EXIT_SUCCESS;
+}
+
+static HANDLE g_hEvents[1];
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+
+ mir_getLP(&pluginInfo);
+
+ pcli = reinterpret_cast<CLIST_INTERFACE*>( CallService(
+ MS_CLIST_RETRIEVE_INTERFACE,0,reinterpret_cast<LPARAM>(g_hInstance)));
+
+ PROTOCOLDESCRIPTOR pd = { 0 };
+ pd.cbSize = sizeof(pd);
+ pd.szName = "Omegle";
+ pd.type = PROTOTYPE_PROTOCOL;
+ pd.fnInit = protoInit;
+ pd.fnUninit = protoUninit;
+ CallService(MS_PROTO_REGISTERMODULE,0,reinterpret_cast<LPARAM>(&pd));
+
+ InitIcons();
+ //InitContactMenus();
+
+ // Init native User-Agent
+ {
+ std::stringstream agent;
+ agent << "Miranda IM/";
+ agent << (( g_mirandaVersion >> 24) & 0xFF);
+ agent << ".";
+ agent << (( g_mirandaVersion >> 16) & 0xFF);
+ agent << ".";
+ agent << (( g_mirandaVersion >> 8) & 0xFF);
+ agent << ".";
+ agent << (( g_mirandaVersion ) & 0xFF);
+ #ifdef _WIN64
+ agent << " Omegle Protocol x64/";
+ #else
+ agent << " Omegle Protocol/";
+ #endif
+ agent << __VERSION_STRING;
+ g_strUserAgent = agent.str( );
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Unload
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ //UninitContactMenus();
+ for(size_t i=0; i<SIZEOF(g_hEvents); i++)
+ UnhookEvent(g_hEvents[i]);
+
+ g_Instances.destroy();
+
+ return 0;
+}
diff --git a/protocols/Omegle/src/messages.cpp b/protocols/Omegle/src/messages.cpp
new file mode 100644
index 0000000000..b90ff67579
--- /dev/null
+++ b/protocols/Omegle/src/messages.cpp
@@ -0,0 +1,92 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+void OmegleProto::SendMsgWorker(void *p)
+{
+ if(p == NULL)
+ return;
+
+ ScopedLock s( facy.send_message_lock_ );
+
+ std::string *data = static_cast<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);
+ }
+
+ delete data;
+}
+
+void OmegleProto::SendTypingWorker(void *p)
+{
+ if (p == NULL)
+ return;
+
+ // Save typing info
+ bool typ = !_tcscmp(static_cast<TCHAR*>(p), _T("1"));
+ mir_free(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*p)
+{
+ NewChat();
+}
+
+void OmegleProto::StopChatWorker(void*p)
+{
+ StopChat();
+}
+
+int OmegleProto::SendMsg(HANDLE hContact, int flags, const char *msg)
+{
+ // TODO: msg comes as Unicode (retyped wchar_t*), why should we convert it as ANSI to UTF-8? o_O
+/* if ( flags & PREF_UNICODE )
+ msg = mir_utf8encode(msg);
+
+ facy.msgid_ = (facy.msgid_ % 1024)+1;
+ ForkThread( &OmegleProto::SendMsgWorker, this,new send_direct(hContact,msg,(HANDLE)facy.msgid_));
+ return facy.msgid_;*/
+ return 0;
+}
diff --git a/protocols/Omegle/src/process.cpp b/protocols/Omegle/src/process.cpp
new file mode 100644
index 0000000000..eb707373ec
--- /dev/null
+++ b/protocols/Omegle/src/process.cpp
@@ -0,0 +1,77 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+void OmegleProto::ProcessEvents( void* data )
+{
+ if ( data == NULL )
+ return;
+
+ std::string* resp = (std::string*)data;
+
+ if ( isOffline() )
+ goto exit;
+
+ LOG("***** Starting processing messages");
+
+ CODE_BLOCK_TRY
+
+ std::vector< Omegle_message* > messages;
+
+ Omegle_json_parser* p = new Omegle_json_parser( this );
+ p->parse_messages( data, &messages );
+ delete p;
+
+ for(std::vector<Omegle_message*>::size_type i=0; i<messages.size( ); i++)
+ {
+ LOG(" Got message: %s", messages[i]->message_text.c_str());
+
+/*
+ PROTORECVEVENT recv = {};
+ CCSDATA ccs = {};
+
+ recv.flags = PREF_UTF;
+ recv.szMessage = const_cast<char*>(messages[i]->message_text.c_str());
+ recv.timestamp = static_cast<DWORD>(messages[i]->time);
+
+ ccs.hContact = hContact;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.wParam = ID_STATUS_ONLINE;
+ ccs.lParam = reinterpret_cast<LPARAM>(&recv);
+ CallService(MS_PROTO_CHAINRECV,0,reinterpret_cast<LPARAM>(&ccs));*/
+
+ delete messages[i];
+ }
+ messages.clear();
+
+ LOG("***** Messages processed");
+
+ CODE_BLOCK_CATCH
+
+ LOG("***** Error processing messages: %s", e.what());
+
+ CODE_BLOCK_END
+
+exit:
+ delete resp;
+}
diff --git a/protocols/Omegle/src/proto.cpp b/protocols/Omegle/src/proto.cpp
new file mode 100644
index 0000000000..51e4bdf599
--- /dev/null
+++ b/protocols/Omegle/src/proto.cpp
@@ -0,0 +1,259 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+OmegleProto::OmegleProto(const char* proto_name, const TCHAR* username)
+{
+ m_iVersion = 2;
+ m_szProtoName = mir_strdup( proto_name );
+ m_szModuleName = mir_strdup( proto_name );
+ m_tszUserName = mir_tstrdup( username );
+
+ this->facy.parent = this;
+
+ this->signon_lock_ = CreateMutex( NULL, FALSE, NULL );
+ this->log_lock_ = CreateMutex( NULL, FALSE, NULL );
+ this->facy.send_message_lock_ = CreateMutex( NULL, FALSE, NULL );
+ this->facy.connection_lock_ = CreateMutex( NULL, FALSE, NULL );
+
+ // Group chats
+ CreateProtoService(m_szModuleName, PS_JOINCHAT, &OmegleProto::OnJoinChat, this);
+ CreateProtoService(m_szModuleName, PS_LEAVECHAT, &OmegleProto::OnLeaveChat, this);
+
+ CreateProtoService(m_szModuleName, PS_CREATEACCMGRUI, &OmegleProto::SvcCreateAccMgrUI, this);
+
+ HookProtoEvent(ME_OPT_INITIALISE, &OmegleProto::OnOptionsInit, this);
+ HookProtoEvent(ME_GC_EVENT, &OmegleProto::OnChatEvent, this);
+
+ // Create standard network connection
+ TCHAR descr[512];
+ NETLIBUSER nlu = {sizeof(nlu)};
+ nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
+ nlu.szSettingsModule = m_szModuleName;
+ char module[512];
+ mir_snprintf(module,SIZEOF(module),"%sAv",m_szModuleName);
+ nlu.szSettingsModule = module;
+ mir_sntprintf(descr,SIZEOF(descr),TranslateT("%s server connection"),m_tszUserName);
+ nlu.ptszDescriptiveName = descr;
+ m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu);
+ if(m_hNetlibUser == NULL)
+ MessageBox(NULL,TranslateT("Unable to get Netlib connection for Omegle"),m_tszUserName,MB_OK);
+
+ facy.set_handle(m_hNetlibUser);
+
+ SkinAddNewSoundExT( "StrangerTyp", m_tszUserName, LPGENT( "Stranger typing" ));
+ SkinAddNewSoundExT( "StrangerTypStop", m_tszUserName, LPGENT( "Stranger stopped typing" ));
+ SkinAddNewSoundExT( "StrangerChange", m_tszUserName, LPGENT( "Changing stranger" ));
+}
+
+OmegleProto::~OmegleProto( )
+{
+ Netlib_CloseHandle( m_hNetlibUser );
+
+ WaitForSingleObject( this->signon_lock_, IGNORE );
+ WaitForSingleObject( this->log_lock_, IGNORE );
+ WaitForSingleObject( this->facy.send_message_lock_, IGNORE );
+ WaitForSingleObject( this->events_loop_lock_, IGNORE );
+
+ CloseHandle( this->signon_lock_ );
+ CloseHandle( this->log_lock_ );
+ CloseHandle( this->facy.send_message_lock_ );
+ CloseHandle( this->events_loop_lock_ );
+ CloseHandle( this->facy.connection_lock_ );
+
+ mir_free( this->facy.nick_ );
+
+ mir_free( m_tszUserName );
+ mir_free( m_szModuleName );
+ mir_free( m_szProtoName );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+DWORD_PTR OmegleProto::GetCaps( int type, HANDLE hContact )
+{
+ switch(type)
+ {
+ case PFLAGNUM_1:
+ return PF1_CHAT;
+ case PFLAGNUM_2:
+ return PF2_ONLINE;
+ case PFLAGNUM_4:
+ return PF4_IMSENDUTF; // | PF4_SUPPORTTYPING;
+ case PFLAG_MAXLENOFMESSAGE:
+ return OMEGLE_MESSAGE_LIMIT;
+ case PFLAG_UNIQUEIDTEXT:
+ return (DWORD_PTR) Translate("Visible name");
+ case PFLAG_UNIQUEIDSETTING:
+ return (DWORD_PTR) "Nick";
+ }
+ return 0;
+}
+
+HICON OmegleProto::GetIcon(int index)
+{
+ if(LOWORD(index) == PLI_PROTOCOL)
+ {
+ HICON ico = (HICON)CallService(MS_SKIN2_GETICON,0,(LPARAM)"Omegle_omegle");
+ return CopyIcon(ico);
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+int OmegleProto::SetStatus( int new_status )
+{
+ // Routing statuses not supported by Omegle
+ switch ( new_status )
+ {
+ case ID_STATUS_OFFLINE:
+ case ID_STATUS_CONNECTING:
+ new_status = ID_STATUS_OFFLINE;
+ break;
+ default:
+ new_status = ID_STATUS_ONLINE;
+ break;
+ }
+
+ m_iDesiredStatus = new_status;
+
+ if ( new_status == m_iStatus)
+ {
+ return 0;
+ }
+
+ if ( m_iStatus == ID_STATUS_CONNECTING && new_status != ID_STATUS_OFFLINE )
+ {
+ return 0;
+ }
+
+ if ( new_status == ID_STATUS_OFFLINE )
+ {
+ ForkThread( &OmegleProto::SignOff, this );
+ }
+ else
+ {
+ ForkThread( &OmegleProto::SignOn, this );
+ }
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+int OmegleProto::OnEvent(PROTOEVENTTYPE event,WPARAM wParam,LPARAM lParam)
+{
+ switch(event)
+ {
+ case EV_PROTO_ONLOAD:
+ return OnModulesLoaded(wParam,lParam);
+
+ case EV_PROTO_ONEXIT:
+ return OnPreShutdown (wParam,lParam);
+
+ case EV_PROTO_ONOPTIONS:
+ return OnOptionsInit (wParam,lParam);
+
+ case EV_PROTO_ONCONTACTDELETED:
+ return OnContactDeleted(wParam,lParam);
+ }
+
+ return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// EVENTS
+
+int OmegleProto::SvcCreateAccMgrUI(WPARAM wParam,LPARAM lParam)
+{
+ return (int)CreateDialogParam(g_hInstance,MAKEINTRESOURCE(IDD_OmegleACCOUNT),
+ (HWND)lParam, OmegleAccountProc, (LPARAM)this );
+}
+
+int OmegleProto::OnModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ // Register group chat
+ GCREGISTER gcr = {sizeof(gcr)};
+ gcr.dwFlags = GC_TYPNOTIF; //GC_ACKMSG;
+ gcr.pszModule = m_szModuleName;
+ gcr.pszModuleDispName = m_szModuleName;
+ gcr.iMaxText = OMEGLE_MESSAGE_LIMIT;
+ gcr.nColors = 0;
+ gcr.pColors = NULL;
+ CallService(MS_GC_REGISTER,0,reinterpret_cast<LPARAM>(&gcr));
+
+ return 0;
+}
+
+int OmegleProto::OnOptionsInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {sizeof(odp)};
+ odp.hInstance = g_hInstance;
+ odp.ptszTitle = m_tszUserName;
+ odp.dwInitParam = LPARAM(this);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR | ODPF_DONTTRANSLATE;
+
+ odp.position = 271828;
+ odp.ptszGroup = LPGENT("Network");
+ odp.ptszTab = LPGENT("Account");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.pfnDlgProc = OmegleOptionsProc;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+int OmegleProto::OnPreShutdown(WPARAM wParam,LPARAM lParam)
+{
+ SetStatus( ID_STATUS_OFFLINE );
+ return 0;
+}
+
+int OmegleProto::OnContactDeleted(WPARAM wparam,LPARAM)
+{
+ //HANDLE hContact = (HANDLE)wparam;
+
+ OnLeaveChat(NULL, NULL);
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// OTHER
+
+/*bool OmegleProto::IsMyContact(HANDLE hContact, bool include_chat)
+{
+ const char *proto = reinterpret_cast<char*>( CallService(MS_PROTO_GETCONTACTBASEPROTO,
+ reinterpret_cast<WPARAM>(hContact),0));
+
+ if ( proto && strcmp(m_szModuleName,proto) == 0 )
+ {
+ if ( include_chat )
+ return true;
+ else
+ return DBGetContactSettingByte(hContact,m_szModuleName,"ChatRoom",0) == 0;
+ } else {
+ return false;
+ }
+}*/
diff --git a/protocols/Omegle/src/proto.h b/protocols/Omegle/src/proto.h
new file mode 100644
index 0000000000..053071aac8
--- /dev/null
+++ b/protocols/Omegle/src/proto.h
@@ -0,0 +1,150 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+class OmegleProto : public PROTO_INTERFACE, public MZeroedObject
+{
+public:
+ OmegleProto( const char *proto_name, const TCHAR *username );
+ ~OmegleProto( );
+
+ inline const char* ModuleName( ) const
+ {
+ return m_szModuleName;
+ }
+
+ inline bool isOnline( )
+ {
+ return ( m_iStatus != ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_CONNECTING );
+ }
+
+ inline bool isOffline( )
+ {
+ return ( m_iStatus == ID_STATUS_OFFLINE );
+ }
+
+ // PROTO_INTERFACE
+ virtual HANDLE __cdecl AddToList( int flags, PROTOSEARCHRESULT* psr );
+ virtual HANDLE __cdecl AddToListByEvent( int flags, int iContact, HANDLE hDbEvent );
+
+ virtual int __cdecl Authorize( HANDLE hDbEvent );
+ virtual int __cdecl AuthDeny( HANDLE hDbEvent, const PROTOCHAR* szReason );
+ virtual int __cdecl AuthRecv( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl AuthRequest( HANDLE hContact, const PROTOCHAR* szMessage );
+
+ virtual HANDLE __cdecl ChangeInfo( int iInfoType, void* pInfoData );
+
+ virtual HANDLE __cdecl FileAllow( HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath );
+ virtual int __cdecl FileCancel( HANDLE hContact, HANDLE hTransfer );
+ virtual int __cdecl FileDeny( HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason );
+ virtual int __cdecl FileResume( HANDLE hTransfer, int* action, const PROTOCHAR** szFilename );
+
+ virtual DWORD_PTR __cdecl GetCaps( int type, HANDLE hContact = NULL );
+ virtual HICON __cdecl GetIcon( int iconIndex );
+ virtual int __cdecl GetInfo( HANDLE hContact, int infoType );
+
+ virtual HANDLE __cdecl SearchBasic( const PROTOCHAR* id );
+ virtual HANDLE __cdecl SearchByEmail( const PROTOCHAR* email );
+ virtual HANDLE __cdecl SearchByName( const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName );
+ virtual HWND __cdecl SearchAdvanced( HWND owner );
+ virtual HWND __cdecl CreateExtendedSearchUI( HWND owner );
+
+ virtual int __cdecl RecvContacts( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl RecvFile( HANDLE hContact, PROTOFILEEVENT* );
+ virtual int __cdecl RecvMsg( HANDLE hContact, PROTORECVEVENT* );
+ virtual int __cdecl RecvUrl( HANDLE hContact, PROTORECVEVENT* );
+
+ virtual int __cdecl SendContacts( HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList );
+ virtual HANDLE __cdecl SendFile( HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles );
+ virtual int __cdecl SendMsg( HANDLE hContact, int flags, const char* msg );
+ virtual int __cdecl SendUrl( HANDLE hContact, int flags, const char* url );
+
+ virtual int __cdecl SetApparentMode( HANDLE hContact, int mode );
+ virtual int __cdecl SetStatus( int iNewStatus );
+
+ virtual HANDLE __cdecl GetAwayMsg( HANDLE hContact );
+ virtual int __cdecl RecvAwayMsg( HANDLE hContact, int mode, PROTORECVEVENT* evt );
+ virtual int __cdecl SendAwayMsg( HANDLE hContact, HANDLE hProcess, const char* msg );
+ virtual int __cdecl SetAwayMsg( int iStatus, const PROTOCHAR* msg );
+
+ virtual int __cdecl UserIsTyping( HANDLE hContact, int type );
+
+ virtual int __cdecl OnEvent( PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam );
+
+ // Services
+ int __cdecl SvcCreateAccMgrUI( WPARAM, LPARAM );
+
+ // Events
+ int __cdecl OnModulesLoaded(WPARAM, LPARAM);
+ int __cdecl OnOptionsInit(WPARAM, LPARAM);
+ int __cdecl OnContactDeleted(WPARAM,LPARAM);
+ int __cdecl OnPreShutdown(WPARAM,LPARAM);
+ int __cdecl OnPrebuildContactMenu(WPARAM,LPARAM);
+
+ // Chat handling
+ int __cdecl OnChatEvent(WPARAM,LPARAM);
+ int __cdecl OnJoinChat(WPARAM,LPARAM);
+ int __cdecl OnLeaveChat(WPARAM,LPARAM);
+
+ // Loops
+ void __cdecl EventsLoop(void*);
+
+ // Worker threads
+ void __cdecl SignOn(void*);
+ void __cdecl SignOff(void*);
+
+ void __cdecl SendMsgWorker(void*);
+ void __cdecl SendTypingWorker(void*);
+
+ void __cdecl NewChatWorker(void*);
+ void __cdecl StopChatWorker(void*);
+
+ void StopChat(bool disconnect = true);
+ void NewChat();
+
+ // Contacts handling
+ //bool IsMyContact(HANDLE, bool include_chat = false);
+
+ // Chat handling
+ void AddChat(const TCHAR *id,const TCHAR *name);
+ void UpdateChat(const TCHAR *name, const TCHAR *message, bool addtochat = true);
+ void AddChatContact(const TCHAR *nick);
+ void DeleteChatContact(const TCHAR *name);
+ void SetChatStatus(int);
+ void ClearChat();
+ void SetTopic(const TCHAR *topic = NULL);
+
+ // Connection client
+ Omegle_client facy;
+
+ HANDLE signon_lock_;
+ HANDLE log_lock_;
+ HANDLE events_loop_lock_;
+
+ HANDLE m_hNetlibUser;
+
+ static void CALLBACK APC_callback(ULONG_PTR p);
+
+ // Logging
+ int Log(const char *fmt,...);
+};
diff --git a/protocols/Omegle/src/resource.h b/protocols/Omegle/src/resource.h
new file mode 100644
index 0000000000..0cfab1d840
--- /dev/null
+++ b/protocols/Omegle/src/resource.h
@@ -0,0 +1,31 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by omegle.rc
+//
+#define IDI_OMEGLE 101
+#define IDD_OmegleACCOUNT 111
+#define IDD_OPTIONS 122
+#define IDC_SERVER 1204
+#define IDC_NAME 1205
+#define IDC_MEET_COMMON 1206
+#define IDC_INTERESTS 1207
+#define IDC_HI_ENABLED 1208
+#define IDC_HI_MESSAGE 1209
+#define IDC_ASL_MESSAGE 1210
+#define IDC_LAST_QUESTION 1211
+#define IDC_NOCLEAR 1213
+#define IDC_DONTSTOP 1214
+#define IDC_REUSE_QUESTIONS 1215
+#define IDC_LOGGING 1216
+#define IDC_SERVER_INFO 1217
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 124
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1208
+#define _APS_NEXT_SYMED_VALUE 131
+#endif
+#endif
diff --git a/protocols/Omegle/src/stubs.cpp b/protocols/Omegle/src/stubs.cpp
new file mode 100644
index 0000000000..b02fd71ef5
--- /dev/null
+++ b/protocols/Omegle/src/stubs.cpp
@@ -0,0 +1,173 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+HANDLE OmegleProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
+{
+ return NULL;
+};
+
+HANDLE OmegleProto::AddToListByEvent(int flags,int iContact,HANDLE hDbEvent)
+{
+ return NULL;
+};
+
+int OmegleProto::Authorize(HANDLE hDbEvent)
+{
+ return 1;
+}
+
+int OmegleProto::AuthDeny(HANDLE hDbEvent,const PROTOCHAR *reason)
+{
+ return 1;
+}
+
+int OmegleProto::AuthRecv(HANDLE hContact,PROTORECVEVENT *)
+{
+ return 1;
+}
+
+int OmegleProto::AuthRequest(HANDLE hContact,const PROTOCHAR *message)
+{
+ return 1;
+}
+
+HANDLE OmegleProto::ChangeInfo(int type,void *info_data)
+{
+ return NULL;
+}
+
+HANDLE OmegleProto::FileAllow(HANDLE hContact,HANDLE hTransfer,const PROTOCHAR *path)
+{
+ return NULL;
+}
+
+int OmegleProto::FileCancel(HANDLE hContact,HANDLE hTransfer)
+{
+ return 1;
+}
+
+int OmegleProto::FileDeny(HANDLE hContact,HANDLE hTransfer,const PROTOCHAR *reason)
+{
+ return 1;
+}
+
+int OmegleProto::FileResume(HANDLE hTransfer,int *action,const PROTOCHAR **filename)
+{
+ return 1;
+}
+
+int OmegleProto::GetInfo( HANDLE hContact, int infoType )
+{
+ return 1;
+}
+
+HANDLE OmegleProto::SearchBasic( const PROTOCHAR* id )
+{
+ return NULL;
+}
+
+HANDLE OmegleProto::SearchByEmail( const PROTOCHAR* email )
+{
+ return NULL;
+}
+
+HANDLE OmegleProto::SearchByName( const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName )
+{
+ return NULL;
+}
+
+HWND OmegleProto::SearchAdvanced(HWND owner)
+{
+ return NULL;
+}
+
+HWND OmegleProto::CreateExtendedSearchUI(HWND owner)
+{
+ return NULL;
+}
+
+int OmegleProto::RecvContacts(HANDLE hContact,PROTORECVEVENT *)
+{
+ return 1;
+}
+
+int OmegleProto::RecvFile(HANDLE hContact,PROTORECVFILET *)
+{
+ return 1;
+}
+
+int OmegleProto::RecvUrl(HANDLE hContact,PROTORECVEVENT *)
+{
+ return 1;
+}
+
+int OmegleProto::SendContacts(HANDLE hContact,int flags,int nContacts,HANDLE *hContactsList)
+{
+ return 1;
+}
+
+HANDLE OmegleProto::SendFile(HANDLE hContact,const PROTOCHAR *desc, PROTOCHAR **files)
+{
+ return NULL;
+}
+
+int OmegleProto::SendUrl(HANDLE hContact,int flags,const char *url)
+{
+ return 1;
+}
+
+int OmegleProto::SetApparentMode(HANDLE hContact,int mode)
+{
+ return 1;
+}
+
+int OmegleProto::RecvAwayMsg(HANDLE hContact,int mode,PROTORECVEVENT *evt)
+{
+ return 1;
+}
+
+int OmegleProto::SendAwayMsg(HANDLE hContact,HANDLE hProcess,const char *msg)
+{
+ return 1;
+}
+
+int OmegleProto::UserIsTyping(HANDLE hContact, int type)
+{
+ return 1;
+}
+
+int OmegleProto::SetAwayMsg(int iStatus, const PROTOCHAR* msg)
+{
+ return 1;
+}
+
+HANDLE OmegleProto::GetAwayMsg( HANDLE hContact )
+{
+ return NULL;
+}
+
+int OmegleProto::RecvMsg(HANDLE hContact, PROTORECVEVENT *pre)
+{
+ return 1;
+}
diff --git a/protocols/Omegle/src/theme.cpp b/protocols/Omegle/src/theme.cpp
new file mode 100644
index 0000000000..d7f7fc7e9b
--- /dev/null
+++ b/protocols/Omegle/src/theme.cpp
@@ -0,0 +1,115 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+extern OBJLIST<OmegleProto> g_Instances;
+
+struct
+{
+ const char* name;
+ const char* descr;
+ int defIconID;
+ const char* section;
+}
+static const icons[] =
+{
+ { "omegle", LPGEN("Omegle Icon"), IDI_OMEGLE },
+// { "homepage", LPGEN("Visit Profile"), 0, "core_main_2" },
+};
+
+static HANDLE hIconLibItem[SIZEOF(icons)];
+
+// TODO: uninit
+void InitIcons(void)
+{
+ TCHAR szFile[MAX_PATH];
+ GetModuleFileName(g_hInstance, szFile, SIZEOF(szFile));
+
+ char setting_name[100];
+ char section_name[100];
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszDefaultFile = szFile;
+ sid.cx = sid.cy = 16;
+ sid.pszName = setting_name;
+ sid.pszSection = section_name;
+ sid.flags = SIDF_PATH_TCHAR;
+
+ for (int i=0; i<SIZEOF(icons); i++)
+ {
+ if(icons[i].defIconID)
+ {
+ mir_snprintf(setting_name,sizeof(setting_name),"%s_%s","Omegle",icons[i].name);
+
+ if (icons[i].section)
+ {
+ mir_snprintf(section_name,sizeof(section_name),"%s/%s/%s",LPGEN("Protocols"),
+ LPGEN("Omegle"), icons[i].section);
+ } else {
+ mir_snprintf(section_name,sizeof(section_name),"%s/%s",LPGEN("Protocols"),
+ LPGEN("Omegle"));
+ }
+
+ sid.pszDescription = (char*)icons[i].descr;
+ sid.iDefaultIndex = -icons[i].defIconID;
+ hIconLibItem[i] = Skin_AddIcon(&sid);
+ } else { // External icons
+ hIconLibItem[i] = (HANDLE)CallService(MS_SKIN2_GETICONHANDLE,0,
+ (LPARAM)icons[i].section);
+ }
+ }
+}
+
+HANDLE GetIconHandle(const char* name)
+{
+ for(size_t i=0; i<SIZEOF(icons); i++)
+ {
+ if(strcmp(icons[i].name,name) == 0)
+ return hIconLibItem[i];
+ }
+ return 0;
+}
+
+// Helper functions
+static OmegleProto * GetInstanceByHContact(HANDLE hContact)
+{
+ char *proto = reinterpret_cast<char*>( CallService(MS_PROTO_GETCONTACTBASEPROTO,
+ reinterpret_cast<WPARAM>(hContact),0));
+ if (!proto)
+ return 0;
+
+ for(int i=0; i<g_Instances.getCount(); i++)
+ if (!strcmp(proto,g_Instances[i].m_szModuleName))
+ return &g_Instances[i];
+
+ return 0;
+}
+
+template<int (__cdecl OmegleProto::*Fcn)(WPARAM,LPARAM)>
+INT_PTR GlobalService(WPARAM wParam,LPARAM lParam)
+{
+ OmegleProto *proto = GetInstanceByHContact(reinterpret_cast<HANDLE>(wParam));
+ return proto ? (proto->*Fcn)(wParam,lParam) : 0;
+}
+
diff --git a/protocols/Omegle/src/theme.h b/protocols/Omegle/src/theme.h
new file mode 100644
index 0000000000..7456803b6c
--- /dev/null
+++ b/protocols/Omegle/src/theme.h
@@ -0,0 +1,30 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+void InitIcons(void);
+HANDLE GetIconHandle(const char *name);
+
+//void InitContactMenus(void);
+//void UninitContactMenus(void);
+//void ShowContactMenus(bool show, bool deleted = false); \ No newline at end of file
diff --git a/protocols/Omegle/src/utils.cpp b/protocols/Omegle/src/utils.cpp
new file mode 100644
index 0000000000..f524dcfba1
--- /dev/null
+++ b/protocols/Omegle/src/utils.cpp
@@ -0,0 +1,150 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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 "common.h"
+
+std::string utils::url::encode(const std::string &s)
+{
+ char *encoded = reinterpret_cast<char*>(CallService( MS_NETLIB_URLENCODE,
+ 0,reinterpret_cast<LPARAM>(s.c_str())));
+ std::string ret = encoded;
+ HeapFree(GetProcessHeap(),0,encoded);
+
+ return ret;
+}
+
+void utils::text::replace_first( std::string* data, std::string from, std::string to )
+{
+ std::string::size_type position = 0;
+
+ if ( ( position = data->find(from, position)) != std::string::npos )
+ {
+ data->replace( position, from.size(), to );
+ position++;
+ }
+}
+
+void utils::text::replace_all( std::string* data, std::string from, std::string to )
+{
+ std::string::size_type position = 0;
+
+ while ( ( position = data->find( from, position )) != std::string::npos )
+ {
+ data->replace( position, from.size(), to );
+ position++;
+ }
+}
+
+std::string utils::text::special_expressions_decode( std::string data )
+{
+ utils::text::replace_all( &data, "\\r", "\r" );
+ utils::text::replace_all( &data, "\\n", "\n" );
+ utils::text::replace_all( &data, "\\\"", "\"" );
+ utils::text::replace_all( &data, "\\\\", "\\" );
+
+ return data;
+}
+
+
+std::string utils::text::slashu_to_utf8( std::string data )
+{
+ std::string new_string = "";
+
+ for ( std::string::size_type i = 0; i < data.length( ); i++ )
+ {
+ if ( data.at(i) == '\\' && (i+1) < data.length( ) && data.at(i+1) == 'u' )
+ {
+ unsigned int udn = strtol( data.substr( i + 2, 4 ).c_str(), NULL, 16 );
+
+ if ( udn >= 128 && udn <= 2047 )
+ { // U+0080 .. U+07FF
+ new_string += ( char )( 192 + ( udn / 64 ));
+ new_string += ( char )( 128 + ( udn % 64 ));
+ }
+ else if ( udn >= 2048 && udn <= 65535 )
+ { // U+0800 .. U+FFFF
+ new_string += ( char )( 224 + ( udn / 4096 ));
+ new_string += ( char )( 128 + ( ( udn / 64 ) % 64 ));
+ new_string += ( char )( 128 + ( udn % 64 ));
+ }
+ else if ( udn <= 127 )
+ { // U+0000 .. U+007F (should not appear)
+ new_string += ( char )udn;
+ }
+
+ i += 5;
+ continue;
+ }
+
+ new_string += data.at(i);
+ }
+
+ return new_string;
+}
+
+std::string utils::text::trim( 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;
+
+ return (begin != std::string::npos) ? data.substr( begin, end - begin ) : "";
+}
+
+int utils::debug::log(std::string file_name, std::string text)
+{
+ char szFile[MAX_PATH];
+ GetModuleFileNameA(g_hInstance, szFile, SIZEOF(szFile));
+ std::string path = szFile;
+ path = path.substr( 0, path.rfind( "\\" ));
+ path = path.substr( 0, path.rfind( "\\" ) + 1 );
+ path = path + file_name.c_str() + ".txt";
+
+ SYSTEMTIME time;
+ GetLocalTime( &time );
+
+ std::ofstream out( path.c_str(), std::ios_base::out | std::ios_base::app | std::ios_base::ate );
+ out << "[" << (time.wHour < 10 ? "0" : "") << time.wHour << ":" << (time.wMinute < 10 ? "0" : "") << time.wMinute << ":" << (time.wSecond < 10 ? "0" : "") << time.wSecond << "] " << text << std::endl;
+ out.close( );
+
+ return EXIT_SUCCESS;
+}
+
+void __fastcall utils::mem::detract(char** str )
+{
+ utils::mem::detract( ( void** )str );
+}
+
+void __fastcall utils::mem::detract(void** p)
+{
+ utils::mem::detract((void*)(*p));
+}
+
+void __fastcall utils::mem::detract(void* p)
+{
+ mir_free(p);
+}
+
+void* __fastcall utils::mem::allocate(size_t size)
+{
+ return mir_calloc(size);
+}
diff --git a/protocols/Omegle/src/utils.h b/protocols/Omegle/src/utils.h
new file mode 100644
index 0000000000..908b721e72
--- /dev/null
+++ b/protocols/Omegle/src/utils.h
@@ -0,0 +1,103 @@
+/*
+
+Omegle plugin for Miranda Instant Messenger
+_____________________________________________
+
+Copyright © 2011-12 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/>.
+
+*/
+
+#pragma once
+
+template<typename T>
+void CreateProtoService(const char *module,const char *service,
+ int (__cdecl T::*serviceProc)(WPARAM,LPARAM),T *self)
+{
+ char temp[MAX_PATH*2];
+
+ mir_snprintf(temp,sizeof(temp),"%s%s",module,service);
+ CreateServiceFunctionObj(temp,( MIRANDASERVICEOBJ )*(void**)&serviceProc, self );
+}
+
+template<typename T>
+void HookProtoEvent(const char* evt, int (__cdecl T::*eventProc)(WPARAM,LPARAM), T *self)
+{
+ ::HookEventObj(evt,(MIRANDAHOOKOBJ)*(void**)&eventProc,self);
+}
+
+template<typename T>
+HANDLE ForkThreadEx(void (__cdecl T::*thread)(void*),T *self,void *data = 0)
+{
+ return reinterpret_cast<HANDLE>( mir_forkthreadowner(
+ (pThreadFuncOwner)*(void**)&thread,self,data,0));
+}
+
+template<typename T>
+void ForkThread(void (__cdecl T::*thread)(void*),T *self,void *data = 0)
+{
+ CloseHandle(ForkThreadEx(thread,self,data));
+}
+
+namespace utils
+{
+ namespace url
+ {
+ std::string encode(const std::string &s);
+ };
+
+ namespace text
+ {
+ void replace_first( std::string* data, std::string from, std::string to );
+ void replace_all( std::string* data, std::string from, std::string to );
+ std::string special_expressions_decode( std::string data );
+ std::string slashu_to_utf8( std::string data );
+ std::string trim( std::string data );
+ };
+
+ namespace debug
+ {
+ int log(std::string file_name, std::string text);
+ };
+
+ namespace mem
+ {
+ void __fastcall detract(char** str );
+ void __fastcall detract(void** p);
+ void __fastcall detract(void* p);
+ void* __fastcall allocate(size_t size);
+ };
+};
+
+class ScopedLock
+{
+public:
+ ScopedLock(HANDLE h) : handle_(h)
+ {
+ WaitForSingleObject(handle_,INFINITE);
+ }
+ ~ScopedLock()
+ {
+ if(handle_)
+ ReleaseMutex(handle_);
+ }
+ void Unlock()
+ {
+ ReleaseMutex(handle_);
+ handle_ = 0;
+ }
+private:
+ HANDLE handle_;
+};