From c80bc292b555c6666930790c399f6fac6226c468 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Sat, 21 Jul 2012 10:11:53 +0000 Subject: Skype and IMO2sProxy added, not adapted yet git-svn-id: http://svn.miranda-ng.org/main/trunk@1091 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Skype/Skript1.aps | Bin 0 -> 122080 bytes protocols/Skype/Skript1.rc | 484 +++++ protocols/Skype/Skype_protocol.dsp | 394 ++++ protocols/Skype/Skype_protocol.dsw | 29 + protocols/Skype/Skype_protocol.mak | 238 +++ protocols/Skype/Skype_protocol.sln | 44 + protocols/Skype/Skype_protocol.vcproj | 2843 +++++++++++++++++++++++++ protocols/Skype/alogon.c | 129 ++ protocols/Skype/alogon.h | 1 + protocols/Skype/changelog.txt | 330 +++ protocols/Skype/contacts.c | 417 ++++ protocols/Skype/contacts.h | 11 + protocols/Skype/debug.c | 75 + protocols/Skype/debug.h | 23 + protocols/Skype/deploy.bat | 15 + protocols/Skype/ezxml/ezxml.c | 1033 +++++++++ protocols/Skype/ezxml/ezxml.h | 167 ++ protocols/Skype/gchat.c | 910 ++++++++ protocols/Skype/gchat.h | 47 + protocols/Skype/m_popup.h | 307 +++ protocols/Skype/m_toptoolbar.h | 107 + protocols/Skype/make.bat | 6 + protocols/Skype/make_w32.bat | 5 + protocols/Skype/make_w64.bat | 6 + protocols/Skype/memlist.c | 248 +++ protocols/Skype/memlist.h | 43 + protocols/Skype/msglist.c | 86 + protocols/Skype/msglist.h | 15 + protocols/Skype/msgq.c | 90 + protocols/Skype/msgq.h | 64 + protocols/Skype/pthread.c | 70 + protocols/Skype/pthread.h | 26 + protocols/Skype/readme.txt | 47 + protocols/Skype/res/8060.ico | Bin 0 -> 2550 bytes protocols/Skype/res/Copy of online.ico | Bin 0 -> 1406 bytes protocols/Skype/res/DND.ico | Bin 0 -> 2550 bytes protocols/Skype/res/Invite.ico | Bin 0 -> 1886 bytes protocols/Skype/res/NA.ico | Bin 0 -> 2550 bytes protocols/Skype/res/add.ico | Bin 0 -> 2550 bytes protocols/Skype/res/add2.ico | Bin 0 -> 2550 bytes protocols/Skype/res/auth.ico | Bin 0 -> 2550 bytes protocols/Skype/res/away.ico | Bin 0 -> 2550 bytes protocols/Skype/res/call.bmp | Bin 0 -> 214 bytes protocols/Skype/res/call.ico | Bin 0 -> 2550 bytes protocols/Skype/res/chat.ico | Bin 0 -> 2550 bytes protocols/Skype/res/conference.ico | Bin 0 -> 2550 bytes protocols/Skype/res/error.ico | Bin 0 -> 9062 bytes protocols/Skype/res/hang_up.ico | Bin 0 -> 2550 bytes protocols/Skype/res/history.ico | Bin 0 -> 2550 bytes protocols/Skype/res/hold.ico | Bin 0 -> 2550 bytes protocols/Skype/res/import.ico | Bin 0 -> 2550 bytes protocols/Skype/res/invisible.ico | Bin 0 -> 2550 bytes protocols/Skype/res/message.ico | Bin 0 -> 2550 bytes protocols/Skype/res/occupied.ico | Bin 0 -> 2550 bytes protocols/Skype/res/offline.ico | Bin 0 -> 2550 bytes protocols/Skype/res/online.ico | Bin 0 -> 2550 bytes protocols/Skype/res/pause.ico | Bin 0 -> 2550 bytes protocols/Skype/res/phone.ico | Bin 0 -> 2550 bytes protocols/Skype/res/resume.ico | Bin 0 -> 2550 bytes protocols/Skype/res/search.ico | Bin 0 -> 2550 bytes protocols/Skype/res/skype.ico | Bin 0 -> 13270 bytes protocols/Skype/res/skypeout.ico | Bin 0 -> 2550 bytes protocols/Skype/res/skyping.ico | Bin 0 -> 2038 bytes protocols/Skype/resource.h | 124 ++ protocols/Skype/skype.c | 3465 +++++++++++++++++++++++++++++++ protocols/Skype/skype.h | 188 ++ protocols/Skype/skypeapi.c | 1699 +++++++++++++++ protocols/Skype/skypeapi.h | 69 + protocols/Skype/skypeopt.c | 969 +++++++++ protocols/Skype/skypeopt.h | 49 + protocols/Skype/skypeprofile.c | 145 ++ protocols/Skype/skypeprofile.h | 33 + protocols/Skype/skypeproxy.h | 7 + protocols/Skype/skypeproxy/skypeproxy.c | 651 ++++++ protocols/Skype/skypeproxy/skypeproxy.h | 36 + protocols/Skype/skypesvc.c | 188 ++ protocols/Skype/skypesvc.h | 24 + protocols/Skype/utf8.c | 334 +++ protocols/Skype/utf8.h | 47 + protocols/Skype/util.c | 57 + protocols/Skype/util.h | 7 + protocols/Skype/voiceservice.c | 156 ++ protocols/Skype/voiceservice.h | 18 + 83 files changed, 16576 insertions(+) create mode 100644 protocols/Skype/Skript1.aps create mode 100644 protocols/Skype/Skript1.rc create mode 100644 protocols/Skype/Skype_protocol.dsp create mode 100644 protocols/Skype/Skype_protocol.dsw create mode 100644 protocols/Skype/Skype_protocol.mak create mode 100644 protocols/Skype/Skype_protocol.sln create mode 100644 protocols/Skype/Skype_protocol.vcproj create mode 100644 protocols/Skype/alogon.c create mode 100644 protocols/Skype/alogon.h create mode 100644 protocols/Skype/changelog.txt create mode 100644 protocols/Skype/contacts.c create mode 100644 protocols/Skype/contacts.h create mode 100644 protocols/Skype/debug.c create mode 100644 protocols/Skype/debug.h create mode 100644 protocols/Skype/deploy.bat create mode 100644 protocols/Skype/ezxml/ezxml.c create mode 100644 protocols/Skype/ezxml/ezxml.h create mode 100644 protocols/Skype/gchat.c create mode 100644 protocols/Skype/gchat.h create mode 100644 protocols/Skype/m_popup.h create mode 100644 protocols/Skype/m_toptoolbar.h create mode 100644 protocols/Skype/make.bat create mode 100644 protocols/Skype/make_w32.bat create mode 100644 protocols/Skype/make_w64.bat create mode 100644 protocols/Skype/memlist.c create mode 100644 protocols/Skype/memlist.h create mode 100644 protocols/Skype/msglist.c create mode 100644 protocols/Skype/msglist.h create mode 100644 protocols/Skype/msgq.c create mode 100644 protocols/Skype/msgq.h create mode 100644 protocols/Skype/pthread.c create mode 100644 protocols/Skype/pthread.h create mode 100644 protocols/Skype/readme.txt create mode 100644 protocols/Skype/res/8060.ico create mode 100644 protocols/Skype/res/Copy of online.ico create mode 100644 protocols/Skype/res/DND.ico create mode 100644 protocols/Skype/res/Invite.ico create mode 100644 protocols/Skype/res/NA.ico create mode 100644 protocols/Skype/res/add.ico create mode 100644 protocols/Skype/res/add2.ico create mode 100644 protocols/Skype/res/auth.ico create mode 100644 protocols/Skype/res/away.ico create mode 100644 protocols/Skype/res/call.bmp create mode 100644 protocols/Skype/res/call.ico create mode 100644 protocols/Skype/res/chat.ico create mode 100644 protocols/Skype/res/conference.ico create mode 100644 protocols/Skype/res/error.ico create mode 100644 protocols/Skype/res/hang_up.ico create mode 100644 protocols/Skype/res/history.ico create mode 100644 protocols/Skype/res/hold.ico create mode 100644 protocols/Skype/res/import.ico create mode 100644 protocols/Skype/res/invisible.ico create mode 100644 protocols/Skype/res/message.ico create mode 100644 protocols/Skype/res/occupied.ico create mode 100644 protocols/Skype/res/offline.ico create mode 100644 protocols/Skype/res/online.ico create mode 100644 protocols/Skype/res/pause.ico create mode 100644 protocols/Skype/res/phone.ico create mode 100644 protocols/Skype/res/resume.ico create mode 100644 protocols/Skype/res/search.ico create mode 100644 protocols/Skype/res/skype.ico create mode 100644 protocols/Skype/res/skypeout.ico create mode 100644 protocols/Skype/res/skyping.ico create mode 100644 protocols/Skype/resource.h create mode 100644 protocols/Skype/skype.c create mode 100644 protocols/Skype/skype.h create mode 100644 protocols/Skype/skypeapi.c create mode 100644 protocols/Skype/skypeapi.h create mode 100644 protocols/Skype/skypeopt.c create mode 100644 protocols/Skype/skypeopt.h create mode 100644 protocols/Skype/skypeprofile.c create mode 100644 protocols/Skype/skypeprofile.h create mode 100644 protocols/Skype/skypeproxy.h create mode 100644 protocols/Skype/skypeproxy/skypeproxy.c create mode 100644 protocols/Skype/skypeproxy/skypeproxy.h create mode 100644 protocols/Skype/skypesvc.c create mode 100644 protocols/Skype/skypesvc.h create mode 100644 protocols/Skype/utf8.c create mode 100644 protocols/Skype/utf8.h create mode 100644 protocols/Skype/util.c create mode 100644 protocols/Skype/util.h create mode 100644 protocols/Skype/voiceservice.c create mode 100644 protocols/Skype/voiceservice.h (limited to 'protocols') diff --git a/protocols/Skype/Skript1.aps b/protocols/Skype/Skript1.aps new file mode 100644 index 0000000000..d99f14a71e Binary files /dev/null and b/protocols/Skype/Skript1.aps differ diff --git a/protocols/Skype/Skript1.rc b/protocols/Skype/Skript1.rc new file mode 100644 index 0000000000..b2052187b7 --- /dev/null +++ b/protocols/Skype/Skript1.rc @@ -0,0 +1,484 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SETAVATAR DIALOGEX 0, 0, 222, 131 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "Set",IDC_SETAVATAR,10,108,45,13,WS_GROUP + PUSHBUTTON "Delete",IDC_DELETEAVATAR,57,108,45,13 + CONTROL "",IDC_AVATAR,"Static",SS_BITMAP | SS_CENTERIMAGE | + SS_SUNKEN | WS_GROUP,10,10,96,93 +END + +IDD_OPT_DEFAULT DIALOGEX 0, 0, 310, 223 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Start Skype with Miranda IM if not running using the following command line options:", + IDC_STARTSKYPE,"Button",BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP,10,4,290,10 + CONTROL "/NOSPLASH - Don't show splash screen on startup", + IDC_NOSPLASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,17, + 264,12 + CONTROL "/MINIMIZED - Start Skype minimized",IDC_MINIMIZED, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,28,264,12 + CONTROL "/NOTRAY - Skype tray icon becomes grey and is therefore ""invisible""", + IDC_NOTRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,40, + 264,12 + CONTROL "/REMOVEABLE - For running portable skype", + IDC_REMOVEABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,36, + 51,264,12 + CONTROL "/SECONDARY - This is the second instance",IDC_SECONDARY, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,62,264,12 + CONTROL "/DATAPATH - Specify Skype data folder*",IDC_DATAPATHO, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,36,74,264,12 + EDITTEXT IDC_DATAPATH,47,88,236,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BROWSEDP,285,87,16,15 + CONTROL "Use custom Skype executable*",IDC_CUSTOMCOMMAND,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,36,103,264,10 + EDITTEXT IDC_COMMANDLINE,47,116,236,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BROWSECMDL,285,115,16,15 + CTEXT "* Relative path root is Miranda IM folder", + IDC_STATIC_PATHINFO,10,136,290,8,NOT WS_GROUP + CONTROL "Shutdown Skype when you close Miranda IM",IDC_SHUTDOWN, + "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,10,151, + 290,10 + CONTROL "Unload Skype when you change to Offline status", + IDC_UNLOADOFFLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 10,164,290,11 + LTEXT "Try at least",IDC_STATIC,10,185,39,8 + EDITTEXT IDC_CONNATTEMPTS,52,183,21,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "times to connect to Skype API before giving up", + IDC_STATIC,78,185,224,8,NOT WS_GROUP + LTEXT "User name:",IDC_STATIC,10,206,38,8 + EDITTEXT IDC_USERNAME,52,204,79,12,ES_AUTOHSCROLL + LTEXT "Password:",IDC_STATIC,148,206,34,8 + EDITTEXT IDC_PASSWORD,186,204,79,12,ES_PASSWORD | ES_AUTOHSCROLL +END + +IDD_DIAL DIALOGEX 0, 0, 198, 46 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Dial" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Number:",IDC_STATIC,7,8,30,11 + COMBOBOX IDC_NUMBER,41,6,149,13,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + DEFPUSHBUTTON "Dial",IDDIAL,88,25,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,141,25,50,14 +END + +IDD_CALLSTAT DIALOGEX 0, 0, 220, 67 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION +CAPTION "%s is calling" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Join conference with %s",IDC_JOIN,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,7,7,206,10 + CONTROL "Answer call; set call to %s on hold",IDC_HOLD,"Button", + BS_AUTORADIOBUTTON,7,19,206,10 + CONTROL "Hang up",IDC_HANGUP,"Button",BS_AUTORADIOBUTTON,7,31, + 206,10 + DEFPUSHBUTTON "OK",IDOK,163,46,50,14,WS_GROUP +END + +IDD_INPUTBOX DIALOGEX 0, 0, 221, 46 +STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_TEXT,7,7,207,13,ES_AUTOHSCROLL | WS_GROUP + DEFPUSHBUTTON "OK",IDOK,112,25,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,165,25,50,14 +END + +IDD_OPTIONS DIALOGEX 0, 0, 313, 249 +STYLE DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Tab1",IDC_OPTIONSTAB,"SysTabControl32",0x0,0,-1,313,250 +END + +IDD_OPT_PROXY DIALOGEX 0, 0, 310, 223 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Use Skype proxy connection over network instead of local Skype API", + IDC_USES2S,"Button",BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP,10,4,290,9 + LTEXT "Host:",IDC_STATIC_HOST,20,21,18,10 + EDITTEXT IDC_HOST,41,19,133,12,ES_AUTOHSCROLL + LTEXT "Port:",IDC_STATIC_PORT,180,21,16,10,0,WS_EX_RIGHT + EDITTEXT IDC_PORT,200,19,29,12,ES_AUTOHSCROLL | ES_NUMBER + CTEXT "* You must restart Miranda IM in order to let the settings take effect", + IDC_STATIC_RESTART,10,54,290,8,NOT WS_GROUP + CONTROL "This Skype proxy requires password authentication:", + IDC_REQPASS,"Button",BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP,20,38,176,9 + EDITTEXT IDC_PASSWORD,200,36,82,12,ES_PASSWORD | ES_AUTOHSCROLL +END + +IDD_SETDETAILS DIALOGEX 0, 0, 216, 151 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Name:",IDC_STATIC,7,6,61,9 + EDITTEXT IDC_FULLNAME,73,4,141,12,ES_AUTOHSCROLL + LTEXT "Birthday:",IDC_STATIC,7,20,61,9 + CONTROL "DateTimePicker1",IDC_BIRTHDAY,"SysDateTimePick32", + DTS_RIGHTALIGN | DTS_APPCANPARSE | WS_TABSTOP,73,18,62, + 12 + LTEXT "Sex:",IDC_STATIC,7,34,61,9 + COMBOBOX IDC_SEX,73,32,141,12,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "City:",IDC_STATIC,7,48,61,9 + EDITTEXT IDC_CITY,73,46,141,12,ES_AUTOHSCROLL + LTEXT "Country:",IDC_STATIC,7,62,61,9 + EDITTEXT IDC_COUNTRY,73,60,141,12,ES_AUTOHSCROLL + LTEXT "Province:",IDC_STATIC,7,76,61,9 + EDITTEXT IDC_PROVINCE,73,74,141,12,ES_AUTOHSCROLL + LTEXT "Home phone:",IDC_STATIC,7,90,61,9 + EDITTEXT IDC_HOMEPHONE,73,88,141,12,ES_AUTOHSCROLL + LTEXT "Office phone:",IDC_STATIC,7,104,61,9 + EDITTEXT IDC_OFFICEPHONE,73,102,141,12,ES_AUTOHSCROLL + LTEXT "Homepage:",IDC_STATIC,7,118,61,9 + EDITTEXT IDC_HOMEPAGE,73,116,141,12,ES_AUTOHSCROLL + PUSHBUTTON "Save",IDC_SAVEDETAILS,170,134,45,14,WS_GROUP +END + +IDD_OPT_ADVANCED DIALOGEX 0, 0, 310, 223 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "Enable Skype menu options (currently: Find/Add user)", + IDC_ENABLEMENU,"Button",BS_AUTOCHECKBOX | WS_GROUP | + WS_TABSTOP,10,4,290,9 + CONTROL "Use popup plugin for displaying messages ",IDC_USEPOPUP, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,19,290,9 + CONTROL "Suppress all error messages (not recommended, but if it annoys you... ;)", + IDC_NOERRORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,34, + 290,9 + CONTROL "Use group chat interface for conversations (requires group chat module)", + IDC_GROUPCHAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10, + 49,290,9 + CONTROL "Mark group chat message as read to avoid notification", + IDC_GROUPCHATREAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 10,64,290,9 + CONTROL "Keep requested online status on startup under every circumstance", + IDC_KEEPSTATE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10, + 79,290,9 + CONTROL "Use time zone patch",IDC_TIMEZONE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,10,94,290,9 + CONTROL "Ignore time zones",IDC_IGNTZ,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,109,290,9 + CONTROL "Show default skype avatar for contacts", + IDC_SHOWDEFAULTAVATAR,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,124,290,9 + CONTROL "Suppress call summary chat message", + IDC_SUPPRESSCALLSUMMARYMESSAGE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,10,139,290,9 + CONTROL "Disable support for N/A and SkypeMe status (for Skype 4+)", + IDC_NOSKYPE3STATS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 10,154,290,9 + CONTROL "Show full name in contact list instead of nickname", + IDC_SHOWFULLNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 10,169,290,9 + LTEXT "SkypeOut contacts are in status:",IDC_STATIC,10,186,108, + 8 + COMBOBOX IDC_SKYPEOUTSTAT,120,184,79,54,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Cleanup Nicknames",IDC_CLEANUP,9,201,80,14,BS_MULTILINE | + WS_GROUP +END + +IDD_OPT_POPUP DIALOGEX 0, 0, 310, 228 +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + GROUPBOX "Skype Popups",IDC_STATIC,0,1,309,227 + GROUPBOX "Incoming Calls",IDC_STATIC,6,16,297,62,WS_GROUP + CONTROL "Show incoming calls",IDC_POPUPINCOMING,"Button", + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,10,28,278,8 + EDITTEXT IDC_POPUPTIME,16,41,20,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "seconds",IDC_STATIC,41,43,92,8,NOT WS_GROUP + CONTROL "",IDC_POPUPBACKCOLOR,"ColourPicker",WS_GROUP | + WS_TABSTOP,142,40,39,12 + LTEXT "Background",IDC_STATIC_POPUPBACKCOLOR,186,42,50,8, + SS_CENTERIMAGE | NOT WS_GROUP + CONTROL "Use Windows colors",IDC_USEWINCOLORS,"Button", + BS_AUTOCHECKBOX | BS_NOTIFY | BS_FLAT | WS_TABSTOP,16,58, + 121,8 + CONTROL "",IDC_POPUPTEXTCOLOR,"ColourPicker",WS_TABSTOP,142,55, + 39,12 + LTEXT "Text",IDC_STATIC_POPUPTEXTCOLOR,186,56,50,8, + SS_CENTERIMAGE | NOT WS_GROUP + PUSHBUTTON "Preview",IDC_PREVIEW,247,58,50,14,WS_GROUP + GROUPBOX "Error Messages",IDC_STATIC,6,81,297,62,WS_GROUP + CONTROL "Display error messages",IDC_POPUPERROR,"Button", + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,10,94,278,8 + EDITTEXT IDC_POPUPTIMEERR,16,107,20,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "seconds",IDC_STATIC,41,109,92,8,NOT WS_GROUP + CONTROL "",IDC_POPUPBACKCOLORERR,"ColourPicker",WS_GROUP | + WS_TABSTOP,142,106,39,12 + LTEXT "Background",IDC_STATIC_POPUPBACKCOLORERR,186,108,50,8, + SS_CENTERIMAGE | NOT WS_GROUP + CONTROL "Use Windows colors",IDC_USEWINCOLORSERR,"Button", + BS_AUTOCHECKBOX | BS_NOTIFY | BS_FLAT | WS_TABSTOP,16, + 124,121,8 + CONTROL "",IDC_POPUPTEXTCOLORERR,"ColourPicker",WS_TABSTOP,142, + 121,39,12 + LTEXT "Text",IDC_STATIC_POPUPTEXTCOLORERR,186,123,50,8, + SS_CENTERIMAGE | NOT WS_GROUP + PUSHBUTTON "Preview",IDC_PREVIEWERR,247,124,50,14,WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + IDD_SETAVATAR, DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 212 + TOPMARGIN, 10 + BOTTOMMARGIN, 121 + END + + IDD_OPT_DEFAULT, DIALOG + BEGIN + LEFTMARGIN, 1 + VERTGUIDE, 10 + VERTGUIDE, 300 + TOPMARGIN, 4 + END + + IDD_DIAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 190 + TOPMARGIN, 6 + BOTTOMMARGIN, 39 + END + + IDD_CALLSTAT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 213 + TOPMARGIN, 7 + BOTTOMMARGIN, 60 + END + + IDD_INPUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 7 + BOTTOMMARGIN, 39 + END + + IDD_OPTIONS, DIALOG + BEGIN + RIGHTMARGIN, 311 + BOTTOMMARGIN, 243 + END + + IDD_OPT_PROXY, DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 300 + TOPMARGIN, 4 + BOTTOMMARGIN, 221 + END + + IDD_SETDETAILS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 214 + TOPMARGIN, 4 + BOTTOMMARGIN, 148 + END + + IDD_OPT_ADVANCED, DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 300 + TOPMARGIN, 4 + BOTTOMMARGIN, 221 + HORZGUIDE, 4 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SKYPE ICON DISCARDABLE "res\\skype.ico" +IDI_INVITE ICON DISCARDABLE "res\\Invite.ico" +IDI_ADD ICON DISCARDABLE "res\\add.ico" +IDI_IMPORT ICON DISCARDABLE "res\\import.ico" +IDI_ERRORS ICON DISCARDABLE "res\\error.ico" +IDI_MESSAGE ICON DISCARDABLE "res\\message.ico" +IDI_CALL ICON DISCARDABLE "res\\call.ico" +IDI_CALLSKYPEOUT ICON DISCARDABLE "res\\skypeout.ico" +IDI_HOLD ICON DISCARDABLE "res\\hold.ico" +IDI_RESUME ICON DISCARDABLE "res\\resume.ico" +IDI_HANGUP ICON DISCARDABLE "res\\hang_up.ico" +IDI_ONLINE ICON DISCARDABLE "res\\online.ico" +IDI_CHAT ICON DISCARDABLE "res\\chat.ico" +IDI_AWAY ICON DISCARDABLE "res\\away.ico" +IDI_NA ICON DISCARDABLE "res\\na.ico" +IDI_OCCUPIED ICON DISCARDABLE "res\\occupied.ico" +IDI_DND ICON DISCARDABLE "res\\dnd.ico" +IDI_INVISIBLE ICON DISCARDABLE "res\\invisible.ico" +IDI_OFFLINE ICON DISCARDABLE "res\\offline.ico" +IDI_PHONE ICON DISCARDABLE "res\\phone.ico" + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,53 + PRODUCTVERSION 0,0,0,53 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Miranda IM community\0" + VALUE "FileDescription", "Skype\0" + VALUE "FileVersion", "0, 0, 0, 53\0" + VALUE "InternalName", "Skype\0" + VALUE "LegalCopyright", "Copyright © 2007-2011 leecher - tweety - jls17\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "Skype.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Skype Protocol for Miranda IM\0" + VALUE "ProductVersion", "0, 0, 0, 53\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_CALL BITMAP MOVEABLE PURE "res\\call.bmp" +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Österreich) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Deutsch (Österreich) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/protocols/Skype/Skype_protocol.dsp b/protocols/Skype/Skype_protocol.dsp new file mode 100644 index 0000000000..3c9191838e --- /dev/null +++ b/protocols/Skype/Skype_protocol.dsp @@ -0,0 +1,394 @@ +# Microsoft Developer Studio Project File - Name="Skype_protocol" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Skype_protocol - Win32 Debug UNICODE +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "Skype_protocol.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "Skype_protocol.mak" CFG="Skype_protocol - Win32 Debug UNICODE" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "Skype_protocol - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Skype_protocol - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Skype_protocol - Win32 Debug UNICODE" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Skype_protocol - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc07 /d "NDEBUG" +# ADD RSC /l 0xc07 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /machine:I386 /out:"../../bin/release/plugins/skype.dll" + +!ELSEIF "$(CFG)" == "Skype_protocol - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc07 /d "_DEBUG" +# ADD RSC /l 0xc07 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../../miranda-testaim/Miranda/plugins/Skype.dll" /pdbtype:sept +# SUBTRACT LINK32 /map + +!ELSEIF "$(CFG)" == "Skype_protocol - Win32 Debug UNICODE" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Skype_protocol___Win32_Debug_UNICODE" +# PROP BASE Intermediate_Dir "Skype_protocol___Win32_Debug_UNICODE" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Skype_protocol___Win32_Debug_UNICODE" +# PROP Intermediate_Dir "Skype_protocol___Win32_Debug_UNICODE" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /YX /FD /GZ /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc07 /d "_DEBUG" +# ADD RSC /l 0xc07 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug/plugins/Skype.dll" /pdbtype:sept +# SUBTRACT BASE LINK32 /map +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug Unicode/plugins/Skype.dll" /pdbtype:sept +# SUBTRACT LINK32 /map + +!ENDIF + +# Begin Target + +# Name "Skype_protocol - Win32 Release" +# Name "Skype_protocol - Win32 Debug" +# Name "Skype_protocol - Win32 Debug UNICODE" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\alogon.c +# End Source File +# Begin Source File + +SOURCE=.\contacts.c +# End Source File +# Begin Source File + +SOURCE=.\debug.c +# End Source File +# Begin Source File + +SOURCE=.\gchat.c +# End Source File +# Begin Source File + +SOURCE=.\memlist.c +# End Source File +# Begin Source File + +SOURCE=.\msglist.c +# End Source File +# Begin Source File + +SOURCE=.\msgq.c +# End Source File +# Begin Source File + +SOURCE=.\pthread.c +# End Source File +# Begin Source File + +SOURCE=.\skype.c +# End Source File +# Begin Source File + +SOURCE=.\skypeapi.c +# End Source File +# Begin Source File + +SOURCE=.\skypeopt.c +# End Source File +# Begin Source File + +SOURCE=.\skypeprofile.c +# End Source File +# Begin Source File + +SOURCE=.\skypesvc.c +# End Source File +# Begin Source File + +SOURCE=.\utf8.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# Begin Source File + +SOURCE=.\voiceservice.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\alogon.h +# End Source File +# Begin Source File + +SOURCE=.\contacts.h +# End Source File +# Begin Source File + +SOURCE=.\debug.h +# End Source File +# Begin Source File + +SOURCE=.\gchat.h +# End Source File +# Begin Source File + +SOURCE=.\m_popup.h +# End Source File +# Begin Source File + +SOURCE=.\m_toptoolbar.h +# End Source File +# Begin Source File + +SOURCE=.\memlist.h +# End Source File +# Begin Source File + +SOURCE=.\msglist.h +# End Source File +# Begin Source File + +SOURCE=.\msgq.h +# End Source File +# Begin Source File + +SOURCE=.\pthread.h +# End Source File +# Begin Source File + +SOURCE=.\skype.h +# End Source File +# Begin Source File + +SOURCE=.\skypeapi.h +# End Source File +# Begin Source File + +SOURCE=.\skypeopt.h +# End Source File +# Begin Source File + +SOURCE=.\skypeprofile.h +# End Source File +# Begin Source File + +SOURCE=.\skypesvc.h +# End Source File +# Begin Source File + +SOURCE=.\utf8.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# Begin Source File + +SOURCE=.\voiceservice.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\res\add.ico +# End Source File +# Begin Source File + +SOURCE=.\res\away.ico +# End Source File +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\res\call.bmp +# End Source File +# Begin Source File + +SOURCE=.\Call.ico +# End Source File +# Begin Source File + +SOURCE=.\res\call.ico +# End Source File +# Begin Source File + +SOURCE=.\res\chat.ico +# End Source File +# Begin Source File + +SOURCE=.\res\DND.ico +# End Source File +# Begin Source File + +SOURCE=.\res\error.ico +# End Source File +# Begin Source File + +SOURCE=.\res\hang_up.ico +# End Source File +# Begin Source File + +SOURCE=.\Hangup.ico +# End Source File +# Begin Source File + +SOURCE=.\res\hold.ico +# End Source File +# Begin Source File + +SOURCE=.\holdcall.ico +# End Source File +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# Begin Source File + +SOURCE=.\icon2.ico +# End Source File +# Begin Source File + +SOURCE=.\res\import.ico +# End Source File +# Begin Source File + +SOURCE=.\res\invisible.ico +# End Source File +# Begin Source File + +SOURCE=.\res\Invite.ico +# End Source File +# Begin Source File + +SOURCE=.\res\message.ico +# End Source File +# Begin Source File + +SOURCE=.\res\NA.ico +# End Source File +# Begin Source File + +SOURCE=.\res\occupied.ico +# End Source File +# Begin Source File + +SOURCE=.\res\offline.ico +# End Source File +# Begin Source File + +SOURCE=.\res\online.ico +# End Source File +# Begin Source File + +SOURCE=.\res\phone.ico +# End Source File +# Begin Source File + +SOURCE=.\res\resume.ico +# End Source File +# Begin Source File + +SOURCE=.\resumecall.ico +# End Source File +# Begin Source File + +SOURCE=.\Skript1.rc +# End Source File +# Begin Source File + +SOURCE=.\res\skype.ico +# End Source File +# Begin Source File + +SOURCE=.\res\skypeout.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\changelog.txt +# End Source File +# End Target +# End Project diff --git a/protocols/Skype/Skype_protocol.dsw b/protocols/Skype/Skype_protocol.dsw new file mode 100644 index 0000000000..3965e55d3e --- /dev/null +++ b/protocols/Skype/Skype_protocol.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "Skype_protocol"=.\Skype_protocol.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/protocols/Skype/Skype_protocol.mak b/protocols/Skype/Skype_protocol.mak new file mode 100644 index 0000000000..cf43334fb3 --- /dev/null +++ b/protocols/Skype/Skype_protocol.mak @@ -0,0 +1,238 @@ +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE Keine Konfiguration angegeben. Win32 Debug wird als Standard verwendet. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" && "$(CFG)" != "Win64 Release" && "$(CFG)" != "Win64 Debug" && "$(CFG)" != "Win32 UNICODE Release" && "$(CFG)" != "Win32 UNICODE Debug" && "$(CFG)" != "Win64 UNICODE Release" && "$(CFG)" != "Win64 UNICODE Debug" +!MESSAGE Ungültige Konfiguration "$(CFG)" angegeben. +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "Skype_protocol.mak" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "Win32 Release" +!MESSAGE "Win32 Debug" +!MESSAGE "Win64 Release" +!MESSAGE "Win64 Debug" +!MESSAGE "Win32 UNICODE Release" +!MESSAGE "Win32 UNICODE Debug" +!MESSAGE "Win64 UNICODE Release" +!MESSAGE "Win64 UNICODE Debug" + +!MESSAGE +!ERROR Eine ungültige Konfiguration wurde angegeben. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +LINK32=link.exe + +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib wsock32.lib comctl32.lib Rpcrt4.lib /nologo /dll /pdb:"$(INTDIR)\skype.pdb" /out:"$(OUTDIR)/skype.dll" /implib:"$(INTDIR)\skype.lib" + +!IF "$(CFG)" == "Win64 Release" +OUTDIR=.\Release64 +INTDIR=.\Release64 +CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "NDEBUG" +!ELSEIF "$(CFG)" == "Win32 Release" +OUTDIR=.\Release +INTDIR=.\Release +CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "NDEBUG" +!ELSEIF "$(CFG)" == "Win64 Debug" +OUTDIR=Debug64 +INTDIR=$(OUTDIR) +CPP_PROJ=/nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "_DEBUG" +!ELSEIF "$(CFG)" == "Win32 Debug" +OUTDIR=.\Debug +INTDIR=$(OUTDIR) +CPP_PROJ=/nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "_DEBUG" +!ELSEIF "$(CFG)" == "Win64 UNICODE Release" +OUTDIR=.\Release64-UNICODE +INTDIR=.\Release64-UNICODE +CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "NDEBUG" +!ELSEIF "$(CFG)" == "Win32 UNICODE Release" +OUTDIR=.\Release-UNICODE +INTDIR=.\Release-UNICODE +CPP_PROJ=/nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:no +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "NDEBUG" +!ELSEIF "$(CFG)" == "Win64 UNICODE Debug" +OUTDIR=Debug64-UNICODE +INTDIR=$(OUTDIR) +CPP_PROJ=/nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +LINK32_FLAGS= $(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "_DEBUG" +!ELSEIF "$(CFG)" == "Win32 UNICODE Debug" +OUTDIR=.\Debug-UNICODE +INTDIR=$(OUTDIR) +CPP_PROJ=/nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SKYPE_PROTOCOL_EXPORTS" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\Skype_protocol.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +LINK32_FLAGS=$(LINK32_FLAGS) /incremental:yes /debug /pdbtype:sept +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC_PROJ=/l 0xc07 /fo"$(INTDIR)\Skript1.res" /d "_DEBUG" +!ENDIF + +LINK32_OBJS= \ + "$(INTDIR)\contacts.obj" \ + "$(INTDIR)\debug.obj" \ + "$(INTDIR)\gchat.obj" \ + "$(INTDIR)\pthread.obj" \ + "$(INTDIR)\skype.obj" \ + "$(INTDIR)\skypeapi.obj" \ + "$(INTDIR)\skypeopt.obj" \ + "$(INTDIR)\skypeprofile.obj" \ + "$(INTDIR)\skypesvc.obj" \ + "$(INTDIR)\utf8.obj" \ + "$(INTDIR)\voiceservice.obj" \ + "$(INTDIR)\msglist.obj" \ + "$(INTDIR)\memlist.obj" \ + "$(INTDIR)\util.obj" \ + "$(INTDIR)\msgq.obj" \ + "$(INTDIR)\alogon.obj" \ + "$(INTDIR)\Skript1.res" + +ALL : "$(OUTDIR)\skype.dll" + + +CLEAN : + -@erase "$(INTDIR)\contacts.obj" + -@erase "$(INTDIR)\debug.obj" + -@erase "$(INTDIR)\gchat.obj" + -@erase "$(INTDIR)\pthread.obj" + -@erase "$(INTDIR)\Skript1.res" + -@erase "$(INTDIR)\skype.obj" + -@erase "$(INTDIR)\skypeapi.obj" + -@erase "$(INTDIR)\skypeopt.obj" + -@erase "$(INTDIR)\skypeprofile.obj" + -@erase "$(INTDIR)\skypesvc.obj" + -@erase "$(INTDIR)\msglist.obj" + -@erase "$(INTDIR)\memlist.obj" + -@erase "$(INTDIR)\util.obj" + -@erase "$(INTDIR)\msgq.obj" \ + -@erase "$(INTDIR)\alogon.obj" \ + -@erase "$(INTDIR)\utf8.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\voiceservice.obj" + -@erase "$(INTDIR)\skype.exp" + -@erase "$(INTDIR)\skype.pdb" + -@erase "$(INTDIR)\skype.lib" + -@erase "$(OUTDIR)\skype.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +"$(OUTDIR)\skype.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("Skype_protocol.dep") +!INCLUDE "Skype_protocol.dep" +!ELSE +!MESSAGE Warning: cannot find "Skype_protocol.dep" +!ENDIF +!ENDIF + + +SOURCE=.\alogon.c + +"$(INTDIR)\alogon.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\contacts.c + +"$(INTDIR)\contacts.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\debug.c + +"$(INTDIR)\debug.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\gchat.c + +"$(INTDIR)\gchat.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\msgq.c + +"$(INTDIR)\msgq.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\pthread.c + +"$(INTDIR)\pthread.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\skype.c + +"$(INTDIR)\skype.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\skypeapi.c + +"$(INTDIR)\skypeapi.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\skypeopt.c + +"$(INTDIR)\skypeopt.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\skypeprofile.c + +"$(INTDIR)\skypeprofile.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\skypesvc.c + +"$(INTDIR)\skypesvc.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\utf8.c + +"$(INTDIR)\utf8.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\voiceservice.c + +"$(INTDIR)\voiceservice.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\Skript1.rc + +"$(INTDIR)\Skript1.res" : $(SOURCE) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + diff --git a/protocols/Skype/Skype_protocol.sln b/protocols/Skype/Skype_protocol.sln new file mode 100644 index 0000000000..0ea2547268 --- /dev/null +++ b/protocols/Skype/Skype_protocol.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Skype_protocol", "Skype_protocol.vcproj", "{5F9243AE-C6C9-4F42-B670-67A97767A50B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + ANSI Debug|Win32 = ANSI Debug|Win32 + ANSI Debug|x64 = ANSI Debug|x64 + ANSI Release|Win32 = ANSI Release|Win32 + ANSI Release|x64 = ANSI Release|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + x64 Debug|Win32 = x64 Debug|Win32 + x64 Debug|x64 = x64 Debug|x64 + x64 Release|Win32 = x64 Release|Win32 + x64 Release|x64 = x64 Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Debug|Win32.ActiveCfg = ANSI Debug|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Debug|Win32.Build.0 = ANSI Debug|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Debug|x64.ActiveCfg = ANSI Debug|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Release|Win32.ActiveCfg = ANSI Release|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Release|Win32.Build.0 = ANSI Release|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.ANSI Release|x64.ActiveCfg = ANSI Release|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Debug|Win32.Build.0 = Debug|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Debug|x64.ActiveCfg = Debug|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Release|Win32.ActiveCfg = Release|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Release|Win32.Build.0 = Release|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.Release|x64.ActiveCfg = Release|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Debug|Win32.ActiveCfg = x64 Debug|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Debug|x64.ActiveCfg = x64 Debug|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Debug|x64.Build.0 = x64 Debug|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Release|Win32.ActiveCfg = x64 Release|Win32 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Release|x64.ActiveCfg = x64 Release|x64 + {5F9243AE-C6C9-4F42-B670-67A97767A50B}.x64 Release|x64.Build.0 = x64 Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/protocols/Skype/Skype_protocol.vcproj b/protocols/Skype/Skype_protocol.vcproj new file mode 100644 index 0000000000..74e7e4bac0 --- /dev/null +++ b/protocols/Skype/Skype_protocol.vcproj @@ -0,0 +1,2843 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/protocols/Skype/alogon.c b/protocols/Skype/alogon.c new file mode 100644 index 0000000000..90c3510944 --- /dev/null +++ b/protocols/Skype/alogon.c @@ -0,0 +1,129 @@ +#include "skype.h" +#include "debug.h" + +extern char g_szProtoName[]; +extern HANDLE SkypeReady; + +/** + * Purpose: Retrieves class name from window + * + * Note: This is some sort of hack to return static local variable, + * but it works :) + */ +static const TCHAR* getClassName(HWND wnd) +{ + static TCHAR className[256]; + + *className=0; + GetClassName(wnd, &className[0], sizeof(className)/sizeof(className[0])); + return className; +} + +/** + * Purpose: Finds a window + * + * Note: This function relies on Skype window placement. + * It should work for Skype 3.x + */ +static HWND findWindow(HWND parent, const TCHAR* childClassName) +{ + // Get child window + // This window is not combo box or edit box + HWND wnd = GetWindow(parent, GW_CHILD); + while(wnd != NULL && _tcscmp(getClassName(wnd), childClassName) != 0) + wnd = GetWindow(wnd, GW_HWNDNEXT); + + return wnd; +} + +static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) +{ + DWORD dwPID; + const TCHAR *lpszClassName; + + + GetWindowThreadProcessId(hWnd,&dwPID); + if (lParam != 0 && dwPID != (DWORD)lParam) return TRUE; + lpszClassName = getClassName(hWnd); + if(_tcscmp(lpszClassName, _T("tSkMainForm.UnicodeClass")) == 0 || + _tcscmp(lpszClassName, _T("TLoginForm.UnicodeClass")) == 0) + { + HWND loginControl = GetWindow(hWnd, GW_CHILD); + + LOG(("setUserNamePasswordThread: Skype window found!")); + + // Sleep for some time, while Skype is loading + // It loads slowly :( + //Sleep(5000); + LOG (("TLoginControl = %S", getClassName(loginControl))); + + // Check for login control + if(_tcscmp(getClassName(loginControl), _T("TLoginControl")) == 0) + { + // Find user name window + HWND userName = findWindow(loginControl, _T("TNavigableTntComboBox.UnicodeClass")); + HWND password = findWindow(loginControl, _T("TNavigableTntEdit.UnicodeClass")); + + LOG (("userName=%08X; password=%08X", userName, password)); + if (userName && password) + { + // Set user name and password + DBVARIANT dbv; + + if(!DBGetContactSettingWString(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) + { + SendMessageW(userName, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); + DBFreeVariant(&dbv); + } + + if(!DBGetContactSettingWString(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) + { + SendMessageW(password, WM_SETTEXT, 0, (LPARAM)dbv.pwszVal); + DBFreeVariant(&dbv); + SendMessageW(password, WM_CHAR, 13, 0); + } + + + SendMessageW(hWnd, + WM_COMMAND, + 0x4a8, // sign-in button; WARNING: This ID can change during newer Skype versions + (LPARAM)findWindow(loginControl, _T("TTntButton.UnicodeClass"))); + } + return FALSE; + } + + } + return TRUE; +} + +DWORD WINAPI setUserNamePasswordThread(LPVOID lpDummy) +{ + DWORD dwPid = (DWORD)lpDummy; + HANDLE mutex = CreateMutex(NULL, TRUE, _T("setUserNamePasswordMutex")); + + // Check double entrance + if(GetLastError() == ERROR_ALREADY_EXISTS) + return 0; + + WaitForSingleObject(SkypeReady, 5000); + EnumWindows (EnumWindowsProc, dwPid); + + ReleaseMutex(mutex); + CloseHandle(mutex); + return 0; +} + +/** + * Purpose: Finds Skype window and sets user name and password. + * + * Note: This function relies on Skype window placement. + * It should work for Skype 3.x + */ +void setUserNamePassword(int dwPid) +{ + DWORD threadId; + CreateThread(NULL, 0, &setUserNamePasswordThread, (LPVOID)dwPid, 0, &threadId); + + // Give time to thread + Sleep(100); +} diff --git a/protocols/Skype/alogon.h b/protocols/Skype/alogon.h new file mode 100644 index 0000000000..00d2e7e703 --- /dev/null +++ b/protocols/Skype/alogon.h @@ -0,0 +1 @@ +void setUserNamePassword(int dwPid); diff --git a/protocols/Skype/changelog.txt b/protocols/Skype/changelog.txt new file mode 100644 index 0000000000..60526b1116 --- /dev/null +++ b/protocols/Skype/changelog.txt @@ -0,0 +1,330 @@ +NOTES +----- + + You have to manually disable popup of messages in SKYPE, as there is + currently no function in the API to do this + Got to File/Options/Instant messages and disable the checkboxes there + + +CODE +---- + Currently a real mess. At least I splitted it up a bit now. + But hey, it kinda works... ;) + +HISTORY +------- + +0.0.0.45 - ! "NA" and "Free for chat" status are available again; NA is supported by skype and Free for chat + uses skypes "Skype Me" status; better leave it that way + ! changes to the mood message of a contact were only visible after a status change + ! plugin was crashing when status changed to offline and a proxy is used + +0.0.0.44 - ! menu item "Hang up (Skype)" was show on none skype contacts + ! fixed serveral bugs in skype startup (including starting skype twice) + ! show connecting state correctly + ! hangup while ringing caused a state where contact isnt callable anymore + * removed "NA" and "Free for chat" status + +0.0.0.43 - + Added option to suppress summary chat message after call is finished (jls17) + ! Fix hangup causes a dial command if opponent hangs up a little bit earlier (jls17) + ! removed empty chat message on incoming call + ! empty mood message is send to skype correctly + + +0.0.0.42 - + Added a trick to identify skype 3 version (fingerprint) +0.0.0.41 - + Added option to enter user name and password. (Patch by NN) + +0.0.0.40 - + Support for new core service: get avatar caps + + Option to show/hide default avatar for contacts + + Hide Skype Avatar page in user details if >= #27 + +0.0.0.39 - + Voice service support in normall calls - no support for SkypeOut yet (pescuma) + ! Made options dialog a little bit smaller, removed frame and set bold frame for popups (pescuma) + + Add more status to manage for away message + +0.0.0.38 - ! Fix the load for pre 0.7.0 #17 build + * Patch by pescuma for avatar. + +0.0.0.37 - ! Avoid empty message from myself on first message received. + + Add the Get user avatar interface + * Change the get user info thread + * code cleanup + + Support for miranda 0.8 + ! Correct use of folder plugin (using "avatar cache folder"\SKYPE). + +0.0.0.36 - ! When settings skype offline, first set proto off then contacts. + * move the broadcast of status change out of if statement in status change. + * Set contacts ofline on plugin load (avoid skype contact to be online if starts skype is not checked) + ! Fix the use of datapath for portable skype + * Allow to choose no splash - no tray - minimized even if start skype with miranda is not checked. + ! Fix bug with timestamp in irc + +0.0.0.35 - * Use unicode nick, status message, city and country in skype profile. + ! Fix for sending status change when offline + * Do not send message to skype if not attached (avoid trying to connect to api at startup) + ! Fix crash on recieving message with groupchat checked. + +0.0.0.34 - + Try to identify if chat message comes from a group chat or not + + Add a option to flag group chat message as read if not using chat.dll for group chat. + ! Fix the check of message type (group chat or normal) + +0.0.0.33 - ! Fix for flags of event and metacontact (thanks SJE) + * Next step to custom popup support (in popup option page) + ! Fix infinite for error popup + +0.0.0.32 - ! Improvemnt of the Action message support. + ! Fix empty message on first chat with a contact. + +0.0.0.31 - + First step to Action Message support ( /me ) + + Updater support for File Listing. + + First step to a custom popup for call notification. + +0.0.0.30 - + Add an option to enable/disable the timezone patch + +0.0.0.29 - ! Try to fix the bug (set skype offline when closing miranda) + +0.0.0.28 - * Improved portable skype integration + +0.0.0.27 - * Try to fix the start using custom command line + + Close skype using custom command line too + +0.0.0.26 - + Add a way to use a custom command line to start skype. + +0.0.0.25 - ! patch from markcs about timezones. + ! shutdown patch by sje + +0.0.0.24 - * Change options dialog (use tabsrmm uxtheme) + +0.0.0.23 - ! Wrong db entry name for cellular (cellucar) + + Set mirver using is video capabale to identify skype 2.0 user + +0.0.0.22 - * Options page redesigned + * Work around to force refresh of avatar in MyDetail (w8 the avatar change service) + * Change Skype protocol to Skype in options->Network + * Free buffer in status message retrieve + * First step to a details info page. + +0.0.0.21 - * Some minor bugfixes + * Severe bugfix: Message sending routine worked incorrectly (no errors were shown + even if there were sending-errors) + * Removed PingPong - thread in favour of WM_TIMER + * Fixed critical section unlocking in skypeapi.c. In certain cases, critical sections + were not left correctly. + * Fixed a bug that caused Miranda to crash on exit with Newstatusnotify plugin + (thanks to TioDuke for reporting) + * Hopefully fixed the nasty bug that caused Miranda to lockup on exit. + +0.0.0.20 - * Split service and options in two new cpp file. + * Put the default attemps number to 10 + +0.0.0.19 - * Add avatar support for own user only (no api to ge contacts avatar) + * Add set status message. + * Add Get status message for contact where viewing contact details + * Change icons (thanks to Faith Healer) + * Updater support (BETA ONLY) + * DBeEditor known module support + * Mods to avoid warning in VC++ 8 + * Implement the MyDetail requested services + +0.0.0.18 - * HOTFIX - Double File-Transfer icon removed. Please note that you can't send files + via drag & drop, because of the nature of Skype API - Skype wants to open its own + "File/Open" dialog, so I cannot supply a path to the file to be sent, therefore I + had to add a seperate File-sending function rather than using Miranda's function. + +0.0.0.17 - * Startup of Skype in a seperate thread was not solved properly. Now it should really + start in background + * The hack for the statusmode-bug is optional in the settings and is turned off + per default. (Thx to Eddie Hung for reporting problems and help) + * Added an ugly hack for the Skype-API offline bug (grr.. ) + * Nickname is now set correctly. To cleanup the existing Nicks, please go to + the options page an push the "Cleanup Nicknames" button. + This will clean out entries where the Nick was set to the Skype handle + * Fixed a bug in the message sending routine that caused errors in communication + (missed messages in Skype that were not fetched..) + * Added "Hold call" feature while calling + * Added support for conference calls (if a second user is calling while you + are in a conversation, you can now choose whether to block the call or let + the user join you in a conference with the existing caller or to put the + other caller on hold) + * Fixed a bug in the code for adding users that were just searched via the + Skype search-window but never have been in contact list. + * Fixed some bugs (memleak, nick error, ..) in the Search-Routine for + Skype-contacts. (thx to Deadman for reporting) + * Fixed a bug with unknown SKYPE_IN contacts + * Added file-sending capability (requires new Skype-version) + * Did a litte code-cleanup + * Adding / Removing contacts can now be done via the Miranda standard-dialogs if + you use the newest Skype-Version + * With the new Skype-version you are able to handle Authorisation-Requests via Miranda + now. + +0.0.0.16 - * Fixed a severe memory-allocation bug in utf8-encoded messages that caused random + crashes (oops :-O) - Thanks to Ary Dvoretz for reporting. + * Bug in SkypeStatusMode-Bug fix from last release fixed (protocol stayed offline) + * Now onlinestatus for SkypeOut-Contacts is configurable + * Made Menu-Options translatable + * Added support for calling SkypeOut-Phonenumbers. You can now dial a PSTN-Number + by calling "Do a SkypeOut call" in the main menu (or top toolbar if the + toptoolbar plugin is installed) and entering a number or + by right-clicking on a non-Skype contact and selecting "Call using SkypeOut", + if there is a phone-Number entry in the User's-Details. + This, of course, is only working if you have SkypeOut privilege + +0.0.0.15 - * Fixed a crash on Miranda-exit when error occured on Skype-Protocol start + * Fixed Bug #0000006: Now user is asked if he wants to enable the Protocol + for the current profile, if he starts with a new profile. + * Fixed Bug #0000002: Now interfacing with Skype is really stopped on going + offline if the option is enabled. (PingPong-thread killed) + - This also applies on closing Skype + * Fixed a memory leak in MsgFetchThread that appeared in the last version because + of the groupchat-implementation (free() within wrong if clause, ooops ;) + * Fixed Bug #0000005: When there is a msg from a user that is not on Skype's contact + list, the user is now added PALF_TEMPORARY and disappears again on next Miranda-start + * Implemented a fix for Skype API's statusmode bug reported by Markus Mützel: + If you change the online status while Skype is still connecting, Skype changes to + the FIRST state that it was requested to change to, after going online, instead of + the LAST state. However the bug was not reproducable for me. + * Fixed broken popup-support (I hope) + * CHANGE of behaviour (inspired by Bug #0000007): + If you turn off "Start Skype with Miranda", the plugin wouldn't search for a + running Skype instance anymore. + * Now when going online and Skype is not launched, Skype will be launched via a + seperate thread (in background) so that Miranda isn't blocked while Skype is loading + * Options Dlg. should now be translateable too. + +0.0.0.14 - + * Miranda crash on exit if Skype was not found installed should be + fixed by now. + * Implemented compatibility layer for Skype API Protocol V3 and above. + * Removed some useless code introduced in 0.0.0.12 + * Added some fixes made by TioDuke (thank you!) + - Using your own Nick instead of your Skype-Handle in conversations + - LastName 3rd token & above are not ignored any more + - Status modes "On the phone" and "out to lunch" are mapped now + * Fixed a bug that caused "Skype API not available" messages under high load. + (thanks to Romeo28 for testing!) + * Fixed a bug that caused Message sending thread to wait forever if sending + a message times out (causing dead threads) + * Skype contact list should be synced now when Skype-Status changes. + (thx to Markus Mützel for Bugreport) + * Implemented a garbage collector that removes old messages from queue + in order to prevent possible memory exhaustion + * Added option to disable all modal Error-message dialog boxes (as people + keep telling me that they are annoyed by them) + * Added langpack support for error messages + * Added option to increase the time the protocol is waiting for Skype + * Added groupchat functions. WARNING: For testing purposes only! + Currently there is a memleak which I cannot find, but even worse, + Skype API doesn't seem to support sending to a groupchat, inviting etc. + So this is currently only experimental! When you send to a groupchat you + currently send single messages to every user seperately. Skype staff + didn't answer my question about sending to groupchats so far, so it + depends on them when this feature will be available for real use. + +0.0.0.13 - A few minor fixes: + * Logging off users shouldn't flood the StatusNotify-Plugin now. + * Popup-plugin can be enabled/disabled in the options dlg. + * Implemented support for SkypeOut contacts (they caused crashes) + * Now using Nick instead of Skype-Handle as Contact list name on + adding new users, if it is available. + +0.0.0.12 - Bugfixing because of strange Skype API behaviour: + * Adding of contacts that are just searched, but not added in Skype + should be prevented now. + * Version number correct again. + +0.0.0.11 - Only minor bugfixes: + * The gender in user-details is now saved correctly to the DB + (thanks to LeON for the hint!) + * The Apply-Button should now be disabled in the options DLG by default + (thanks to sje for the bug report) + * Contactlist should be reinitialized after a SYNC-Problem now. + * Bug with usernames that contain commas should be fixed + * Protocol messages are now shown as popups if Popup-plugin is installed + +0.0.0.10 - * Hopefully recovery after sync problem works a bit better now + (Sync-Problem Messages are no longer shown) + * Now you can hang up a call directly from a contact's context menu + * Now implemented support for using Skype over a network. You can use + the included skypeproxy service to in/output Skype API messages + on a socket and can connect to it with the plugin. + So you can, for example, launch the skypeproxy service on your + Windows-server (eeek! :P) and control Skype from your workstation + using Miranda. (requested feature by foosmate) + * Now you can accept incoming calls via Miranda (or hang them up) + * The status mode bug (clist status menu was not updated properly) + should be fixed by now. + * The logfile in the dbeug-build should now always be written to the + Miranda directory. + +0.0.0.9 - * Fixed bug with error when starting Skype with Miranda ("Wheee...") + * As Skype seems to use new, UNDOCUMENTED Message types (I think it's + a severe Skype-API bug) I adapted the plugin so that it works + with new API now. This fixes the problem of not being able to receive + messages in new Skype versions. + Skype now sends "MESSAGE TYPE SAID" instead of "MESSAGE TYPE TEXT", + the bug has been reported to Skype forum. + (http://forum.skype.com/viewtopic.php?t=15435) + * Fixed a memory leak in Message-receiving routine + * Added UTF8-support for Contact properties (does this fix something?) + * Fixed a memory leak in Startup-routine + * Finally renamed Plugin from SKYPE_PROTOCOL to SKYPE internally. + Hopefully it will upgrade your existing DB seamlessly. + * Now all threads should be sync with Miranda as I'm using the pthread- + functions "borrowed" from Yahoo protocol. + +0.0.0.8 - * Now there is support for the "Occupied" mode, which is mapped to DND + This is useful for users who do a global statusmodechange so that Skype + gets to "Occupied" state instead of staying online. + * Now the protocol doesn't disable itself when you chose to not start + Skype on startup, instead it stays offline and starts Skype when you + try to go online. + +0.0.0.7 - * Fixed a bug that caused a lockup on Plugin startup (when a Window was not + reacting to the HWND_BROADCAST) (thx to Cool Blue) + * Fixed a bug in the Startup-procedure.. + * Now Skype doesn't go offline when you close Miranda (thx to Egodust) + * Now it should really work unter WIN98 (thx to TioDuke for testing) + * Implemented feature for Shutting down Skype on going offline and + restarting Skype on changing to online mode again, as many people requested. + +0.0.0.6 - * Added feature requests from kreisquadratur: + * Option to disable Skype-Menuitems + * Fixed bug with Apply-Button + * Using a nicer Skype-Icon now + * Now using Skype-Timestamp for messages + * Implementing importing history from skype (see contextmenu of contact) + * Fixed bug with processing first message of MESSAGES - List + * Found out, that RegisterClass() doesn't work for UNICODE-Programs on + non-UNICODE win98, therefore return-value check for RegisterClass removed + * Fixed a bug that caused a "We got a Sync problem :(" + +0.0.0.5 - * Fixed a bug that caused the plugin to crash with bigger contact lists + (Skype API was flooded on startup) + +0.0.0.4 - * Missed messages are fetched now + * User details work now + * More verbose error msgs now (to help Win98 user debugging his problem) + * Added option for starting skype with miranda and shutting down + Skype when closing miranda. + * You can now chose the command line options to pass to Skype on startup + * Hopefully the bug with multiple Call - Entries per user is fixed now + * Protocol name is now "Skype", not "Skype_protocol" - Remember this + when updating, so DELETE skype_protocol.dll first!! + * Secured Message Queue with a Mutex + * Fixed a Message-receiving bug that could cause delays in message-processing + * Adding a Contact in Skype now also adds it to Miranda immediately + (Deleting should also work, but doesn't because of a Skype API bug) + * Added searching for contacts, but this feature seems to be quite useless, + as Skype API doesn't support adding contacts, so you still have to add + your contacts in the Skype program, sorry + In order to do this comfortably, I added a Miranda Menu-Item for adding + Skype-contacts. + +0.0.0.3 - * I hope it's thread-safe now + * Changing the Online-Status should work correctly now + * Fixed "We got a sync problem :(" bug - big thx to Azzie + * Now starts Skype more in the background as proposed by Kreisquadratur + * Implemented PING-PONG with Skype to detect if Connection to Skype API + was lost + * Launching of Skype by Miranda improved diff --git a/protocols/Skype/contacts.c b/protocols/Skype/contacts.c new file mode 100644 index 0000000000..c83d3294a1 --- /dev/null +++ b/protocols/Skype/contacts.c @@ -0,0 +1,417 @@ +/* + * Contactlist management functions + */ + +#include "skype.h" +#include "skypeapi.h" +#include "debug.h" +#include "pthread.h" +#include "gchat.h" +#include "voiceservice.h" + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include "../../include/m_langpack.h" +#pragma warning (pop) + +#pragma warning (disable: 4706) // assignment within conditional expression + +// Imported Globals +extern HINSTANCE hInst; +extern BOOL bSkypeOut, bIsImoproxy; +extern char protocol, g_szProtoName[]; + +// Handles +static HANDLE hMenuCallItem, hMenuCallHangup, hMenuSkypeOutCallItem, hMenuHoldCallItem, hMenuFileTransferItem, hMenuChatInitItem; + +// Check if alpha blending icons are supported +// Seems to be not neccessary +/* +BOOL SupportAlphaIcons(void) { + HANDLE hMod; + DLLVERSIONINFO tDVI={0}; + BOOL retval=FALSE; + FARPROC pDllGetVersion; + + if (!(hMod=LoadLibrary("comctl32.dll"))) return FALSE; + if (pDllGetVersion=GetProcAddress(hMod, "DllGetVersion")) { + tDVI.cbSize=sizeof(tDVI); + if (!pDllGetVersion ((DLLVERSIONINFO *)&tDVI)) { + if (GetDeviceCaps(GetDC(NULL), BITSPIXEL)*GetDeviceCaps(GetDC(NULL), PLANES)>=32 && + tDVI.dwMajorVersion>=6) + retval=TRUE; + } + } + FreeLibrary(hMod); + return retval; +} +*/ + +CLISTMENUITEM CallItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.ptszName=LPGENT("Call (Skype)"); + mi.pszService=SKYPE_CALL; + + return mi; +} + +CLISTMENUITEM SkypeOutCallItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_HIDDEN|CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALLSKYPEOUT)); + mi.ptszName=LPGENT("Call using SkypeOut"); + mi.pszService=SKYPEOUT_CALL; + + return mi; +} + +CLISTMENUITEM HupItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_HANGUP)); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.ptszName=LPGENT("Hang up call (Skype)"); + mi.pszService=SKYPE_CALLHANGUP; + + return mi; +} + +CLISTMENUITEM SkypeOutHupItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_HANGUP)); + mi.ptszName=LPGENT("Hang up SkypeOut call"); + mi.pszService=SKYPEOUT_CALL; + return mi; +} + +CLISTMENUITEM HoldCallItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_HIDDEN|CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_HOLD)); + mi.ptszName=LPGENT("Hold call"); + mi.pszService=SKYPE_HOLDCALL; + return mi; +} + +CLISTMENUITEM ResumeCallItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_HIDDEN|CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_RESUME)); + mi.ptszName=LPGENT("Resume call"); + mi.pszService=SKYPE_HOLDCALL; + return mi; +} + +CLISTMENUITEM FileTransferItem(void) { + CLISTMENUITEM mi={0}; + + // Stolen from file.c of Miranda core + mi.cbSize=sizeof(mi); + mi.position=-2000020000; + mi.flags=CMIF_HIDDEN|CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadSkinnedIcon(SKINICON_EVENT_FILE); + mi.ptszName=LPGENT("&File"); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.pszService=SKYPE_SENDFILE; + return mi; +} + +CLISTMENUITEM ChatInitItem(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000020000; + mi.flags=CMIF_HIDDEN|CMIF_NOTOFFLINE|CMIF_TCHAR; + mi.hIcon=LoadIcon( hInst, MAKEINTRESOURCE( IDI_INVITE )); + mi.ptszName=LPGENT("&Open groupchat"); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.pszService=SKYPE_CHATNEW; + return mi; +} + +HANDLE add_contextmenu(HANDLE hContact) { + CLISTMENUITEM mi; + + UNREFERENCED_PARAMETER(hContact); + + if (!HasVoiceService()) { + mi=CallItem(); + hMenuCallItem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); + mi=HupItem(); + hMenuCallHangup=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi); + } + + mi=SkypeOutCallItem(); + hMenuSkypeOutCallItem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); + + if (!HasVoiceService()) { + mi=HoldCallItem(); + hMenuHoldCallItem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); + } + + // We cannot use flag PF1_FILESEND for sending files, as Skype opens its own + // sendfile-Dialog. + mi=FileTransferItem(); + hMenuFileTransferItem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); + + mi=ChatInitItem(); + hMenuChatInitItem=(HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); + + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_IMPORT)); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.ptszName=LPGENT("Import Skype history"); + mi.pszService=SKYPE_IMPORTHISTORY; + return (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0,(LPARAM)&mi); +} + +HANDLE add_mainmenu(void) { + CLISTMENUITEM mi={0}; + + mi.cbSize=sizeof(mi); + mi.position=-2000005000; + mi.flags=CMIF_TCHAR; + mi.hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_ADD)); + mi.pszContactOwner=SKYPE_PROTONAME; + mi.ptszName=LPGENT("Add Skype contact"); + mi.pszService=SKYPE_ADDUSER; + return (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, (WPARAM)NULL,(LPARAM)&mi); + +} + +int __cdecl PrebuildContactMenu(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + CLISTMENUITEM mi; + char *szProto; + BOOL callAvailable = FALSE; + BOOL hangupAvailable = FALSE; + + UNREFERENCED_PARAMETER(lParam); + + if (!(szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0))) return 0; + + if (!HasVoiceService()) { + // Clear hold-Item in case it exists + mi=HoldCallItem(); + mi.flags|=CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem,(LPARAM)&mi); + } + + if (!strcmp(szProto, SKYPE_PROTONAME)) { + if (!HasVoiceService()) { + if (!DBGetContactSetting((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + if (DBGetContactSettingByte((HANDLE)wParam, SKYPE_PROTONAME, "OnHold", 0)) + mi=ResumeCallItem(); else mi=HoldCallItem(); + mi.flags=CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuHoldCallItem,(LPARAM)&mi); + + callAvailable = FALSE; + hangupAvailable = TRUE; + + DBFreeVariant(&dbv); + } else { callAvailable = TRUE; hangupAvailable = FALSE; } + + if (DBGetContactSettingByte((HANDLE)wParam, SKYPE_PROTONAME, "ChatRoom", 0)!=0) { + callAvailable = FALSE; + hangupAvailable = FALSE; + } + + mi = CallItem(); + mi.flags |= CMIM_ALL | (!callAvailable?CMIF_HIDDEN:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallItem,(LPARAM)&mi); + + mi = HupItem(); + mi.flags |= CMIM_ALL | (!hangupAvailable?CMIF_HIDDEN:0); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuCallHangup,(LPARAM)&mi); + } + + // Clear SkypeOut menu in case it exists + mi=SkypeOutCallItem(); + mi.flags|=CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem,(LPARAM)&mi); + + // File sending and groupchat-creation works starting with protocol version 5 + if (protocol>=5) { + mi=FileTransferItem(); + if (DBGetContactSettingByte((HANDLE)wParam, SKYPE_PROTONAME, "ChatRoom", 0)==0) + mi.flags ^= CMIF_HIDDEN; + mi.flags |= CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuFileTransferItem,(LPARAM)&mi); + + mi=ChatInitItem(); + if (DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseGroupchat", 0) && + DBGetContactSettingByte((HANDLE)wParam, SKYPE_PROTONAME, "ChatRoom", 0)==0) + mi.flags ^= CMIF_HIDDEN; + mi.flags |= CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuChatInitItem,(LPARAM)&mi); + } + + } else if (bSkypeOut) { + if (!DBGetContactSetting((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + mi=SkypeOutHupItem(); + DBFreeVariant(&dbv); + } else { + mi=SkypeOutCallItem(); + if(!DBGetContactSetting((HANDLE)wParam,"UserInfo","MyPhone0",&dbv)) { + DBFreeVariant(&dbv); + mi.flags=0; + } + } + mi.flags|=CMIM_ALL; + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)(HANDLE)hMenuSkypeOutCallItem,(LPARAM)&mi); + } + + return 0; +} + +/* +int ClistDblClick(WPARAM wParam, LPARAM lParam) { + char *szProto; + + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, wParam, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && + DBGetContactSettingWord((HANDLE)wParam, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)==ID_STATUS_ONTHEPHONE) { + SkypeCall(wParam, 0); + } + + return 0; +} +*/ + +HANDLE find_contact(char *name) { + char *szProto; + int tCompareResult; + HANDLE hContact; + DBVARIANT dbv; + + // already on list? + for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);hContact != NULL;hContact=(HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==0) + { + if (DBGetContactSettingString(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; + tCompareResult = strcmp(dbv.pszVal, name); + DBFreeVariant(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} +HANDLE find_contactT(TCHAR *name) { + char *szProto; + int tCompareResult; + HANDLE hContact; + DBVARIANT dbv; + + // already on list? + for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);hContact != NULL;hContact=(HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==0) + { + if (DBGetContactSettingTString(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) continue; + tCompareResult = _tcscmp(dbv.ptszVal, name); + DBFreeVariant(&dbv); + if (tCompareResult) continue; + return hContact; // already there, return handle + } + } + return NULL; +} + + +HANDLE add_contact(char *name, DWORD flags) { + HANDLE hContact; + + // already on list? + if (hContact=find_contact(name)) { + if (!(flags & PALF_TEMPORARY) && DBGetContactSettingByte(hContact, "CList", "NotOnList", 1)) { + DBDeleteContactSetting( hContact, "CList", "NotOnList" ); + DBDeleteContactSetting( hContact, "CList", "Hidden" ); + } + LOG(("add_contact: Found %s", name)); + return hContact; // already there, return handle + } + // no, so add + + LOG(("add_contact: Adding %s", name)); + hContact=(HANDLE)CallServiceSync(MS_DB_CONTACT_ADD, 0, 0); + if (hContact) { + if (CallServiceSync(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact,(LPARAM)SKYPE_PROTONAME)!=0) { + LOG(("add_contact: Ouch! MS_PROTO_ADDTOCONTACT failed for some reason")); + CallServiceSync(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + return NULL; + } + if (name[0]) DBWriteContactSettingString(hContact, SKYPE_PROTONAME, SKYPE_NAME, name); + + if (flags & PALF_TEMPORARY ) { + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1); + } + if (name[0]) { + SkypeSend("GET USER %s DISPLAYNAME", name); + } else {LOG(("add_contact: Info: The contact added has no name."));} + } else {LOG(("add_contact: Ouch! MS_DB_CONTACT_ADD failed for some reason"));} + LOG(("add_contact succeeded")); + return hContact; +} + +void logoff_contacts(BOOL bCleanup) { + HANDLE hContact; + char *szProto; + DBVARIANT dbv={0}; + + LOG(("logoff_contacts: Logging off contacts.")); + for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);hContact != NULL;hContact=(HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME)) + { + if (DBGetContactSettingWord(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) + DBWriteContactSettingWord(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE); + + DBDeleteContactSetting(hContact, SKYPE_PROTONAME, "CallId"); + if (DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0)==1) + { + if (DBGetContactSettingTString(hContact, SKYPE_PROTONAME, "ChatRoomID", &dbv)) continue; + RemChat (dbv.ptszVal); + DBFreeVariant(&dbv); + } + if (DBGetContactSettingString(hContact, SKYPE_PROTONAME, "Typing_Stream", &dbv) == 0) + { + if (bCleanup) SkypeSend ("ALTER APPLICATION libpurple_typing DISCONNECT %s", dbv.pszVal); + DBFreeVariant(&dbv); + DBDeleteContactSetting(hContact, SKYPE_PROTONAME, "Typing_Stream"); + } + + } + } + if (bCleanup && (protocol>=5 || bIsImoproxy)) SkypeSend ("DELETE APPLICATION libpurple_typing"); +} diff --git a/protocols/Skype/contacts.h b/protocols/Skype/contacts.h new file mode 100644 index 0000000000..35a400c3e9 --- /dev/null +++ b/protocols/Skype/contacts.h @@ -0,0 +1,11 @@ +// Prototypes +HANDLE add_contextmenu(HANDLE hContact); +HANDLE find_contact(char *name); +HANDLE find_contactT(TCHAR *name); +HANDLE add_contact(char *name, DWORD flags); +HANDLE add_mainmenu(void); +CLISTMENUITEM HupItem(void); +CLISTMENUITEM CallItem(void); +void logoff_contacts(BOOL bCleanup); +int PrebuildContactMenu(WPARAM, LPARAM); +//int ClistDblClick(WPARAM, LPARAM); \ No newline at end of file diff --git a/protocols/Skype/debug.c b/protocols/Skype/debug.c new file mode 100644 index 0000000000..a1267d8d8a --- /dev/null +++ b/protocols/Skype/debug.c @@ -0,0 +1,75 @@ +#ifndef _DEBUG +#pragma warning (disable: 4206) // nonstandard extension used : translation unit is empty +#else +#include "debug.h" + +#define WIN32_LEAN_AND_MEAN +//#include +#include +//#include +#include "skype.h" +#include +#include + +#define INITBUF 1024 /* Initial size of buffer */ + +#pragma warning (disable: 4706) // assignment within conditional expression + +extern char g_szProtoName[]; + +static CRITICAL_SECTION m_WriteFileMutex; +static FILE *m_fpLogFile = INVALID_HANDLE_VALUE; +static char *m_szLogBuf = NULL; +static DWORD m_iBufSize = 0; + +void init_debug(void) { + char *p; + char logfile[MAX_PATH]; + + ZeroMemory(logfile, sizeof(logfile)); + p=logfile+GetModuleFileNameA(NULL, logfile, sizeof(logfile)); + if (!(p=strrchr (logfile, '\\'))) p=logfile; else p++; + sprintf (p, "%s_log.txt", SKYPE_PROTONAME); + m_szLogBuf = calloc (1, (m_iBufSize = INITBUF)); + m_fpLogFile = fopen(logfile, "a"); + InitializeCriticalSection(&m_WriteFileMutex); +} + +void end_debug (void) { + if (m_szLogBuf) free (m_szLogBuf); + if (m_fpLogFile) fclose (m_fpLogFile); + DeleteCriticalSection(&m_WriteFileMutex); +} + +void do_log(const char *pszFormat, ...) { + char *ct, *pNewBuf; + va_list ap; + time_t lt; + int iLen; + + if (!m_szLogBuf || !m_fpLogFile) return; + EnterCriticalSection(&m_WriteFileMutex); + time(<); + ct=ctime(<); + ct[strlen(ct)-1]=0; + do + { + va_start(ap, pszFormat); + iLen = _vsnprintf(m_szLogBuf, m_iBufSize, pszFormat, ap); + va_end(ap); + if (iLen == -1) + { + if (!(pNewBuf = (char*)realloc (m_szLogBuf, m_iBufSize*2))) + { + iLen = strlen (m_szLogBuf); + break; + } + m_szLogBuf = pNewBuf; + m_iBufSize*=2; + } + } while (iLen == -1); + fprintf (m_fpLogFile, sizeof(time_t) == sizeof(int) ? "%s (%ld) [%08X] %s\n" : "%s (%lld) [%08X] %s\n", ct, lt, GetCurrentThreadId(), m_szLogBuf); + fflush (m_fpLogFile); + LeaveCriticalSection(&m_WriteFileMutex); +} +#endif \ No newline at end of file diff --git a/protocols/Skype/debug.h b/protocols/Skype/debug.h new file mode 100644 index 0000000000..9582246251 --- /dev/null +++ b/protocols/Skype/debug.h @@ -0,0 +1,23 @@ +//#define DEBUG_RELEASE 1 + +#ifdef DEBUG_RELEASE + #define _DEBUG 1 +#endif + +#ifdef _DEBUG + void init_debug(void); + void end_debug (void); + void do_log(const char *pszFormat, ...); + #define DEBUG_OUT(a) OUTPUT(a) + #define TRACE(a) OutputDebugString(a) + #define TRACEA(a) OutputDebugStringA(a) + #define TRACEW(a) OutputDebugStringW(a) + #define LOG(a) do_log a +#else + #define DEBUG_OUT(a) + #define LOG(a) + #define TRACE(a) + #define TRACEA(a) + #define TRACEW(a) +#endif + diff --git a/protocols/Skype/deploy.bat b/protocols/Skype/deploy.bat new file mode 100644 index 0000000000..eee9e164d1 --- /dev/null +++ b/protocols/Skype/deploy.bat @@ -0,0 +1,15 @@ +@echo off +set PATH=%PATH%;C:\Programme\WinRAR +echo Deploying.. +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol.zip Release\skype.dll +rem There is no ANSI x64 Build +rem winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_x64.zip Release64\skype.dll +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode.zip Release-UNICODE\skype.dll +winrar a -apPlugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_unicode_x64.zip Release64-UNICODE\skype.dll + +winrar a -apDebug -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.pdb +winrar a -apDebug\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug\skype.dll +winrar a -apDebug64-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.pdb +winrar a -apDebug64-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug64-UNICODE\skype.dll +winrar a -apDebug-UNICODE -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.pdb +winrar a -apDebug-UNICODE\Plugins -ep1 \\linux01\leecher\webserver\Skype\Skype_protocol_debug.zip Debug-UNICODE\skype.dll diff --git a/protocols/Skype/ezxml/ezxml.c b/protocols/Skype/ezxml/ezxml.c new file mode 100644 index 0000000000..24c02fbd70 --- /dev/null +++ b/protocols/Skype/ezxml/ezxml.c @@ -0,0 +1,1033 @@ +/* ezxml.c + * + * Copyright 2004-2006 Aaron Voisine + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if defined(WIN32) || defined(_WIN32) +#include +#ifndef EZXML_NOMMAP +#define EZXML_NOMMAP +#endif +#endif + +#include +#include +#include +#include +#include +#if !defined(WIN32) && !defined(_WIN32) +#include +#endif +#include +#ifndef EZXML_NOMMAP +#include +#endif // EZXML_NOMMAP +#include +#include "ezxml.h" + +#if defined(WIN32) || defined(_WIN32) +#define vsnprintf _vsnprintf +#define snprintf _snprintf +#define open _open +#define read _read +#define write _write +#define close _close +#endif + +#define EZXML_WS "\t\r\n " // whitespace +#define EZXML_ERRL 128 // maximum error string length + +typedef struct ezxml_root *ezxml_root_t; +struct ezxml_root { // additional data for the root tag + struct ezxml xml; // is a super-struct built on top of ezxml struct + ezxml_t cur; // current xml tree insertion point + char *m; // original xml string + size_t len; // length of allocated memory for mmap, -1 for malloc + char *u; // UTF-8 conversion of string if original was UTF-16 + char *s; // start of work area + char *e; // end of work area + char **ent; // general entities (ampersand sequences) + char ***attr; // default attributes + char ***pi; // processing instructions + short standalone; // non-zero if + char err[EZXML_ERRL]; // error string +}; + +char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings + +// returns the first child tag with the given name or NULL if not found +ezxml_t ezxml_child(ezxml_t xml, const char *name) +{ + xml = (xml) ? xml->child : NULL; + while (xml && strcmp(name, xml->name)) xml = xml->sibling; + return xml; +} + +// returns the Nth tag with the same name in the same subsection or NULL if not +// found +ezxml_t ezxml_idx(ezxml_t xml, int idx) +{ + for (; xml && idx; idx--) xml = xml->next; + return xml; +} + +// returns the value of the requested tag attribute or NULL if not found +const char *ezxml_attr(ezxml_t xml, const char *attr) +{ + int i = 0, j = 1; + ezxml_root_t root = (ezxml_root_t)xml; + + if (! xml || ! xml->attr) return NULL; + while (xml->attr[i] && strcmp(attr, xml->attr[i])) i += 2; + if (xml->attr[i]) return xml->attr[i + 1]; // found attribute + + while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag + for (i = 0; root->attr[i] && strcmp(xml->name, root->attr[i][0]); i++); + if (! root->attr[i]) return NULL; // no matching default attributes + while (root->attr[i][j] && strcmp(attr, root->attr[i][j])) j += 3; + return (root->attr[i][j]) ? root->attr[i][j + 1] : NULL; // found default +} + +// same as ezxml_get but takes an already initialized va_list +ezxml_t ezxml_vget(ezxml_t xml, va_list ap) +{ + char *name = va_arg(ap, char *); + int idx = -1; + + if (name && *name) { + idx = va_arg(ap, int); + xml = ezxml_child(xml, name); + } + return (idx < 0) ? xml : ezxml_vget(ezxml_idx(xml, idx), ap); +} + +// Traverses the xml tree to retrieve a specific subtag. Takes a variable +// length list of tag names and indexes. The argument list must be terminated +// by either an index of -1 or an empty string tag name. Example: +// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1); +// This retrieves the title of the 3rd book on the 1st shelf of library. +// Returns NULL if not found. +ezxml_t ezxml_get(ezxml_t xml, ...) +{ + va_list ap; + ezxml_t r; + + va_start(ap, xml); + r = ezxml_vget(xml, ap); + va_end(ap); + return r; +} + +// returns a null terminated array of processing instructions for the given +// target +const char **ezxml_pi(ezxml_t xml, const char *target) +{ + ezxml_root_t root = (ezxml_root_t)xml; + int i = 0; + + if (! root) return (const char **)EZXML_NIL; + while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag + while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target + return (const char **)((root->pi[i]) ? root->pi[i] + 1 : EZXML_NIL); +} + +// set an error string and return root +ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...) +{ + va_list ap; + int line = 1; + char *t, fmt[EZXML_ERRL]; + + for (t = root->s; t < s; t++) if (*t == '\n') line++; + snprintf(fmt, EZXML_ERRL, "[error near line %d]: %s", line, err); + + va_start(ap, err); + vsnprintf(root->err, EZXML_ERRL, fmt, ap); + va_end(ap); + + return &root->xml; +} + +// Recursively decodes entity and character references and normalizes new lines +// ent is a null terminated array of alternating entity names and values. set t +// to '&' for general entity decoding, '%' for parameter entity decoding, 'c' +// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata +// attribute normalization. Returns s, or if the decoded string is longer than +// s, returns a malloced string that must be freed. +char *ezxml_decode(char *s, char **ent, char t) +{ + char *e, *r = s, *m = s; + long b, c, d, l; + + for (; *s; s++) { // normalize line endings + while (*s == '\r') { + *(s++) = '\n'; + if (*s == '\n') memmove(s, (s + 1), strlen(s)); + } + } + + for (s = r; ; ) { + while (*s && *s != '&' && (*s != '%' || t != '%') && !isspace(*s)) s++; + + if (! *s) break; + else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference + if (s[2] == 'x') c = strtol(s + 3, &e, 16); // base 16 + else c = strtol(s + 2, &e, 10); // base 10 + if (! c || *e != ';') { s++; continue; } // not a character ref + + if (c < 0x80) *(s++) = c; // US-ASCII subset + else { // multi-byte UTF-8 sequence + for (b = 0, d = c; d; d /= 2) b++; // number of bits in c + b = (b - 2) / 5; // number of bytes in payload + *(s++) = (0xFF << (7 - b)) | (c >> (6 * b)); // head + while (b) *(s++) = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload + } + + memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';'))); + } + else if ((*s == '&' && (t == '&' || t == ' ' || t == '*')) || + (*s == '%' && t == '%')) { // entity reference + for (b = 0; ent[b] && strncmp(s + 1, ent[b], strlen(ent[b])); + b += 2); // find entity in entity list + + if (ent[b++]) { // found a match + if ((c = strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) { + l = (d = (s - r)) + c + strlen(e); // new length + r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l); + e = strchr((s = r + d), ';'); // fix up pointers + } + + memmove(s + c, e + 1, strlen(e)); // shift rest of string + strncpy(s, ent[b], c); // copy in replacement text + } + else s++; // not a known entity + } + else if ((t == ' ' || t == '*') && isspace(*s)) *(s++) = ' '; + else s++; // no decoding needed + } + + if (t == '*') { // normalize spaces for non-cdata attributes + for (s = r; *s; s++) { + if ((l = strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1); + while (*s && *s != ' ') s++; + } + if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space + } + return r; +} + +// called when parser finds start of new tag +void ezxml_open_tag(ezxml_root_t root, char *name, char **attr) +{ + ezxml_t xml = root->cur; + + if (xml->name) xml = ezxml_add_child(xml, name, strlen(xml->txt)); + else xml->name = name; // first open tag + + xml->attr = attr; + root->cur = xml; // update tag insertion point +} + +// called when parser finds character content between open and closing tag +void ezxml_char_content(ezxml_root_t root, char *s, size_t len, char t) +{ + ezxml_t xml = root->cur; + char *m = s; + size_t l; + + if (! xml || ! xml->name || ! len) return; // sanity check + + s[len] = '\0'; // null terminate text (calling functions anticipate this) + len = strlen(s = ezxml_decode(s, root->ent, t)) + 1; + + if (! *(xml->txt)) xml->txt = s; // initial character content + else { // allocate our own memory and make a copy + xml->txt = (xml->flags & EZXML_TXTM) // allocate some space + ? realloc(xml->txt, (l = strlen(xml->txt)) + len) + : strcpy(malloc((l = strlen(xml->txt)) + len), xml->txt); + strcpy(xml->txt + l, s); // add new char content + if (s != m) free(s); // free s if it was malloced by ezxml_decode() + } + + if (xml->txt != m) ezxml_set_flag(xml, EZXML_TXTM); +} + +// called when parser finds closing tag +ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s) +{ + if (! root->cur || ! root->cur->name || strcmp(name, root->cur->name)) + return ezxml_err(root, s, "unexpected closing tag ", name); + + root->cur = root->cur->parent; + return NULL; +} + +// checks for circular entity references, returns non-zero if no circular +// references are found, zero otherwise +int ezxml_ent_ok(char *name, char *s, char **ent) +{ + int i; + + for (; ; s++) { + while (*s && *s != '&') s++; // find next entity reference + if (! *s) return 1; + if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref. + for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2); + if (ent[i] && ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0; + } +} + +// called when the parser finds a processing instruction +void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len) +{ + int i = 0, j = 1; + char *target = s; + + s[len] = '\0'; // null terminate instruction + if (*(s += strcspn(s, EZXML_WS))) { + *s = '\0'; // null terminate target + s += strspn(s + 1, EZXML_WS) + 1; // skip whitespace after target + } + + if (! strcmp(target, "xml")) { // + if ((s = strstr(s, "standalone")) && ! strncmp(s + strspn(s + 10, + EZXML_WS "='\"") + 10, "yes", 3)) root->standalone = 1; + return; + } + + if (! root->pi[0]) *(root->pi = malloc(sizeof(char **))) = NULL; //first pi + + while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target + if (! root->pi[i]) { // new target + root->pi = realloc(root->pi, sizeof(char **) * (i + 2)); + root->pi[i] = malloc(sizeof(char *) * 3); + root->pi[i][0] = target; + root->pi[i][1] = (char *)(root->pi[i + 1] = NULL); // terminate pi list + root->pi[i][2] = strdup(""); // empty document position list + } + + while (root->pi[i][j]) j++; // find end of instruction list for this target + root->pi[i] = realloc(root->pi[i], sizeof(char *) * (j + 3)); + root->pi[i][j + 2] = realloc(root->pi[i][j + 1], j + 1); + strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<"); + root->pi[i][j + 1] = NULL; // null terminate pi list for this target + root->pi[i][j] = s; // set instruction +} + +// called when the parser finds an internal doctype subset +short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len) +{ + char q, *c, *t, *n = NULL, *v, **ent, **pe; + int i, j; + + pe = memcpy(malloc(sizeof(EZXML_NIL)), EZXML_NIL, sizeof(EZXML_NIL)); + + for (s[len] = '\0'; s; ) { + while (*s && *s != '<' && *s != '%') s++; // find next declaration + + if (! *s) break; + else if (! strncmp(s, "'); + continue; + } + + for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++); + ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent + if (*c == '%') pe = ent; + else root->ent = ent; + + *(++s) = '\0'; // null terminate name + if ((s = strchr(v, q))) *(s++) = '\0'; // null terminate value + ent[i + 1] = ezxml_decode(v, pe, '%'); // set value + ent[i + 2] = NULL; // null terminate entity list + if (! ezxml_ent_ok(n, ent[i + 1], ent)) { // circular reference + if (ent[i + 1] != v) free(ent[i + 1]); + ezxml_err(root, v, "circular entity declaration &%s", n); + break; + } + else ent[i] = n; // set entity name + } + else if (! strncmp(s, "")) == '>') continue; + else *s = '\0'; // null terminate tag name + for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++); + + while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { + if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name + else { ezxml_err(root, t, "malformed ") - 1; + if (*c == ' ') continue; // cdata is default, nothing to do + v = NULL; + } + else if ((*s == '"' || *s == '\'') && // default value + (s = strchr(v = s + 1, *s))) *s = '\0'; + else { ezxml_err(root, t, "malformed attr[i]) { // new tag name + root->attr = (! i) ? malloc(2 * sizeof(char **)) + : realloc(root->attr, + (i + 2) * sizeof(char **)); + root->attr[i] = malloc(2 * sizeof(char *)); + root->attr[i][0] = t; // set tag name + root->attr[i][1] = (char *)(root->attr[i + 1] = NULL); + } + + for (j = 1; root->attr[i][j]; j += 3); // find end of list + root->attr[i] = realloc(root->attr[i], + (j + 4) * sizeof(char *)); + + root->attr[i][j + 3] = NULL; // null terminate list + root->attr[i][j + 2] = c; // is it cdata? + root->attr[i][j + 1] = (v) ? ezxml_decode(v, root->ent, *c) + : NULL; + root->attr[i][j] = n; // attribute name + } + } + else if (! strncmp(s, ""); // comments + else if (! strncmp(s, ""))) + ezxml_proc_inst(root, c, s++ - c); + } + else if (*s == '<') s = strchr(s, '>'); // skip other declarations + else if (*(s++) == '%' && ! root->standalone) break; + } + + free(pe); + return ! *root->err; +} + +// Converts a UTF-16 string to UTF-8. Returns a new string that must be freed +// or NULL if no conversion was needed. +char *ezxml_str2utf8(char **s, size_t *len) +{ + char *u; + size_t l = 0, sl, max = *len; + long c, d; + int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1; + + if (be == -1) return NULL; // not UTF-16 + + u = malloc(max); + for (sl = 2; sl < *len - 1; sl += 2) { + c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) //UTF-16BE + : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); //UTF-16LE + if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { // high-half + d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) + : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); + c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000; + } + + while (l + 6 > max) u = realloc(u, max += EZXML_BUFSIZE); + if (c < 0x80) u[l++] = c; // US-ASCII subset + else { // multi-byte UTF-8 sequence + for (b = 0, d = c; d; d /= 2) b++; // bits in c + b = (b - 2) / 5; // bytes in payload + u[l++] = (0xFF << (7 - b)) | (c >> (6 * b)); // head + while (b) u[l++] = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload + } + } + return *s = realloc(u, *len = l); +} + +// frees a tag attribute list +void ezxml_free_attr(char **attr) { + int i = 0; + char *m; + + if (! attr || attr == EZXML_NIL) return; // nothing to free + while (attr[i]) i += 2; // find end of attribute list + m = attr[i + 1]; // list of which names and values are malloced + for (i = 0; m[i]; i++) { + if (m[i] & EZXML_NAMEM) free(attr[i * 2]); + if (m[i] & EZXML_TXTM) free(attr[(i * 2) + 1]); + } + free(m); + free(attr); +} + +// parse the given xml string and return an ezxml structure +ezxml_t ezxml_parse_str(char *s, size_t len) +{ + ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL); + char q, e, *d, **attr, **a = NULL; // initialize a to avoid compile warning + int l, i, j; + + root->m = s; + if (! len) return ezxml_err(root, NULL, "root tag missing"); + root->u = ezxml_str2utf8(&s, &len); // convert utf-16 to utf-8 + root->e = (root->s = s) + len; // record start and end of work area + + e = s[len - 1]; // save end char + s[len - 1] = '\0'; // turn end char into null terminator + + while (*s && *s != '<') s++; // find first tag + if (! *s) return ezxml_err(root, s, "root tag missing"); + + for (; ; ) { + attr = (char **)EZXML_NIL; + d = ++s; + + if (isalpha(*s) || *s == '_' || *s == ':' || *s < '\0') { // new tag + if (! root->cur) + return ezxml_err(root, d, "markup outside of root element"); + + s += strcspn(s, EZXML_WS "/>"); + while (isspace(*s)) *(s++) = '\0'; // null terminate tag name + + if (*s && *s != '/' && *s != '>') // find tag in default attr list + for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++); + + for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { // new attrib + attr = (l) ? realloc(attr, (l + 4) * sizeof(char *)) + : malloc(4 * sizeof(char *)); // allocate space + attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2) + : malloc(2); // mem for list of maloced vals + strcpy(attr[l + 3] + (l / 2), " "); // value is not malloced + attr[l + 2] = NULL; // null terminate list + attr[l + 1] = ""; // temporary attribute value + attr[l] = s; // set attribute name + + s += strcspn(s, EZXML_WS "=/>"); + if (*s == '=' || isspace(*s)) { + *(s++) = '\0'; // null terminate tag attribute name + q = *(s += strspn(s, EZXML_WS "=")); + if (q == '"' || q == '\'') { // attribute value + attr[l + 1] = ++s; + while (*s && *s != q) s++; + if (*s) *(s++) = '\0'; // null terminate attribute val + else { + ezxml_free_attr(attr); + return ezxml_err(root, d, "missing %c", q); + } + + for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j +=3); + attr[l + 1] = ezxml_decode(attr[l + 1], root->ent, (a + && a[j]) ? *a[j + 2] : ' '); + if (attr[l + 1] < d || attr[l + 1] > s) + attr[l + 3][l / 2] = EZXML_TXTM; // value malloced + } + } + while (isspace(*s)) s++; + } + + if (*s == '/') { // self closing tag + *(s++) = '\0'; + if ((*s && *s != '>') || (! *s && e != '>')) { + if (l) ezxml_free_attr(attr); + return ezxml_err(root, d, "missing >"); + } + ezxml_open_tag(root, d, attr); + ezxml_close_tag(root, d, s); + } + else if ((q = *s) == '>' || (! *s && e == '>')) { // open tag + *s = '\0'; // temporarily null terminate tag name + ezxml_open_tag(root, d, attr); + *s = q; + } + else { + if (l) ezxml_free_attr(attr); + return ezxml_err(root, d, "missing >"); + } + } + else if (*s == '/') { // close tag + s += strcspn(d = s + 1, EZXML_WS ">") + 1; + if (! (q = *s) && e != '>') return ezxml_err(root, d, "missing >"); + *s = '\0'; // temporarily null terminate tag name + if (ezxml_close_tag(root, d, s)) return &root->xml; + if (isspace(*s = q)) s += strspn(s, EZXML_WS); + } + else if (! strncmp(s, "!--", 3)) { // xml comment + if (! (s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) || + (! *s && e != '>')) return ezxml_err(root, d, "unclosed Yes +// 0 --> No +int AnySkypeusers(void) +{ + HANDLE hContact; + DBVARIANT dbv; + int tCompareResult; + + // already on list? + for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + hContact != NULL; + hContact=(HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + // GETCONTACTBASEPROTO doesn't work on not loaded protocol, therefore get + // protocol from DB + if (DBGetContactSettingString(hContact, "Protocol", "p", &dbv)) continue; + tCompareResult = !strcmp(dbv.pszVal, SKYPE_PROTONAME); + DBFreeVariant(&dbv); + if (tCompareResult) return 1; + } + return 0; +} + + +void UpgradeName(char *OldName) +{ + DBCONTACTENUMSETTINGS cns; + DBCONTACTWRITESETTING cws; + DBVARIANT dbv; + HANDLE hContact=NULL; + struct PLUGINDI pdi; + + LOG(("Updating old database settings if there are any...")); + cns.pfnEnumProc=EnumOldPluginName; + cns.lParam=(LPARAM)&pdi; + cns.szModule=OldName; + cns.ofsSettings=0; + + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + + for ( ;; ) { + memset(&pdi,0,sizeof(pdi)); + CallService(MS_DB_CONTACT_ENUMSETTINGS,(WPARAM)hContact,(LPARAM)&cns); + // Upgrade Protocol settings to new string + if (pdi.szSettings) { + int i; + + LOG(("We're currently upgrading...")); + for (i=0;i 0 && !Miranda_Terminated()) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + UnregisterClass (WndClass.lpszClassName, hInst); + LOG (("Messagepump stopped.")); +} + +// DLL Stuff // + +__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirVersion) +{ + mirandaVersion = mirVersion; + + pluginInfo.cbSize = sizeof(PLUGININFO); + return (PLUGININFO*) &pluginInfo; +} + +__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirVersion) +{ + mirandaVersion = mirVersion; + + return &pluginInfo; +} + +static const MUUID interfaces[] = {MUUID_SKYPE_CALL, MIID_LAST}; +__declspec(dllexport) const MUUID * MirandaPluginInterfaces(void) +{ + return interfaces; +} + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + UNREFERENCED_PARAMETER(fdwReason); + UNREFERENCED_PARAMETER(lpvReserved); + + hInst = hinstDLL; + return TRUE; +} + + +int PreShutdown(WPARAM wParam, LPARAM lParam) { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + PostThreadMessage(msgPumpThreadId, WM_QUIT, 0, 0); + return 0; +} + +int __declspec(dllexport) Load(PLUGINLINK *link) +{ + PROTOCOLDESCRIPTOR pd; + DWORD Buffsize; + HKEY MyKey; + BOOL SkypeInstalled; + BOOL UseCustomCommand; + WSADATA wsaData; + char path[MAX_PATH]; + + pluginLink = link; + mir_getMMI( &mmi ); + //mir_getLP(&pluginInfo); + + GetModuleFileNameA( hInst, path, sizeof( path )); + _splitpath (path, NULL, NULL, SKYPE_PROTONAME, NULL); + CharUpperA( SKYPE_PROTONAME ); + + InitializeCriticalSection(&RingAndEndcallMutex); + InitializeCriticalSection(&QueryThreadMutex); + InitializeCriticalSection(&TimeMutex); + + +#ifdef _DEBUG + init_debug(); +#endif + + LOG(("Load: Skype Plugin loading...")); + + // We need to upgrade SKYPE_PROTOCOL internal name to Skype if not already done + if (!DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UpgradeDone", 0)) + UpgradeName("SKYPE_PROTOCOL"); + + // Initialisation of Skype MsgQueue must be done because of Cleanup in end and + // Mutex is also initialized here. + LOG(("SkypeMsgInit initializing Skype MSG-queue")); + if (SkypeMsgInit()==-1) { + OUTPUT(_T("Memory allocation error on startup.")); + return 0; + } + + // On first run on new profile, ask user, if he wants to enable the plugin in + // this profile + // --> Fixing Issue #0000006 from bugtracker. + if (!DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "FirstRun", 0)) { + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "FirstRun", 1); + if (AnySkypeusers()==0) // First run, it seems :) + if (MessageBox(NULL, TranslateT("This seems to be the first time that you're running the Skype protocol plugin. Do you want to enable the protocol for this Miranda-Profile? (If you chose NO, you can always enable it in the plugin options later."), _T("Welcome!"), MB_ICONQUESTION|MB_YESNO)==IDNO) { + char path[MAX_PATH], *filename; + GetModuleFileNameA(hInst, path, sizeof(path)); + if (filename = strrchr(path,'\\')+1) + DBWriteContactSettingByte(NULL,"PluginDisable",filename,1); + return 0; + } + } + + + // Check if Skype is installed + SkypeInstalled=TRUE; + UseCustomCommand = (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + UseSockets = (BOOL)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0); + + if (!UseSockets && !UseCustomCommand) + { + if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey)!=ERROR_SUCCESS) + { + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Skype\\Phone"), 0, KEY_READ, &MyKey)!=ERROR_SUCCESS) + { + SkypeInstalled=FALSE; + } + } + + Buffsize=sizeof(skype_path); + + if (SkypeInstalled==FALSE || RegQueryValueExA(MyKey, "SkypePath", NULL, NULL, (unsigned char *)skype_path, &Buffsize)!=ERROR_SUCCESS) + { + //OUTPUT("Skype was not found installed :( \nMaybe you are using portable skype."); + RegCloseKey(MyKey); + skype_path[0]=0; + //return 0; + } + RegCloseKey(MyKey); + } + WSAStartup(MAKEWORD(2,2), &wsaData); + + // Start Skype connection + if (!(ControlAPIAttach=RegisterWindowMessage(_T("SkypeControlAPIAttach"))) || !(ControlAPIDiscover=RegisterWindowMessage(_T("SkypeControlAPIDiscover")))) + { + OUTPUT(_T("Cannot register Window message.")); + return 0; + } + + SkypeMsgReceived=CreateSemaphore(NULL, 0, MAX_MSGS, NULL); + if (!(SkypeReady=CreateEvent(NULL, TRUE, FALSE, NULL)) || + !(MessagePumpReady=CreateEvent(NULL, FALSE, FALSE, NULL)) || +#ifdef SKYPEBUG_OFFLN + !(GotUserstatus=CreateEvent(NULL, TRUE, FALSE, NULL)) || +#endif + !(hBuddyAdded=CreateEvent(NULL, FALSE, FALSE, NULL)) || + !(FetchMessageEvent=CreateEvent(NULL, FALSE, TRUE, NULL))) { + OUTPUT(_T("Unable to create Mutex!")); + return 0; + } + + /* Register the module */ + ZeroMemory(&pd, sizeof(pd)); + pd.cbSize = sizeof(pd); + pd.szName = SKYPE_PROTONAME; + pd.type = PROTOTYPE_PROTOCOL; + CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); + + VoiceServiceInit(); + + CreateServices(); + HookEvents(); + InitVSApi(); + MsgList_Init(); + + HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown); + + // Startup Message-pump + pthread_create (( pThreadFunc )MsgPump, NULL); + WaitForSingleObject(MessagePumpReady, INFINITE); + return 0; +} + + + +int __declspec( dllexport ) Unload(void) +{ + BOOL UseCustomCommand = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + BOOL Shutdown = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "Shutdown", 0); + + LOG (("Unload started")); + + if ( Shutdown && ((skype_path && skype_path[0]) ||UseCustomCommand) ) { + + if(UseCustomCommand) + { + DBVARIANT dbv; + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) + { + char szAbsolutePath[MAX_PATH]; + + TranslateMirandaRelativePathToAbsolute(dbv.pszVal, szAbsolutePath, FALSE); + _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); + LOG (("Unload Sent /shutdown to %s", szAbsolutePath)); + DBFreeVariant(&dbv); + } + } + else + { + _spawnl(_P_NOWAIT, skype_path, skype_path, "/SHUTDOWN", NULL); + LOG (("Unload Sent /shutdown to %s", skype_path)); + } + + } + SkypeMsgCleanup(); + WSACleanup(); + FreeVSApi(); + UnhookEvents(); + UnhookEvent(hChatEvent); + UnhookEvent (hChatMenu); + UnhookEvent (hEvInitChat); + DestroyHookableEvent(hInitChat); + VoiceServiceExit(); + GCExit(); + MsgList_Exit(); + + CloseHandle(SkypeReady); + CloseHandle(SkypeMsgReceived); +#ifdef SKYPEBUG_OFFLN + CloseHandle(GotUserstatus); +#endif + CloseHandle(MessagePumpReady); + CloseHandle(hBuddyAdded); + CloseHandle(FetchMessageEvent); + + DeleteCriticalSection(&RingAndEndcallMutex); + DeleteCriticalSection(&QueryThreadMutex); + + SkypeRegisterProxy (0, 0); + LOG (("Unload: Shutdown complete")); +#ifdef _DEBUG + end_debug(); +#endif + DeleteCriticalSection(&TimeMutex); + return 0; +} + diff --git a/protocols/Skype/skype.h b/protocols/Skype/skype.h new file mode 100644 index 0000000000..6439a24dc8 --- /dev/null +++ b/protocols/Skype/skype.h @@ -0,0 +1,188 @@ +#pragma once + +#define _CRT_SECURE_NO_DEPRECATE 1 +#define TEXT_LEN 1024 +#define CP_ACP 0 + +#define code_page CP_ACP; +#define MIRANDA_CUSTOM_LP + + +// System includes +#include +#include +#include +#include +#include +#include "resource.h" +#include +#include +#include +#include +#include "util.h" + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter + +// Miranda Includes +#include "../../include/newpluginapi.h" +#include "../../include/m_utils.h" +#include "../../include/m_protosvc.h" +#include "../../include/m_protomod.h" +#include "../../include/m_skin.h" +#include "../../include/m_message.h" +#include "../../include/m_database.h" +#include "../../include/m_clist.h" +#include "../../include/m_system.h" +#include "sdk/m_updater.h" +#include "sdk/m_folders.h" +#include "../../include/m_options.h" +#include "../../include/m_langpack.h" +#include "../../include/m_userinfo.h" +#include "../../include/m_avatars.h" +#include "../../include/m_contacts.h" +#include "../../include/m_popup.h" + +#pragma warning (pop) + +// MyDetails defines + +// wParam=NULL +// lParam=(char *) new nickname - do not free +// return=0 for sucess +#define PS_SETMYNICKNAME "/SetNickname" + +// Optional, default value is 1024 +// wParam=NULL +// lParam=NULL +// return= <=0 for error, >0 the max length of the nick +#define PS_GETMYNICKNAMEMAXLENGTH "/GetMyNicknameMaxLength" + +// wParam=(char *)Buffer to file name +// lParam=(int)Buffer size +// return=0 for sucess +#define PS_GETMYAVATAR "/GetMyAvatar" + +// wParam=0 +// lParam=(const char *)Avatar file name +// return=0 for sucess +#define PS_SETMYAVATAR "/SetMyAvatar" + + +// Program defines +#define SKYPE_NAME "Username" +#define SKYPE_PROTO "PROTOCOL 7" +#define SKYPE_PROTONAME g_szProtoName // Name of our protocol, taken from .DLL name +#define MAX_MSGS 128 // Maximum messages in queue +#define MAX_USERLEN 32 // Maximum length of a username in Skype +#define PING_INTERVAL 10000 // Ping every 10000 msec to see if Skype is still available +#define USEPOPUP 1 // Use the popup-plugin? +#define TIMEOUT_MSGSEND 9000 // Stolen from msgdialog.c +#define MAX_MSG_AGE 30 // Maximum age in seconds before a Message from queue gets trashed +#define SKYPEBUG_OFFLN 1 // Activate fix for the SkypeAPI Offline-Bug + +// Program hooks +typedef struct { + char ChatNew[MAXMODULELABELLENGTH]; + char SetAvatar[MAXMODULELABELLENGTH]; + char SendFile[MAXMODULELABELLENGTH]; + char HoldCall[MAXMODULELABELLENGTH]; + char AnswerCall[MAXMODULELABELLENGTH]; + char ImportHistory[MAXMODULELABELLENGTH]; + char AddUser[MAXMODULELABELLENGTH]; + char SkypeOutCallUser[MAXMODULELABELLENGTH]; + char CallHangupUser[MAXMODULELABELLENGTH]; + char CallUser[MAXMODULELABELLENGTH]; +} SKYPE_SVCNAMES; +#define SKYPE_CALL g_svcNames.CallUser +#define SKYPE_CALLHANGUP g_svcNames.CallHangupUser +#define SKYPEOUT_CALL g_svcNames.SkypeOutCallUser +#define SKYPE_ADDUSER g_svcNames.AddUser +#define SKYPE_IMPORTHISTORY g_svcNames.ImportHistory +#define SKYPE_ANSWERCALL g_svcNames.AnswerCall +#define SKYPE_HOLDCALL g_svcNames.HoldCall +#define SKYPE_SENDFILE g_svcNames.SendFile +#define SKYPE_SETAVATAR g_svcNames.SetAvatar +#define SKYPE_CHATNEW g_svcNames.ChatNew +#define EVENTTYPE_CALL 2000 + +#ifndef __SKYPESVC_C__ +extern SKYPE_SVCNAMES g_svcNames; +#endif + +// Skype API Communication services +#define PSS_SKYPEAPIMSG "/SendSkypeAPIMsg" +#define SKYPE_REGPROXY "/RegisterProxySvc" + +#define MUUID_SKYPE_CALL { 0x245241eb, 0x178c, 0x4b3f, { 0x91, 0xa, 0x4c, 0x4d, 0xf0, 0xa0, 0xc3, 0xb6 } } + + +// Common used code-pieces +#define OUTPUT(a) ShowMessage(IDI_ERRORS, a, 1); +#define OUTPUTA(a) ShowMessageA(IDI_ERRORS, a, 1); + +typedef void ( __cdecl* pThreadFunc )( void* ); + +// Prototypes + +void __cdecl SkypeSystemInit(char *); +void __cdecl MsgPump (char *dummy); +void PingPong(void); +void CheckIfApiIsResponding(char *); +void TellError(DWORD err); +int ShowMessage(int, TCHAR*, int); +#ifdef _UNICODE +int ShowMessageA(int iconID, char *lpzText, int mustShow); +#else +#define ShowMessageA ShowMessage +#endif +void EndCallThread(char *); +void GetInfoThread(HANDLE); +int OnDetailsInit( WPARAM, LPARAM ); +INT_PTR SkypeGetAvatarInfo(WPARAM wParam,LPARAM lParam); +INT_PTR SkypeGetAvatarCaps(WPARAM wParam,LPARAM lParam); +INT_PTR SkypeGetAwayMessage(WPARAM wParam,LPARAM lParam); +int HookContactAdded(WPARAM wParam, LPARAM lParam); +int HookContactDeleted(WPARAM wParam, LPARAM lParam); +INT_PTR ImportHistory(WPARAM wParam, LPARAM lParam); +int CreateTopToolbarButton(WPARAM wParam, LPARAM lParam); +int OnModulesLoaded(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSetStatus(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeGetStatus(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeGetInfo(WPARAM wParam,LPARAM lParam); +INT_PTR SkypeAddToList(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeBasicSearch(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSendMessage(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeRecvMessage(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeUserIsTyping(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSendAuthRequest(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeRecvAuth(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeAuthAllow(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeAuthDeny(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeAddToListByEvent(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeRegisterProxy(WPARAM wParam, LPARAM lParam); +time_t SkypeTime(time_t *timer); +void MessageSendWatchThread(HANDLE hContact); +int OkToExit(WPARAM wParam, LPARAM lParam); +int MirandaExit(WPARAM wParam, LPARAM lParam); +int __stdcall EnterBitmapFileName( char* szDest ); +void CleanupNicknames(char *dummy); +int InitVSApi(); +int FreeVSApi(); +HANDLE GetMetaHandle(DWORD dwId); +void LaunchSkypeAndSetStatusThread(void *newStatus); + +// Write contact setting as UTF-8 for convenience, if possible. Older Miranda IM versions will store it as ANSI +INT_PTR SkypeDBWriteContactSettingUTF8String(HANDLE hContact,const char *szModule,const char *szSetting,const char *val); + +// Structs + +typedef struct { + char *SkypeSetting; + char *MirandaSetting; +} settings_map; + +// Optional includes +#ifdef USEPOPUP + #include "../../include/m_popup.h" +#endif diff --git a/protocols/Skype/skypeapi.c b/protocols/Skype/skypeapi.c new file mode 100644 index 0000000000..2a6eb1b76e --- /dev/null +++ b/protocols/Skype/skypeapi.c @@ -0,0 +1,1699 @@ +/* + * SkypeAPI - All more or less important functions that deal with Skype + */ + +#include "skype.h" +#include "skypeapi.h" +#include "utf8.h" +#include "debug.h" +#include "contacts.h" +#include "skypeproxy.h" +#include "pthread.h" +#include "gchat.h" +#include "alogon.h" +#include "msgq.h" +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include "../../include/m_utils.h" +#include "../../include/m_langpack.h" +#pragma warning (push) +#include "m_toptoolbar.h" + +#pragma warning (disable: 4706) // assignment within conditional expression + +// Imported Globals +extern HWND hSkypeWnd, g_hWnd; +extern BOOL SkypeInitialized, UseSockets, MirandaShuttingDown, bIsImoproxy; +extern int SkypeStatus, receivers; +extern HANDLE SkypeReady, SkypeMsgReceived, httbButton; +extern UINT ControlAPIAttach, ControlAPIDiscover; +extern LONG AttachStatus; +extern HINSTANCE hInst; +extern PLUGININFO pluginInfo; +extern HANDLE hProtocolAvatarsFolder, hHookSkypeApiRcv; +extern char DefaultAvatarsFolder[MAX_PATH+1], *pszProxyCallout, protocol, g_szProtoName[]; + +// -> Skype Message Queue functions // + +static TYP_MSGQ SkypeMsgs, SkypeSendQueue; + +status_map status_codes[] = { + {ID_STATUS_AWAY, "AWAY"}, + {ID_STATUS_NA, "NA"}, + {ID_STATUS_DND, "DND"}, + {ID_STATUS_ONLINE, "ONLINE"}, + {ID_STATUS_FREECHAT, "SKYPEME"}, // Unfortunately Skype API tells us userstatus ONLINE, if we are free for chat + {ID_STATUS_OFFLINE, "OFFLINE"}, + {ID_STATUS_INVISIBLE, "INVISIBLE"}, + {ID_STATUS_CONNECTING, "CONNECTING"}, + {0, NULL} +}; + +//status_map + + +static CRITICAL_SECTION ConnectMutex; +static BOOL rcvThreadRunning=FALSE, isConnecting = FALSE; +static SOCKET ClientSocket=INVALID_SOCKET; +static HANDLE SkypeMsgToSend=NULL; + +static char *m_szSendBuf = NULL; +static DWORD m_iBufSize = 0; + + +static int _ConnectToSkypeAPI(char *path, BOOL bStart); + + +/* SkypeReceivedMessage + * + * Purpose: Hook to be called when a message is received, if some caller is + * using our internal I/O services. + * Params : wParam - Not used + * lParam - COPYDATASTRUCT like in WM_COPYDATA + * Returns: Result from SendMessage + */ +INT_PTR SkypeReceivedAPIMessage(WPARAM wParam, LPARAM lParam) { + return SendMessage(g_hWnd, WM_COPYDATA, (WPARAM)hSkypeWnd, lParam); +} + +/* + * Skype via Socket --> Skype2Socket connection + */ + +void rcvThread(char *dummy) { + unsigned int length; + char *buf; + COPYDATASTRUCT CopyData; + int rcv; + + if (!UseSockets) return; + rcvThreadRunning=TRUE; + for ( ;; ) { + if (ClientSocket==INVALID_SOCKET) { + rcvThreadRunning=FALSE; + return; + } + LOG(("rcvThread Receiving from socket..")); + if ((rcv=recv(ClientSocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || rcv==0) { + rcvThreadRunning=FALSE; + if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} + else {LOG(("rcvThread lost connection, graceful shutdown"));} + return; + } + LOG(("rcvThread Received length, recieving message..")); + buf=(char *)calloc(1, length+1); + if ((rcv = recv(ClientSocket, buf, length, 0))==SOCKET_ERROR || rcv==0) { + rcvThreadRunning=FALSE; + if (rcv==SOCKET_ERROR) {LOG(("rcvThread Socket error"));} + else {LOG(("rcvThread lost connection, graceful shutdown"));} + free(buf); + return; + } + LOG(("Received message: %s", buf)); + + CopyData.dwData=0; + CopyData.lpData=buf; + CopyData.cbData=(DWORD)strlen(buf)+1; + if (!SendMessage(g_hWnd, WM_COPYDATA, (WPARAM)hSkypeWnd, (LPARAM)&CopyData)) + { + LOG(("SendMessage failed: %08X", GetLastError())); + } + free(buf); + } +} + +void sendThread(char *dummy) { + COPYDATASTRUCT CopyData; + LRESULT SendResult; + int oldstatus; + unsigned int length; + char *szMsg; + + while (SkypeMsgToSend) { + if (WaitForSingleObject(SkypeMsgToSend, INFINITE) != WAIT_OBJECT_0) return; + if (!(szMsg = MsgQ_Get(&SkypeSendQueue))) continue; + length=(unsigned int)strlen(szMsg); + + if (UseSockets) { + if (send(ClientSocket, (char *)&length, sizeof(length), 0) != SOCKET_ERROR && + send(ClientSocket, szMsg, length, 0) != SOCKET_ERROR) { + free (szMsg); + continue; + } + SendResult = 0; + } else { + CopyData.dwData=0; + CopyData.lpData=szMsg; + CopyData.cbData=length+1; + + // Internal comm channel + if (pszProxyCallout) { + CallService (pszProxyCallout, 0, (LPARAM)&CopyData); + free(szMsg); + continue; + } + + // If this didn't work, proceed with normal Skype API + if (!hSkypeWnd) + { + LOG(("SkypeSend: DAMN! No Skype window handle! :(")); + } + SendResult=SendMessage(hSkypeWnd, WM_COPYDATA, (WPARAM)g_hWnd, (LPARAM)&CopyData); + LOG(("SkypeSend: SendMessage returned %d", SendResult)); + free(szMsg); + } + if (!SendResult) { + SkypeInitialized=FALSE; + AttachStatus=-1; + ResetEvent(SkypeReady); + if (g_hWnd) KillTimer (g_hWnd, 1); + if (SkypeStatus!=ID_STATUS_OFFLINE) { + // Go offline + logoff_contacts(FALSE); + oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + } + // Reconnect to Skype + ResetEvent(SkypeReady); + pthread_create(LaunchSkypeAndSetStatusThread, (void *)ID_STATUS_ONLINE); + WaitForSingleObject (SkypeReady, 10000); + // SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); + } + } +} + + +/* + * Skype Messagequeue - Implemented as a linked list + */ + +/* SkypeMsgInit + * + * Purpose: Initializes the Skype Message queue and API + * Returns: 0 - Success + * -1 - Memory allocation failure + */ +int SkypeMsgInit(void) { + + MsgQ_Init(&SkypeMsgs); + MsgQ_Init(&SkypeSendQueue); + InitializeCriticalSection(&ConnectMutex); + if (SkypeMsgToSend=CreateSemaphore(NULL, 0, MAX_MSGS, NULL)) { + if (m_szSendBuf = malloc(m_iBufSize=512)) { + if (_beginthread(( pThreadFunc )sendThread, 0, NULL)!=-1) + return 0; + free(m_szSendBuf); + } + CloseHandle (SkypeMsgToSend); + } + return -1; +} + +/* SkypeMsgAdd + * + * Purpose: Add Message to linked list + * Params : msg - Message to add to queue + * Returns: 0 - Success + * -1 - Memory allocation failure + */ +int SkypeMsgAdd(char *msg) { + return MsgQ_Add(&SkypeMsgs, msg)?0:-1; +} + +/* SkypeMsgCleanup + * + * Purpose: Clean up the whole MESSagequeue - free() all + */ +void SkypeMsgCleanup(void) { + int i; + + LOG(("SkypeMsgCleanup Cleaning up message queue..")); + if (receivers>1) + { + LOG (("SkypeMsgCleanup Releasing %d receivers", receivers)); + for (i=0;i %s", szMsg)); + + // Fake PING-PONG, as PING-PONG is not supported by Skype2Socket + if ((UseSockets || bIsImoproxy) && !strcmp(szMsg, "PING")) { + CopyData.dwData=0; + CopyData.lpData="PONG"; + CopyData.cbData=5; + SendMessage(g_hWnd, WM_COPYDATA, (WPARAM)hSkypeWnd, (LPARAM)&CopyData); + return 0; + } + + if (UseSockets && ClientSocket==INVALID_SOCKET) return -1; + if (!MsgQ_Add(&SkypeSendQueue, szMsg) || !ReleaseSemaphore(SkypeMsgToSend, 1, NULL)) + return -1; + return 0; +} + +/* SkypeSend + * + * Purpose: Sends the specified message to the Skype API. + * If it fails, try to reconnect zu the Skype API + * Params: use like sprintf without first param (dest. buffer) + * Returns: 0 - Success + * -1 - Failure + */ +int SkypeSend(char *szFmt, ...) { + char *pNewBuf; + va_list ap; + size_t iLen; + + // 0.0.0.17+ - Build message-String from supplied parameter list + // so the user doesn't have to care about memory allocation any more. + // 0.0.0.47+ - No more restrictions apply to the format string. + // The temporary buffer remains allocated during the session and gets + // dynamically expanded when needed. This makes sense, as this function + // is used very often and therefore it is faster to not allocate + // memory on every send. + if (!m_szSendBuf && !(m_szSendBuf=malloc(m_iBufSize=512))) return -1; + do + { + va_start(ap, szFmt); + iLen = _vsnprintf(m_szSendBuf, m_iBufSize, szFmt, ap); + va_end(ap); + if (iLen == -1) + { + if (!(pNewBuf = (char*)realloc (m_szSendBuf, m_iBufSize*2))) + { + iLen = strlen (m_szSendBuf); + break; + } + m_szSendBuf = pNewBuf; + m_iBufSize*=2; + } + } while (iLen == -1); + + return __sendMsg(m_szSendBuf); +} + +/* SkypeRcvTime + * + * Purpose: Wait, until either the message "what" is received or maxwait-Time has passed + * or there was an error and return it + * Params : what - Wait for this string-part at the beginning of a received string + * If the first character of the string is NULL, the rest after the NULL + * character will be searched in the entire received message-string. + * You can tokenize the string by using NULL characters. + * You HAVE TO end the string with a extra \0, otherwise the tokenizer + * will run amok in memory! + * st - The message timestamp must be newer or equal to st. + * Set to 0, if you do not need this and want the first message of this + * kind in the queue. + * maxwait - Wait this time before returning, if nothing was received, + * can be INFINITE + * Returns: The received message containing "what" or a ERROR-Message or NULL if + * time is up and nothing was received + * Warning: Don't forget to free() return value! + */ +char *SkypeRcvTime(char *what, time_t st, DWORD maxwait) { + char *msg, *token=NULL; + struct MsgQueue *ptr; + int j; + DWORD dwWaitStat; + BOOL bChatMsg = FALSE, bIsChatMsg = FALSE; + + LOG (("SkypeRcv - Requesting answer: %s", what)); + if (what) bChatMsg = strncmp(what, "CHATMESSAGE", 11)==0; + do { + EnterCriticalSection(&SkypeMsgs.cs); + // First, search for the requested message. On second run, also accept an ERROR + for (j=0; j<2; j++) + { + for (ptr=SkypeMsgs.l.tqh_first; ptr; ptr=ptr->l.tqe_next) { + if (what && what[0]==0) { + // Tokenizer syntax active + token=what+1; + while (*token) { + if (!strstr (ptr->message, token)) { + token=NULL; + break; + } + token+=strlen(token)+1; + } + } + + //if (j==1) {LOG(("SkypeRcv compare %s (%lu) -- %s (%lu)", ptr->message, ptr->tReceived, what, st));} + if ((st == 0 || ptr->tReceived >= st) && + (what==NULL || token || (what[0] && !strncmp(ptr->message, what, strlen(what))) || + (bIsChatMsg = (j==1 && bChatMsg && !strncmp(ptr->message, what+4, strlen(what+4)))) || + (j==1 && !strncmp(ptr->message, "ERROR", 5)))) + { + msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); + LOG(("1) InterlockedDecrement ((long *)&receivers); // receivers--; + if (receivers>1) {LOG (("SkypeRcv: %d receivers still waiting", receivers));} + + } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); + InterlockedDecrement ((long *)&receivers); + LOG(("message, what)); + pCurMsg = ptr->message; + bIsError = FALSE; + if (*what && !strncmp(pCurMsg, what, iLenWhat)) { + // Now we received a MESSAGE with an identifier. So this one is definitely for us + // However the status can be SENDING instead of SENT and next message with this number + // isn't using the ID anymore, so we have to save the ID as new identifier for message recognition + pCurMsg+=iLenWhat; + if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) + strncpy (msgid, pCurMsg, pMsg-pCurMsg); + else if (strncmp (pCurMsg, "ERROR", 5) == 0) bIsError = TRUE; + } + + if ((*msgid && strncmp (pCurMsg, msgid, strlen(msgid)) == 0) || + (!*what && ptr->tReceived >= st && + (strncmp(pCurMsg, "MESSAGE", 7) == 0 || strncmp(pCurMsg, "CHATMESSAGE", 11) == 0 ) + ) || bIsError || + (ptr->tReceived >= st && ptr->tReceived <=st+1 && + (bIsError=(strncmp(pCurMsg, "ERROR 26", 8)==0 || strncmp(pCurMsg, "ERROR 43", 8)==0)) + ) ) + { + bProcess = bIsError; + if (!bIsError) { + if ((pMsg = strchr (pCurMsg, ' ')) && (pMsg=strchr (pMsg+1, ' '))) { + pMsg++; + if (strncmp (pMsg, "STATUS ", 7) == 0) { + pMsg+=7; + if (strcmp (pMsg, "SENDING") == 0 && + DBGetContactSettingWord(hContact, SKYPE_PROTONAME, "Status", ID_STATUS_OFFLINE)!=ID_STATUS_OFFLINE) { + // Remove dat shit + struct MsgQueue *ptr_=ptr->l.tqe_next; + + free(MsgQ_RemoveMsg(&SkypeMsgs, ptr)); + ptr=ptr_; + continue; + } + bProcess = (strcmp (pMsg, "SENT") == 0 || strcmp (pMsg, "QUEUED") == 0 || + strcmp (pMsg, "FAILED") == 0 || strcmp (pMsg, "IGNORED") == 0 || + strcmp (pMsg, "SENDING") == 0); + } + } + } + if (bProcess) { + msg=MsgQ_RemoveMsg(&SkypeMsgs, ptr); + LOG(("l.tqe_next; + } + LeaveCriticalSection(&SkypeMsgs.cs); + InterlockedIncrement ((long *)&receivers); //receivers++; + dwWaitStat = WaitForSingleObject(SkypeMsgReceived, maxwait); + if (receivers>1) InterlockedDecrement ((long *)&receivers); // receivers--; + if (receivers>1) {LOG (("SkypeRcvMsg: %d receivers still waiting", receivers));} + + } while(dwWaitStat == WAIT_OBJECT_0 && !MirandaShuttingDown); + InterlockedDecrement ((long *)&receivers); + LOG((" Answer %s", str, ptr)); + return ptr; +} + +char *SkypeGetID(char *szWhat, char *szWho, char *szProperty) { + char szID[16]={0}; + static DWORD dwId = 0; + + if (protocol>=4 || bIsImoproxy) sprintf (szID, "#G%d ", dwId++); + return __SkypeGet (szID, szWhat, szWho, szProperty); +} + +char *SkypeGet(char *szWhat, char *szWho, char *szProperty) { + return __SkypeGet ("", szWhat, szWho, szProperty); +} + +#ifdef _UNICODE +WCHAR *SkypeGetW(char *szWhat, WCHAR *szWho, char *szProperty) { + char *ptszWho = (char*)make_utf8_string(szWho); + char *pRet = SkypeGet (szWhat, ptszWho, szProperty); + free (ptszWho); + if (pRet) { + WCHAR *ptr = make_unicode_string((const unsigned char*)pRet); + free (pRet); + return ptr; + } + return NULL; +} +#endif + +char *SkypeGetErr(char *szWhat, char *szWho, char *szProperty) { + char *ret = SkypeGet(szWhat, szWho, szProperty); + if (ret && !strncmp(ret, "ERROR", 5)) { + free (ret); + return NULL; + } + return ret; +} + +#ifdef _UNICODE +WCHAR *SkypeGetErrW(char *szWhat, TCHAR *szWho, char *szProperty) { + WCHAR *ret = SkypeGetW(szWhat, szWho, szProperty); + if (ret && !_tcsncmp(ret, _T("ERROR"), 5)) { + free (ret); + return NULL; + } + return ret; +} +#endif + + +/* SkypeGetProfile + * + * Issues a SET PROFILE szProperty szValue and waits until the answer is received + * Returns the answer or NULL on failure + * BEWARE: Don't forget to free() return value! + * + * For example: SkypeGetProfile("FULLNAME", "Tweety"); +*/ +char *SkypeGetProfile(char *szProperty) { + return SkypeGet ("PROFILE", "", szProperty); +} + +/* SkypeSetProfile + * + * +*/ +int SkypeSetProfile(char *szProperty, char *szValue) { + return SkypeSend("SET PROFILE %s %s", szProperty, szValue); +} + +/* SkypeMsgCollectGarbage + * + * Purpose: Runs the garbage collector on the Skype Message-Queue to throw out old + * messages which may unnecessarily eat up memory. + * Params : age - Time in seconds. Messages older than this value will be + * thrown out. + * Returns: 0 - No messages were thrown out + * >0 - n messages were thrown out + */ +int SkypeMsgCollectGarbage(time_t age) { + return MsgQ_CollectGarbage(&SkypeMsgs, age); +} + + +/* SkypeCall + * + * Purpose: Give a Skype call to the given User in wParam + * or hangs up existing call + * (hangUp is moved over to SkypeCallHangup) + * Params : wParam - Handle to the User to be called + * lParam - Can be NULL + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + char *msg=0; + int res; + + if (!DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + res = -1; // no direct return, because dbv needs to be freed + } else { + if (DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; + msg=(char *)malloc(strlen(dbv.pszVal)+6); + strcpy(msg, "CALL "); + strcat(msg, dbv.pszVal); + res=SkypeSend(msg); + } + DBFreeVariant(&dbv); + free(msg); + return res; +} + +/* SkypeCallHangup + * + * Prupose: Hangs up the existing call to the given User + * in wParam. + * + * Params : wParam - Handle to the User to be called + * lParam - Can be NULL + * + * Returns: 0 - Success + * -1 - Failure + * + */ +INT_PTR SkypeCallHangup(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + char *msg=0; + int res = -1; + + if (!DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + msg=(char *)malloc(strlen(dbv.pszVal)+21); + sprintf(msg, "SET %s STATUS FINISHED", dbv.pszVal); + //sprintf(msg, "ALTER CALL %s HANGUP", dbv.pszVal); + res=SkypeSend(msg); +#if _DEBUG + DBDeleteContactSetting((HANDLE)wParam, SKYPE_PROTONAME, "CallId"); +#endif + //} else { + // if (DBGetContactSetting((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) return -1; + // msg=(char *)malloc(strlen(dbv.pszVal)+6); + // strcpy(msg, "CALL "); + // strcat(msg, dbv.pszVal); + // res=SkypeSend(msg); + } + DBFreeVariant(&dbv); + free(msg); + return res; +} + +/* FixNumber + * + * Purpose: Eliminates all non-numeric chars from the given phonenumber + * Params : p - Pointer to the buffer with the number + */ +static void FixNumber(char *p) { + unsigned int i; + + for (i=0;i<=strlen(p);i++) + if ((p[i]<'0' || p[i]>'9')) + if (p[i]) { + memmove(p+i, p+i+1, strlen(p+i)); + i--; + } else break; +} + + +/* DialDlgProc + * + * Purpose: Dialog procedure for the Dial-Dialog + */ +static BOOL CALLBACK DialDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static HANDLE hContact; + static unsigned int entries=0; + BOOL TempAdded=FALSE; + char number[64], *msg, *ptr=NULL; + + switch (uMsg){ + case WM_INITDIALOG: + hContact=(HANDLE)lParam; + Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); + TranslateDialogDefault(hwndDlg); + + if (lParam) { + DBVARIANT dbv; + BOOL bDialNow=TRUE; + + if (!DBGetContactSetting(hContact,"UserInfo","MyPhone1",&dbv)) { + int j; + char idstr[16]; + + // Multiple phone numbers, select one + bDialNow=FALSE; + DBFreeVariant(&dbv); + for(j=0;;j++) { + sprintf(idstr,"MyPhone%d",j); + if(DBGetContactSettingString(hContact,"UserInfo",idstr,&dbv)) break; + FixNumber(dbv.pszVal+1); // Leave + alone + SendDlgItemMessage(hwndDlg,IDC_NUMBER,CB_ADDSTRING,0,(LPARAM)dbv.pszVal); + DBFreeVariant(&dbv); + } + } + if (DBGetContactSettingString(hContact,SKYPE_PROTONAME,"SkypeOutNr",&dbv)) { + DBGetContactSettingString(hContact,"UserInfo","MyPhone0",&dbv); + FixNumber(dbv.pszVal+1); + } + SetDlgItemTextA(hwndDlg, IDC_NUMBER, dbv.pszVal); + DBFreeVariant(&dbv); + if (bDialNow) PostMessage(hwndDlg, WM_COMMAND, IDDIAL, 0); + } else { + DBVARIANT dbv; + char number[64]; + + for (entries=0;entriesMAX_ENTRIES) entries=MAX_ENTRIES; + for (i=entries;i>0;i--) { + sprintf(buf, "LastNumber%d", i-1); + if (!DBGetContactSettingString(NULL, SKYPE_PROTONAME, buf, &dbv)) { + sprintf(buf, "LastNumber%d", i); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, buf, dbv.pszVal); + DBFreeVariant(&dbv); + } else break; + } + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "LastNumber0", number); + } + TempAdded=TRUE; + } + if (!DBWriteContactSettingString(hContact, SKYPE_PROTONAME, "SkypeOutNr", number)) { + msg=(char *)malloc(strlen(number)+6); + strcpy(msg, "CALL "); + strcat(msg, number); + if (SkypeSend(msg) || (ptr=SkypeRcv("ERROR", 500))) { + DBDeleteContactSetting(hContact, SKYPE_PROTONAME, "SkypeOutNr"); + if (ptr) { + OUTPUTA(ptr); + free(ptr); + } + if (TempAdded) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); + } + free(msg); + } + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "DIALdlg"); + if (httbButton) CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)httbButton, TTBST_RELEASED); + break; + } + return FALSE; +} + +/* CallstatDlgProc + * + * Purpose: Dialog procedure for the CallStatus Dialog + */ +static BOOL CALLBACK CallstatDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static int selected; + static DBVARIANT dbv, dbv2={0}; + + switch (uMsg){ + case WM_INITDIALOG: + { + HANDLE hContact; + char *szProto; + + if (!DBGetContactSettingString((HANDLE)lParam, SKYPE_PROTONAME, "CallId", &dbv)) { + + // Check, if another call is in progress + for (hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);hContact != NULL;hContact=(HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) { + szProto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if (szProto!=NULL && !strcmp(szProto, SKYPE_PROTONAME) && hContact!=(HANDLE)lParam && + DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 && + !DBGetContactSettingString(hContact, SKYPE_PROTONAME, "CallId", &dbv2)) + { + if (DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "OnHold", 0)) { + DBFreeVariant(&dbv2); + continue; + } else break; + } + } + + if (dbv2.pszVal) + { + char buf[256], buf2[256]; + char *szOtherCaller=(char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0); + + Utils_RestoreWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); + TranslateDialogDefault(hwndDlg); + SendMessage(hwndDlg, WM_COMMAND, IDC_JOIN, 0); + + GetWindowTextA(hwndDlg, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)lParam,0)); + SetWindowTextA(hwndDlg, buf2); + + GetDlgItemTextA(hwndDlg, IDC_JOIN, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, szOtherCaller); + SetDlgItemTextA(hwndDlg, IDC_JOIN, buf2); + + GetDlgItemTextA(hwndDlg, IDC_HOLD, buf, sizeof(buf)); + _snprintf(buf2, sizeof(buf), buf, szOtherCaller); + SetDlgItemTextA(hwndDlg, IDC_HOLD, buf2); + + return TRUE; + } + + // No other call in progress, no need for this Dlg., just answer the call + SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); + testfor ("ERROR", 200); + DBFreeVariant(&dbv); + } + DestroyWindow(hwndDlg); + break; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_JOIN: + case IDC_HOLD: + case IDC_HANGUP: + CheckRadioButton(hwndDlg, IDC_JOIN, IDC_HANGUP, (selected=LOWORD(wParam))); + break; + case IDOK: + { + char *szIdCall2; + + switch (selected) { + case IDC_JOIN: + if (szIdCall2=strchr(dbv2.pszVal, ' ')) + SkypeSend("SET %s JOIN_CONFERENCE%s", dbv.pszVal, szIdCall2); + break; + case IDC_HOLD: + SkypeSend("SET %s STATUS ONHOLD", dbv2.pszVal); + SkypeSend("SET %s STATUS INPROGRESS", dbv.pszVal); + break; + case IDC_HANGUP: + SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); + break; + } + + DBFreeVariant(&dbv); + DBFreeVariant(&dbv2); + DestroyWindow(hwndDlg); + break; + } + } + break; + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg, NULL, SKYPE_PROTONAME, "CALLSTATdlg"); + break; + } + return FALSE; +} + + +/* SkypeOutCallErrorCheck + * + * Purpose: Checks, if an error has occured after call and + * if so, hangs up the call + * This procedure is a seperate thread to not block the core + * while waiting for "ERROR" + * Params : szCallId - ID of the call + */ +void SkypeOutCallErrorCheck(char *szCallId) { + if (testfor("ERROR", 500)) EndCallThread(szCallId); +} + +/* SkypeOutCall + * + * Purpose: Give a SkypeOut call to the given User in wParam + * or hangs up existing call + * The user's record is searched for Phone-number entries. + * If there is more than 1 entry, the Dial-Dialog is shown + * Params : wParam - Handle to the User to be called + * If NULL, the dial-dialog is shown + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeOutCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int res = -1; + + if (wParam && !DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) { + res=SkypeSend("SET %s STATUS FINISHED", dbv.pszVal); + pthread_create(( pThreadFunc )SkypeOutCallErrorCheck, _strdup(dbv.pszVal)); + DBFreeVariant(&dbv); + } else if (!CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIAL), NULL, DialDlgProc, (LPARAM)wParam)) return -1; + return res; +} + +/* SkypeHoldCall + * + * Purpose: Put the call to the User given in wParam on Hold or Resumes it + * Params : wParam - Handle to the User + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeHoldCall(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int retval; + + LOG(("SkypeHoldCall started")); + if (!wParam || DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, "CallId", &dbv)) + return -1; + retval = SkypeSend ("SET %s STATUS %s", dbv.pszVal, + DBGetContactSettingByte((HANDLE)wParam, SKYPE_PROTONAME, "OnHold", 0)?"INPROGRESS":"ONHOLD"); + DBFreeVariant(&dbv); + return retval; +} + +/* SkypeAnswerCall + * + * Purpose: Answer a Skype-call when a user double-clicks on + * The incoming-call-Symbol. Works for both, Skype and SkypeOut-calls + * Params : wParam - Not used + * lParam - CLISTEVENT* + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeAnswerCall(WPARAM wParam, LPARAM lParam) { + + LOG(("SkypeAnswerCall started")); + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CALLSTAT), NULL, CallstatDlgProc, (LPARAM)((CLISTEVENT*)lParam)->hContact); + return 0; +} +/* SkypeSetNick + * + * Purpose: Set Full Name in profile + * Params : wParam=0 + * lParam=(LPARAM)(const char*)Nick text + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetNick(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Nick = NULL; + + if (wParam & SMNN_UNICODE) + { + DBWriteContactSettingWString(0, SKYPE_PROTONAME, "Nick", (WCHAR*)lParam); + if (AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && + !(Nick = (char*)make_utf8_string((WCHAR*)lParam))) return -1; + } + else + { + DBWriteContactSettingString(0, SKYPE_PROTONAME, "Nick", (char*)lParam); + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS && + utf8_encode((const char *)lParam, &Nick) == -1 ) return -1; + } + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE FULLNAME %s", Nick); + if (Nick) free (Nick); + + return retval; + +} +/* SkypeSetAwayMessage + * + * Purpose: Set Mood message in profile + * Params : wParam=status mode + * lParam=(LPARAM)(const char*)message text + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetAwayMessage(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Mood = NULL; + + if (!lParam) lParam=(LPARAM)""; + if(utf8_encode((const char *)lParam, &Mood) == -1 ) return -1; + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "MoodText", (const char *)lParam); + + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); + free (Mood); + + return retval; +} +INT_PTR SkypeSetAwayMessageW(WPARAM wParam, LPARAM lParam) { + int retval = -1; + char *Mood = NULL; + + if (!lParam) lParam=(LPARAM)""; + if (!(Mood = (char*)make_utf8_string((WCHAR*)lParam))) return -1; + DBWriteContactSettingWString(NULL, SKYPE_PROTONAME, "MoodText", (WCHAR*)lParam); + + if(AttachStatus == SKYPECONTROLAPI_ATTACH_SUCCESS) + retval = SkypeSend("SET PROFILE MOOD_TEXT %s", Mood); + free (Mood); + + return retval; +} + +/* SkypeSetAvatar + * + * Purpose: Set user avatar in profile + * Params : wParam=0 + * lParam=(LPARAM)(const char*)filename + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam) { + char *filename = (char *) lParam, *ext; + char AvatarFile[MAX_PATH+1], OldAvatarFile[1024]; + char *ptr = NULL; + int ret; + char command[500]; + DBVARIANT dbv = {0}; + BOOL hasOldAvatar = (DBGetContactSettingString(NULL, SKYPE_PROTONAME, "AvatarFile", &dbv) == 0 && dbv.type == DBVT_ASCIIZ); + size_t len; + + if (AttachStatus != SKYPECONTROLAPI_ATTACH_SUCCESS) + return -3; + + if (filename == NULL) + return -1; + len = strlen(filename); + if (len < 4) + return -1; + + ext = &filename[len-4]; + if (_stricmp(ext, ".jpg")==0 || _stricmp(ext-1, ".jpeg")==0) + ext = "jpg"; + else if (_stricmp(ext, ".png")==0) + ext = "png"; + else + return -2; + + FoldersGetCustomPath(hProtocolAvatarsFolder, AvatarFile, sizeof(AvatarFile), DefaultAvatarsFolder); + mir_snprintf(AvatarFile, sizeof(AvatarFile), "%s\\%s avatar.%s", AvatarFile, SKYPE_PROTONAME, ext); + + // Backup old file + if (hasOldAvatar) + { + strncpy(OldAvatarFile, dbv.pszVal, sizeof(OldAvatarFile)-4); + OldAvatarFile[sizeof(OldAvatarFile)-5] = '\0'; + strcat(OldAvatarFile, "_old"); + DeleteFileA(OldAvatarFile); + if (!MoveFileA(dbv.pszVal, OldAvatarFile)) + { + DBFreeVariant(&dbv); + return -3; + } + } + + // Copy new file + if (!CopyFileA(filename, AvatarFile, FALSE)) + { + if (hasOldAvatar) + { + MoveFileA(OldAvatarFile, dbv.pszVal); + DBFreeVariant(&dbv); + } + return -3; + } + + // Try to set with skype + mir_snprintf(command, sizeof(command), "SET AVATAR 1 %s", AvatarFile); + if (SkypeSend(command) || (ptr = SkypeRcv(command+4, INFINITE)) == NULL || !strncmp(ptr, "ERROR", 5)) + { + DeleteFileA(AvatarFile); + + if (hasOldAvatar) + MoveFileA(OldAvatarFile, dbv.pszVal); + + ret = -4; + } + else + { + if (hasOldAvatar) + DeleteFileA(OldAvatarFile); + + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "AvatarFile", AvatarFile); + + ret = 0; + } + + if (ptr != NULL) + free(ptr); + + if (hasOldAvatar) + DBFreeVariant(&dbv); + + return ret; +} + + +/* SkypeSendFile + * + * Purpose: Opens the Skype-dialog to send a file + * Params : wParam - Handle to the User + * lParam - Not used + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeSendFile(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + int retval; + + if (!wParam || DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + retval=SkypeSend("OPEN FILETRANSFER %s", dbv.pszVal); + DBFreeVariant(&dbv); + return retval; +} + +/* SkypeChatCreate + * + * Purpose: Creates a groupchat with the user + * Params : wParam - Handle to the User + * lParam - Not used + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeChatCreate(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + HANDLE hContact=(HANDLE)wParam; + char *ptr, *ptr2; + + if (!hContact || DBGetContactSettingString(hContact, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + // Flush old messages + while (testfor("\0CHAT \0 STATUS \0", 0)); + if (SkypeSend("CHAT CREATE %s", dbv.pszVal) || !(ptr=SkypeRcv ("\0CHAT \0 STATUS \0", INFINITE))) + { + DBFreeVariant(&dbv); + return -1; + } + DBFreeVariant(&dbv); + if (ptr2=strstr (ptr, "STATUS")) { + *(ptr2-1)=0; + ChatStart (ptr+5, FALSE); + } + free(ptr); + return 0; +} + +/* SkypeAdduserDlg + * + * Purpose: Show Skype's Add user Dialog + */ +INT_PTR SkypeAdduserDlg(WPARAM wParam, LPARAM lParam) { + SkypeSend("OPEN ADDAFRIEND"); + return 0; +} + +/* SkypeFlush + * + * Purpose: Flush the Skype Message-List + */ +void SkypeFlush(void) { + char *ptr; + + while ((ptr=SkypeRcv(NULL, 0))!=NULL) free(ptr); +} + +/* SkypeStatusToMiranda + * + * Purpose: Converts the specified Skype-Status mode to the corresponding Miranda-Status mode + * Params : s - Skype Status + * Returns: The correct Status + * 0 - Nothing found + */ +int SkypeStatusToMiranda(char *s) { + int i; + if (!strcmp("SKYPEOUT", s)) return DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); + for(i=0; status_codes[i].szStat; i++) + if (!strcmp(status_codes[i].szStat, s)) + return status_codes[i].id; + return 0; +} + +/* MirandaStatusToSkype + * + * Purpose: Converts the specified Miranda-Status mode to the corresponding Skype-Status mode + * Params : id - Miranda Status + * Returns: The correct Status + * NULL - Nothing found + */ +char *MirandaStatusToSkype(int id) { + int i; + if (DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) { + switch (id) + { + case ID_STATUS_NA: return "AWAY"; + case ID_STATUS_FREECHAT: return "ONLINE"; + } + } + for(i=0; status_codes[i].szStat; i++) + if (status_codes[i].id==id) + return status_codes[i].szStat; + return NULL; +} + +/* GetSkypeErrorMsg + * + * Purpose: Get a human-readable Error-Message for the supplied Skype Error-Message + * Params : str - Skype Error-Message string + * Returns: Human-readable Error Message or NULL, if nothing was found + * Warning: Don't forget to free() return value + */ +char *GetSkypeErrorMsg(char *str) { + char *pos, *reason, *msg; + + LOG (("GetSkypeErrorMsg received error: %s", str)); + if (!strncmp(str, "ERROR", 5)) { + reason=_strdup(str); + return reason; + } + if ((pos=strstr(str, "FAILURE")) ) { + switch(atoi(pos+14)) { + case MISC_ERROR: msg="Misc. Error"; break; + case USER_NOT_FOUND: msg="User does not exist, check username"; break; + case USER_NOT_ONLINE: msg="Trying to send IM to an user, who is not online"; break; + case USER_BLOCKED: msg="IM blocked by recipient"; break; + case TYPE_UNSUPPORTED: msg="Type unsupported"; break; + case SENDER_NOT_FRIEND: msg="Sending IM message to user, who has not added you to friendslist and has chosen 'only people in my friendslist can start IM'"; break; + case SENDER_NOT_AUTHORIZED: msg="Sending IM message to user, who has not authorized you and has chosen 'only people whom I have authorized can start IM'"; break; + default: msg="Unknown error"; + } + reason=(char *)malloc(strlen(pos)+strlen(msg)+3); + sprintf (reason, "%s: %s", pos, msg); + return reason; + } + return NULL; +} + +/* testfor + * + * Purpose: Wait, until the given Message-Fragment is received from Skype within + * the given amount of time + * Params : see SkypeRcv + * Returns: TRUE - Message was received within the given amount of time + * FALSE- nope, sorry + */ +BOOL testfor(char *what, DWORD maxwait) { + char *res; + + if ((res=SkypeRcv(what, maxwait))==NULL) return FALSE; + free(res); + return TRUE; +} + +char SendSkypeproxyCommand(char command) { + int length=0; + char reply=0; + BOOL res; + + res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR + || send(ClientSocket, (char *)&command, sizeof(command), 0)==SOCKET_ERROR + || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; + if (res) + return -1; + else + return reply; +} + +/* ConnectToSkypeAPI + * + * Purpose: Establish a connection to the Skype API + * Params : path - Path to the Skype application + * iStart - Need to start skype for status change. + * 1 = Normal start if Skype not running + * 2 = Forced startp code execution no matter what + * Returns: 0 - Connecting succeeded + * -1 - Something went wrong + */ +int ConnectToSkypeAPI(char *path, int iStart) { + static int iRet = -1; // last request result + static volatile long newRequest = TRUE; + + InterlockedExchange(&newRequest, TRUE); // place new request + EnterCriticalSection(&ConnectMutex); // Prevent reentrance + if (iRet == -1 || newRequest) + { + iRet = _ConnectToSkypeAPI(path, iStart); + InterlockedExchange(&newRequest, FALSE); // every thread which is waiting for connect mutex will get our result as well.. but subsequent calls will set this value to true and call _Connect again + } + LeaveCriticalSection(&ConnectMutex); + return iRet; +} + +void TranslateMirandaRelativePathToAbsolute(LPCSTR cszPath, LPSTR szAbsolutePath, BOOL fQuoteSpaces) { + *szAbsolutePath = 0; + CallService (MS_UTILS_PATHTOABSOLUTE, (WPARAM)(*cszPath ? cszPath : ".\\"), (LPARAM)szAbsolutePath); + if(fQuoteSpaces && strchr((LPCSTR)szAbsolutePath, ' ')){ + memmove (szAbsolutePath+1, szAbsolutePath, strlen(szAbsolutePath)+1); + *szAbsolutePath='"'; + strcat (szAbsolutePath, "\""); + } + + TRACEA(szAbsolutePath); +} + +static int my_spawnv(const char *cmdname, const char *const *argv, PROCESS_INFORMATION *pi) +{ + int i, iLen=0; + char *CommandLine; + STARTUPINFOA si={0}; + BOOL bRet; + + memset (pi, 0, sizeof(PROCESS_INFORMATION)); + for (i=0; argv[i]; i++) iLen+=strlen(argv[i])+1; + if (!(CommandLine = calloc(1, iLen))) return -1; + for (i=0; argv[i]; i++) { + if (i) strcat (CommandLine, " "); + strcat (CommandLine, argv[i]); + } + si.cb = sizeof(si); + + bRet = CreateProcessA( cmdname,CommandLine,NULL,NULL,FALSE,0,NULL,NULL,&si,pi); + free(CommandLine); + if (!bRet) return -1; + return (DWORD)pi->hProcess; +} + +static int _ConnectToSkypeAPI(char *path, int iStart) { + BOOL SkypeLaunched=FALSE; + BOOL UseCustomCommand = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0); + int counter=0, i, j, maxattempts=DBGetContactSettingWord(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10); + char *args[7], *pFree = NULL; + char *SkypeOptions[]={"/notray", "/nosplash", "/minimized", "/removable", "/datapath:", "/secondary"}; + const int SkypeDefaults[]={0, 1, 1, 0, 0}; + + char szAbsolutePath[MAX_PATH]; + + LOG(("ConnectToSkypeAPI started.")); + if (UseSockets) + { + SOCKADDR_IN service; + DBVARIANT dbv; + long inet; + struct hostent *hp; + + LOG(("ConnectToSkypeAPI: Connecting to Skype2socket socket...")); + if ((ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) return -1; + + if (!DBGetContactSettingString(NULL, SKYPE_PROTONAME, "Host", &dbv)) { + if ((inet=inet_addr(dbv.pszVal))==-1) { + if (hp=gethostbyname(dbv.pszVal)) + memcpy(&inet, hp->h_addr, sizeof(inet)); + else { + OUTPUT(_T("Cannot resolve host!")); + DBFreeVariant(&dbv); + return -1; + } + } + DBFreeVariant(&dbv); + } else { + OUTPUT(_T("Cannot find valid host to connect to.")); + return -1; + } + + service.sin_family = AF_INET; + service.sin_addr.s_addr = inet; + service.sin_port = htons((unsigned short)DBGetContactSettingWord(NULL, SKYPE_PROTONAME, "Port", 1401)); + + if ( connect( ClientSocket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR) return -1; + + if (DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "RequiresPassword", 0) && !DBGetContactSettingString(NULL, SKYPE_PROTONAME, "Password", &dbv)) + { + char reply=0; + + CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal); + if ((reply=SendSkypeproxyCommand(AUTHENTICATE))==-1) + { + DBFreeVariant(&dbv); + return -1; + } + if (!reply) { + OUTPUT(_T("Authentication is not supported/needed for this Skypeproxy server. It will be disabled.")); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "RequiresPassword", 0); + } else { + unsigned int length=(unsigned int)strlen(dbv.pszVal); + BOOL res; + res = send(ClientSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR + || send(ClientSocket, dbv.pszVal, length, 0)==SOCKET_ERROR + || recv(ClientSocket, (char *)&reply, sizeof(reply), 0)==SOCKET_ERROR; + if (res) + { + DBFreeVariant(&dbv); + return -1; + } + if (!reply) + { + OUTPUT(_T("Authentication failed for this server, connection was not successful. Verify that your password is correct!")); + DBFreeVariant(&dbv); + return -1; + } + } + DBFreeVariant(&dbv); + } + else + { + char reply=0; + + if ((reply=SendSkypeproxyCommand(CAPABILITIES))==-1) return -1; + if (reply&USE_AUTHENTICATION) { + OUTPUT(_T("The server you specified requires authentication, but you have not supplied a password for it. Check the Skype plugin settings and try again.")); + return -1; + } + } + + + if (!rcvThreadRunning) + if(_beginthread(( pThreadFunc )rcvThread, 0, NULL)==-1) return -1; + + AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; + return 0; + } + + if (pszProxyCallout) + { + if (SkypeSend("SET USERSTATUS ONLINE")==-1) + { + AttachStatus=SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE; + return -1; + } + for ( ;; ) { + char *ptr = SkypeRcv ("CONNSTATUS", INFINITE); + if (strcmp (ptr+11, "CONNECTING")) + { + free (ptr); + break; + } + free (ptr); + } + + AttachStatus=SKYPECONTROLAPI_ATTACH_SUCCESS; + return 0; + } + + do + { + int retval; + /* To initiate communication, Client should broadcast windows message + ('SkypeControlAPIDiscover') to all windows in the system, specifying its own + window handle in wParam parameter. + */ + if (iStart != 2 || counter) + { + LOG(("ConnectToSkypeAPI sending discover message.. hWnd=%08X", (long)g_hWnd)); + retval=SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)g_hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); + LOG(("ConnectToSkypeAPI sent discover message returning %d", retval)); + } + + /* In response, Skype responds with + message 'SkypeControlAPIAttach' to the handle specified, and indicates + connection status + SkypeReady is set if there is an answer by Skype other than API_AVAILABLE. + If there is no answer after 3 seconds, launch Skype as it's propably + not running. + */ + if (iStart == 2 || (WaitForSingleObject(SkypeReady, 3000)==WAIT_TIMEOUT && AttachStatus!=SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION)) + { + if (iStart != 2 && g_hWnd==NULL) + { + LOG(("ConnectToSkypeAPI: hWnd of SkypeDispatchWindow not yet set..")); + continue; + } + if ((iStart == 2 || !SkypeLaunched) && (path || UseCustomCommand)) + { + static PROCESS_INFORMATION pi={0}; + DWORD dwExitStatus = 0; + + if ((!pi.hProcess || !GetExitCodeProcess(pi.hProcess, &dwExitStatus) || dwExitStatus != STILL_ACTIVE) && + (DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "StartSkype", 1) || iStart)) + { + LOG(("ConnectToSkypeAPI Starting Skype, as it's not running")); + + j=1; + for (i=0; i=maxattempts && AttachStatus==-1) + { + int oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + OUTPUT(_T("ERROR: Skype not running / too old / working!")); + return -1; + } + } + } + LOG(("Attachstatus %d", AttachStatus)); + } while (AttachStatus==SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE || AttachStatus==SKYPECONTROLAPI_ATTACH_API_AVAILABLE || AttachStatus==-1); + + while (AttachStatus==SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION) Sleep(1000); + LOG(("Attachstatus %d", AttachStatus)); + if (AttachStatus!=SKYPECONTROLAPI_ATTACH_SUCCESS) { + int oldstatus; + + switch(AttachStatus) { + case SKYPECONTROLAPI_ATTACH_REFUSED: + OUTPUT(_T("Skype refused the connection :(")); + break; + case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE: + OUTPUT(_T("The Skype API is not available")); + break; + default: + LOG(("ERROR: AttachStatus: %d", AttachStatus)); + OUTPUT(_T("Wheee, Skype won't let me use the API. :(")); + } + oldstatus=SkypeStatus; + InterlockedExchange((long *)&SkypeStatus, (int)ID_STATUS_OFFLINE); + ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldstatus, SkypeStatus); + return -1; + } + + return 0; +} + +/* CloseSkypeAPI + * Purpose: Closes existing api connection + * Params: path - Path to the Skype application; could be NULL when using proxy + * Returns: always 0 + */ +int CloseSkypeAPI(char *skypePath) +{ + char szAbsolutePath[MAX_PATH]; + + logoff_contacts(TRUE); + if (UseSockets) + { + if (ClientSocket != INVALID_SOCKET) + { + closesocket(ClientSocket); + ClientSocket = INVALID_SOCKET; + } + } + else { + if (!pszProxyCallout) + { + if (AttachStatus!=-1) + { + // it was crashing when the skype-network-proxy is used (imo2sproxy for imo.im) and skype-path is empty + // now, with the "UseSockets" check and the skypePath[0] != 0 check its fixed + if (skypePath != NULL && skypePath[0] != 0) { + TranslateMirandaRelativePathToAbsolute(skypePath, szAbsolutePath, FALSE); + _spawnl(_P_NOWAIT, szAbsolutePath, szAbsolutePath, "/SHUTDOWN", NULL); + } + } + } + } + SkypeInitialized=FALSE; + ResetEvent(SkypeReady); + AttachStatus=-1; + if (g_hWnd) KillTimer (g_hWnd, 1); + return 0; +} +/* ConnectToSkypeAPI + * + * Purpose: Establish a connection to the Skype API + * Params : path - Path to the Skype application + * Returns: 0 - Connecting succeeded + * -1 - Something went wrong + */ +//int __connectAPI(char *path) { +// int retval; +// +// EnterCriticalSection(&ConnectMutex); +// if (AttachStatus!=-1) { +// LeaveCriticalSection(&ConnectMutex); +// return -1; +// } +// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_CONNECTING); +// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_OFFLINE, SkypeStatus); +// retval=__connectAPI(path); +// if (retval==-1) { +// logoff_contacts(); +// InterlockedExchange((long *)&SkypeStatus, ID_STATUS_OFFLINE); +// ProtoBroadcastAck(SKYPE_PROTONAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) ID_STATUS_CONNECTING, SkypeStatus); +// } +// LeaveCriticalSection(&ConnectMutex); +// return retval; +//} diff --git a/protocols/Skype/skypeapi.h b/protocols/Skype/skypeapi.h new file mode 100644 index 0000000000..fa4f5139a1 --- /dev/null +++ b/protocols/Skype/skypeapi.h @@ -0,0 +1,69 @@ +// Skype API defines +#define SKYPECONTROLAPI_ATTACH_SUCCESS 0 +#define SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION 1 +#define SKYPECONTROLAPI_ATTACH_REFUSED 2 +#define SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE 3 +#define SKYPECONTROLAPI_ATTACH_API_AVAILABLE 0x8001 + +#define MISC_ERROR 1 +#define USER_NOT_FOUND 2 +#define USER_NOT_ONLINE 3 +#define USER_BLOCKED 4 +#define TYPE_UNSUPPORTED 5 +#define SENDER_NOT_FRIEND 6 +#define SENDER_NOT_AUTHORIZED 7 + +#define MAX_ENTRIES 128 // Max. 128 number-Entries in Dial-dlg. + +typedef struct { + int id; + char *szStat; +} status_map; + +// Prototypes +int SkypeMsgInit(void); +int SkypeMsgAdd(char *msg); +void SkypeMsgCleanup(void); +char *SkypeMsgGet(void); +int SkypeSend(char*, ...); +char *SkypeRcv(char *what, DWORD maxwait); +char *SkypeRcvTime(char *what, time_t st, DWORD maxwait); +char *SkypeRcvMsg(char *what, time_t st, HANDLE hContact, DWORD maxwait); +INT_PTR SkypeCall(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeCallHangup(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeOutCall(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeHup(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeHoldCall(WPARAM wParam, LPARAM lParam); +void SkypeFlush(void); +int SkypeStatusToMiranda(char *s); +char *MirandaStatusToSkype(int id); +char *GetSkypeErrorMsg(char *str); +BOOL testfor(char *what, DWORD maxwait); +int ConnectToSkypeAPI(char *path, BOOL bStart); +int CloseSkypeAPI(char *skypePath); +INT_PTR SkypeAdduserDlg(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeAnswerCall(WPARAM wParam, LPARAM lParam); +int SkypeMsgCollectGarbage(time_t age); +INT_PTR SkypeSendFile(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSetAvatar(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSetAwayMessage(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSetAwayMessageW(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeSetNick(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeChatCreate(WPARAM wParam, LPARAM lParam); +int SkypeSetProfile(char *szProperty, char *szValue); +char *SkypeGet(char *szWhat, char *szWho, char *szProperty); +char *SkypeGetID(char *szWhat, char *szWho, char *szProperty); +char *SkypeGetErr(char *szWhat, char *szWho, char *szProperty); +#ifdef _UNICODE +WCHAR *SkypeGetW(char *szWhat, WCHAR *szWho, char *szProperty); +WCHAR *SkypeGetErrW(char *szWhat, TCHAR *szWho, char *szProperty); +#define SkypeGetT SkypeGetW +#define SkypeGetErrT SkypeGetErrW +#else +#define SkypeGetT SkypeGet +#define SkypeGetErrT SkypeGetErr +#endif +char *SkypeGetProfile(char *szProperty); +void SetUserNamePassword(); +INT_PTR SkypeAdduserDlg(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeReceivedAPIMessage(WPARAM wParam, LPARAM lParam); diff --git a/protocols/Skype/skypeopt.c b/protocols/Skype/skypeopt.c new file mode 100644 index 0000000000..2dfc4faef5 --- /dev/null +++ b/protocols/Skype/skypeopt.c @@ -0,0 +1,969 @@ +#include "skype.h" +#include "skypeopt.h" +#include "pthread.h" +#include "gchat.h" +#include "skypeprofile.h" +#if(WINVER >= 0x0500) +#include "uxtheme.h" +#define HAVE_UXTHEMES +#endif + +#ifdef SKYPE_AUTO_DETECTION +#include "ezxml/ezxml.c" +#endif + +#ifdef UNICODE +#include "utf8.h" +#endif + +#pragma warning (disable: 4706) // assignment within conditional expression + +// VC6 SDK defines +#ifndef BIF_SHAREABLE +#define BIF_SHAREABLE 0x8000 // sharable resources displayed (remote shares, requires BIF_USENEWUI) +#endif +#ifndef BIF_NEWDIALOGSTYLE +#define BIF_NEWDIALOGSTYLE 0x0040 // Use the new dialog layout with the ability to resize +#endif // Caller needs to call OleInitialize() before using this API +#ifndef BIF_NONEWFOLDERBUTTON +#define BIF_NONEWFOLDERBUTTON 0x0200 // Do not add the "New Folder" button to the dialog. Only applicable with BIF_NEWDIALOGSTYLE. +#endif + + +extern HINSTANCE hInst; +extern PLUGININFO pluginInfo; +extern char protocol, g_szProtoName[]; +extern BOOL SkypeInitialized, bProtocolSet, bIsImoproxy; +extern DWORD mirandaVersion; + +BOOL showPopup, showPopupErr, popupWindowColor, popupWindowColorErr; +unsigned int popupBackColor, popupBackColorErr; +unsigned int popupTextColor, popupTextColorErr; +int popupTimeSec, popupTimeSecErr; +POPUPDATAT InCallPopup; +POPUPDATAT ErrorPopup; + +static SkypeProfile myProfile; +static HBITMAP hAvatar = NULL; + +extern BOOL PopupServiceExists; +extern BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD); + +int RegisterOptions(WPARAM wParam, LPARAM lParam) { + OPTIONSDIALOGPAGE odp; + + UNREFERENCED_PARAMETER(lParam); + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pszGroup = "Network"; + odp.pszTitle = SKYPE_PROTONAME; + odp.pfnDlgProc = OptionsDlgProc; + odp.flags = ODPF_BOLDGROUPS; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + + if(PopupServiceExists) + { + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUP); + odp.pszGroup = "Popups"; + odp.pfnDlgProc = OptPopupDlgProc; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + } + + return 0; +} + +INT_PTR CALLBACK OptPopupDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static RECT r; + + switch ( msg ) + { + case WM_INITDIALOG: + TranslateDialogDefault( hwnd ); + // Message Popup + popupTimeSec = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupTimeSec", 4); + popupTextColor = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupTextColor", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColor = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupBackColor", GetSysColor(COLOR_BTNFACE)); + popupWindowColor = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "popupWindowColor", FALSE); + showPopup = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "showPopup", TRUE); + // ERROR Message Popup + popupTimeSecErr = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupTimeSecErr", 4); + popupTextColorErr = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupTextColorErr", GetSysColor(COLOR_WINDOWTEXT)); + popupBackColorErr = DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "popupBackColorErr", GetSysColor(COLOR_BTNFACE)); + popupWindowColorErr = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "popupWindowColorErr", FALSE); + showPopupErr = DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "showPopupErr", TRUE); + + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); + CheckDlgButton(hwnd, IDC_POPUPINCOMING, (WPARAM) showPopup); + CheckDlgButton(hwnd, IDC_USEWINCOLORS, (WPARAM) popupWindowColor); + CheckDlgButton(hwnd, IDC_POPUPERROR, (WPARAM) showPopupErr); + CheckDlgButton(hwnd, IDC_USEWINCOLORSERR, (WPARAM) popupWindowColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPTIME, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt(hwnd, IDC_POPUPTIME, popupTimeSec,FALSE); + SendDlgItemMessage(hwnd, IDC_POPUPTIMEERR, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt(hwnd, IDC_POPUPTIMEERR, popupTimeSecErr,FALSE); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETCOLOUR,0, popupBackColor); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETCOLOUR,0, popupTextColor); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLOR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETCOLOUR,0, popupBackColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPBACKCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_BTNFACE)); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETCOLOUR,0, popupTextColorErr); + SendDlgItemMessage(hwnd, IDC_POPUPTEXTCOLORERR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); + + + return TRUE; + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) + { + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupBackColor", popupBackColor); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupTextColor", popupTextColor); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupTimeSec", popupTimeSec); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "popupWindowColor", (BYTE)popupWindowColor); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "showPopup", (BYTE)showPopup); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupBackColorErr", popupBackColorErr); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupTextColorErr", popupTextColorErr); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "popupTimeSecErr", popupTimeSecErr); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "popupWindowColorErr", (BYTE)popupWindowColorErr); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "showPopupErr", (BYTE)showPopupErr); + break; + } + } + break; + + + + case WM_COMMAND: + switch( LOWORD( wParam )) + { + case IDC_PREVIEW: + { + HANDLE hContact; + TCHAR * lpzContactName; + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST,0,0); + lpzContactName = (TCHAR*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,GCDNF_TCHAR); + InCallPopup.lchContact = hContact; + InCallPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); + InCallPopup.colorBack = ! popupWindowColor ? popupBackColor : GetSysColor(COLOR_BTNFACE); + InCallPopup.colorText = ! popupWindowColor ? popupTextColor : GetSysColor(COLOR_WINDOWTEXT); + InCallPopup.iSeconds = popupTimeSec; + InCallPopup.PluginData = (void *)1; + + lstrcpy(InCallPopup.lptzText, TranslateT("Incoming Skype Call")); + + lstrcpy(InCallPopup.lptzContactName, lpzContactName); + + CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&InCallPopup,0); + + + break; + } + case IDC_PREVIEWERR: + ErrorPopup.lchContact = NULL; + ErrorPopup.lchIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_CALL)); + ErrorPopup.colorBack = ! popupWindowColorErr ? popupBackColorErr : GetSysColor(COLOR_BTNFACE); + ErrorPopup.colorText = ! popupWindowColorErr ? popupTextColorErr : GetSysColor(COLOR_WINDOWTEXT); + ErrorPopup.iSeconds = popupTimeSecErr; + ErrorPopup.PluginData = (void *)1; + + lstrcpy(ErrorPopup.lptzText, TranslateT("Preview Error Message")); + + lstrcpy(ErrorPopup.lptzContactName, _T("Error Message")); + + + CallService(MS_POPUP_ADDPOPUPT,(WPARAM)&ErrorPopup,0); + + break; + + case IDC_POPUPTIME: + case IDC_POPUPTIMEERR: + { + BOOL Translated; + popupTimeSec = GetDlgItemInt(hwnd,IDC_POPUPTIME,&Translated,FALSE); + popupTimeSecErr = GetDlgItemInt(hwnd,IDC_POPUPTIMEERR,&Translated,FALSE); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + } + case IDC_POPUPTEXTCOLOR: + case IDC_POPUPBACKCOLOR: + case IDC_POPUPTEXTCOLORERR: + case IDC_POPUPBACKCOLORERR: + popupBackColor = SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLOR,CPM_GETCOLOUR,0,0); + popupTextColor = SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLOR,CPM_GETCOLOUR,0,0); + popupBackColorErr = SendDlgItemMessage(hwnd,IDC_POPUPBACKCOLORERR,CPM_GETCOLOUR,0,0); + popupTextColorErr = SendDlgItemMessage(hwnd,IDC_POPUPTEXTCOLORERR,CPM_GETCOLOUR,0,0); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_USEWINCOLORS: + popupWindowColor = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORS)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR), showPopup && ! popupWindowColor); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_POPUPINCOMING: + showPopup = (IsDlgButtonChecked(hwnd,IDC_POPUPINCOMING)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORS),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLOR),showPopup && ! popupWindowColor); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIME),showPopup); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEW),showPopup); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_USEWINCOLORSERR: + popupWindowColorErr = (IsDlgButtonChecked(hwnd,IDC_USEWINCOLORSERR)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR), showPopupErr && ! popupWindowColorErr); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + case IDC_POPUPERROR: + showPopupErr = (IsDlgButtonChecked(hwnd,IDC_POPUPERROR)==BST_CHECKED); + EnableWindow(GetDlgItem(hwnd,IDC_USEWINCOLORSERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPBACKCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_STATIC_POPUPTEXTCOLORERR),showPopupErr && ! popupWindowColorErr); + EnableWindow(GetDlgItem(hwnd,IDC_POPUPTIMEERR),showPopupErr); + EnableWindow(GetDlgItem(hwnd,IDC_PREVIEWERR),showPopupErr); + SendMessage(GetParent(hwnd),PSM_CHANGED,0,0); + break; + } + + break; + + case WM_DESTROY: + break; + } + + return 0; +} + +INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int iInit = TRUE; + + UNREFERENCED_PARAMETER(wParam); + + switch(msg) + { + case WM_INITDIALOG: + { + TCITEM tci; + RECT rcClient; + GetClientRect(hwnd, &rcClient); + + iInit = TRUE; + tci.mask = TCIF_PARAM|TCIF_TEXT; + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_DEFAULT), hwnd, OptionsDefaultDlgProc); + tci.pszText = TranslateT("Skype default"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 0, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_ADVANCED),hwnd,OptionsAdvancedDlgProc); + tci.pszText = TranslateT("Skype advanced"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 1, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); + ShowWindow((HWND)tci.lParam, SW_HIDE); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + tci.lParam = (LPARAM)CreateDialog(hInst,MAKEINTRESOURCE(IDD_OPT_PROXY),hwnd,OptionsProxyDlgProc); + tci.pszText = TranslateT("Skype proxy"); + TabCtrl_InsertItem(GetDlgItem(hwnd, IDC_OPTIONSTAB), 2, &tci); + MoveWindow((HWND)tci.lParam,1,28,rcClient.right-5,rcClient.bottom-31,1); + ShowWindow((HWND)tci.lParam, SW_HIDE); +#ifdef HAVE_UXTHEMES + if(MyEnableThemeDialogTexture) + MyEnableThemeDialogTexture((HWND)tci.lParam, ETDT_ENABLETAB); +#endif + + iInit = FALSE; + return FALSE; + } + + case PSM_CHANGED: // used so tabs dont have to call SendMessage(GetParent(GetParent(hwnd)), PSM_CHANGED, 0, 0); + if(!iInit) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + TCITEM tci; + int i,count; + tci.mask = TCIF_PARAM; + count = TabCtrl_GetItemCount(GetDlgItem(hwnd,IDC_OPTIONSTAB)); + for (i=0;icode) + { + case TCN_SELCHANGING: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_HIDE); + } + break; + case TCN_SELCHANGE: + { + TCITEM tci; + tci.mask = TCIF_PARAM; + TabCtrl_GetItem(GetDlgItem(hwnd,IDC_OPTIONSTAB),TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_OPTIONSTAB)),&tci); + ShowWindow((HWND)tci.lParam,SW_SHOW); + } + break; + } + break; + + } + break; + } + return FALSE; +} + +INT_PTR CALLBACK OptionsProxyDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + const int Skype2SocketControls[]={ IDC_STATIC_HOST, IDC_HOST, IDC_STATIC_PORT, IDC_PORT, IDC_REQPASS, IDC_PASSWORD, IDC_STATIC_RESTART }; + static BOOL initDlg=FALSE; + DBVARIANT dbv; + int i; + + switch (uMsg){ + case WM_INITDIALOG: + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + if (!DBGetContactSettingString(NULL, SKYPE_PROTONAME, "Host", &dbv)) { + SetDlgItemTextA(hwndDlg, IDC_HOST, dbv.pszVal); + DBFreeVariant(&dbv); + } else SetDlgItemText(hwndDlg, IDC_HOST, _T("localhost")); + SendDlgItemMessage(hwndDlg, IDC_PORT, EM_SETLIMITTEXT, 5, 0L); + SetDlgItemInt(hwndDlg, IDC_PORT, DBGetContactSettingWord(NULL, SKYPE_PROTONAME, "Port", 1401), FALSE); + CheckDlgButton(hwndDlg, IDC_REQPASS, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "RequiresPassword", 0)); + CheckDlgButton(hwndDlg, IDC_USES2S, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseSkype2Socket", 0)); + if (!DBGetContactSettingString(NULL, SKYPE_PROTONAME, "Password", &dbv)) { + CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal); + SetDlgItemTextA(hwndDlg, IDC_PASSWORD, dbv.pszVal); + DBFreeVariant(&dbv); + } + SendMessage(hwndDlg, WM_COMMAND, IDC_USES2S, 0); + SendMessage(hwndDlg, WM_COMMAND, IDC_REQPASS, 0); + initDlg=FALSE; + return TRUE; + case WM_NOTIFY: { + NMHDR* nmhdr = (NMHDR*)lParam; + + switch (nmhdr->code){ + case PSN_APPLY: + case PSN_KILLACTIVE: + { + char buf[1024]; + GetDlgItemTextA(hwndDlg, IDC_HOST, buf, sizeof(buf)); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "Host", buf); + DBWriteContactSettingWord(NULL, SKYPE_PROTONAME, "Port", (unsigned short)GetDlgItemInt(hwndDlg, IDC_PORT, NULL, FALSE)); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "RequiresPassword", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REQPASS), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UseSkype2Socket", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USES2S), BM_GETCHECK,0,0))); + ZeroMemory(buf, sizeof(buf)); + GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf)); + CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf), (LPARAM)buf); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "Password", buf); + return TRUE; + } + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + case IDC_USES2S: + for (i=0; i=5)) { + CheckDlgButton(hwndDlg, IDC_GROUPCHAT, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseGroupchat", 0)); + CheckDlgButton(hwndDlg, IDC_GROUPCHATREAD, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "MarkGroupchatRead", 0)); + } else { + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHAT), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), FALSE); + } + +#ifdef USEPOPUP + if (ServiceExists(MS_POPUP_ADDPOPUP)) + CheckDlgButton(hwndDlg, IDC_USEPOPUP, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UsePopup", 0)); + else +#endif + EnableWindow(GetDlgItem(hwndDlg, IDC_USEPOPUP), FALSE); + + j=DBGetContactSettingDword(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", ID_STATUS_ONTHEPHONE); + for(i=0;icode){ + case PSN_APPLY: + case PSN_KILLACTIVE: + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "EnableMenu", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_ENABLEMENU), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UsePopup", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_USEPOPUP), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UseGroupchat", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHAT), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "MarkGroupchatRead", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_GROUPCHATREAD), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "SuppressErrors", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOERRORS), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "KeepState", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_KEEPSTATE), BM_GETCHECK,0,0))); + DBWriteContactSettingDword(NULL, SKYPE_PROTONAME, "SkypeOutStatusMode", SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETITEMDATA,SendDlgItemMessage(hwndDlg,IDC_SKYPEOUTSTAT,CB_GETCURSEL,0,0),0)); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UseTimeZonePatch", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_TIMEZONE), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "IgnoreTimeZones", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_IGNTZ), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "ShowDefaultSkypeAvatar", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWDEFAULTAVATAR), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "SuppressCallSummaryMessage", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SUPPRESSCALLSUMMARYMESSAGE), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "NoSkype3Stats", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSKYPE3STATS), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "ShowFullname", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHOWFULLNAME), BM_GETCHECK,0,0))); + return TRUE; + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + case IDC_CLEANUP: + pthread_create(( pThreadFunc )CleanupNicknames, NULL); + break; + } + if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + return 0; +} + +static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + UNREFERENCED_PARAMETER(lParam); + + switch (uMsg) + { + case BFFM_INITIALIZED: + { + // Set initial directory. +#ifdef UNICODE + wchar_t* wszInitFolder = make_unicode_string((const unsigned char*)lpData); + SendMessage(hWnd, BFFM_SETSELECTION, TRUE, (LPARAM)wszInitFolder); + free(wszInitFolder); +#else + SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData); +#endif + break; + } + } + return 0; +} + +INT_PTR CALLBACK OptionsDefaultDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static BOOL initDlg=FALSE; + static int skypeLaunchControls[]={IDC_NOSPLASH,IDC_MINIMIZED,IDC_NOTRAY,IDC_REMOVEABLE,IDC_SECONDARY,IDC_DATAPATHO,IDC_CUSTOMCOMMAND,IDC_STATIC_PATHINFO}; + + switch (uMsg){ + case WM_INITDIALOG: + { + DBVARIANT dbv; + BOOL startSkype; + int i; + + initDlg=TRUE; + TranslateDialogDefault(hwndDlg); + + startSkype=DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "StartSkype", 1); + + CheckDlgButton(hwndDlg, IDC_STARTSKYPE, (BYTE)startSkype); + CheckDlgButton(hwndDlg, IDC_NOSPLASH, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "nosplash", 1)); + CheckDlgButton(hwndDlg, IDC_MINIMIZED, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "minimized", 1)); + CheckDlgButton(hwndDlg, IDC_NOTRAY, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "notray", 0)); + CheckDlgButton(hwndDlg, IDC_REMOVEABLE, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "removable", 0)); + CheckDlgButton(hwndDlg, IDC_SECONDARY, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "secondary", 0)); + CheckDlgButton(hwndDlg, IDC_DATAPATHO, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "datapath:", 0)); + CheckDlgButton(hwndDlg, IDC_SHUTDOWN, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "Shutdown", 0)); + CheckDlgButton(hwndDlg, IDC_UNLOADOFFLINE, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UnloadOnOffline", 0)); + + CheckDlgButton(hwndDlg, IDC_CUSTOMCOMMAND, (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "UseCustomCommand", 0)); + SendDlgItemMessage(hwndDlg, IDC_COMMANDLINE, EM_SETLIMITTEXT, MAX_PATH-1, 0L); + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"CommandLine",&dbv)) + { + SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), dbv.pszVal); + DBFreeVariant(&dbv); + } + + SendDlgItemMessage(hwndDlg, IDC_DATAPATH, EM_SETLIMITTEXT, MAX_PATH-1, 0L); + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"datapath",&dbv)) + { + SetWindowTextA(GetDlgItem(hwndDlg, IDC_DATAPATH), dbv.pszVal); + DBFreeVariant(&dbv); + } + + for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) + EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + + // LoginUserName + if(!DBGetContactSettingWString(NULL,SKYPE_PROTONAME,"LoginUserName",&dbv)) + { + SetWindowTextW(GetDlgItem(hwndDlg, IDC_USERNAME), dbv.pwszVal); + DBFreeVariant(&dbv); + } + + // LoginPassword + if(!DBGetContactSettingWString(NULL,SKYPE_PROTONAME,"LoginPassword",&dbv)) + { + SetWindowTextW(GetDlgItem(hwndDlg, IDC_PASSWORD), dbv.pwszVal); + DBFreeVariant(&dbv); + } + + SendDlgItemMessage(hwndDlg, IDC_CONNATTEMPTS, EM_SETLIMITTEXT, 3, 0L); + SetDlgItemInt (hwndDlg, IDC_CONNATTEMPTS, DBGetContactSettingWord(NULL, SKYPE_PROTONAME, "ConnectionAttempts", 10), FALSE); + SendMessage(hwndDlg, WM_COMMAND, IDC_STARTSKYPE, 0); + initDlg=FALSE; + return TRUE; + } + case WM_NOTIFY: { + NMHDR* nmhdr = (NMHDR*)lParam; + + switch (nmhdr->code){ + case PSN_APPLY: + case PSN_KILLACTIVE: + { + char text[500]; + WCHAR wtext[500]; + char szRelativePath[MAX_PATH]; + + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "StartSkype", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "nosplash", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOSPLASH), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "minimized", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_MINIMIZED), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "notray", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_NOTRAY), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "Shutdown", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SHUTDOWN), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UnloadOnOffline", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_UNLOADOFFLINE), BM_GETCHECK,0,0))); + DBWriteContactSettingWord (NULL, SKYPE_PROTONAME, "ConnectionAttempts", (unsigned short)GetDlgItemInt(hwndDlg, IDC_CONNATTEMPTS, NULL, FALSE)); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "UseCustomCommand", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "datapath:", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "removable", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_REMOVEABLE), BM_GETCHECK,0,0))); + DBWriteContactSettingByte (NULL, SKYPE_PROTONAME, "secondary", (BYTE)(SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY), BM_GETCHECK,0,0))); + + GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,text,sizeof(text)); + strncpy(szRelativePath, text, sizeof(szRelativePath)-1); + CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "CommandLine", szRelativePath); + + GetDlgItemTextA(hwndDlg,IDC_DATAPATH,text,sizeof(text)); + strncpy(szRelativePath, text, sizeof(szRelativePath)-1); + CallService (MS_UTILS_PATHTORELATIVE, (WPARAM)text, (LPARAM)szRelativePath); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "datapath", szRelativePath); + + // LoginUserName + GetDlgItemTextW(hwndDlg,IDC_USERNAME,wtext,sizeof(wtext)/sizeof(WCHAR)); + DBWriteContactSettingWString(NULL, SKYPE_PROTONAME, "LoginUserName", wtext); + + // LoginPassword + GetDlgItemTextW(hwndDlg,IDC_PASSWORD,wtext,sizeof(wtext)/sizeof(WCHAR)); + DBWriteContactSettingWString(NULL, SKYPE_PROTONAME, "LoginPassword", wtext); + + return TRUE; + } + } + break; + } + case WM_COMMAND: { + switch (LOWORD(wParam)) { + BOOL startSkype; + int i; + case IDC_STARTSKYPE: + startSkype=SendMessage(GetDlgItem(hwndDlg, IDC_STARTSKYPE), BM_GETCHECK,0,0); + + for(i=0; i < sizeof(skypeLaunchControls)/sizeof(skypeLaunchControls[0]); i++) + EnableWindow(GetDlgItem(hwndDlg, skypeLaunchControls[i]), startSkype); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), startSkype && SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + break; + case IDC_CLEANUP: + pthread_create(( pThreadFunc )CleanupNicknames, NULL); + break; + case IDC_DATAPATHO: + EnableWindow(GetDlgItem(hwndDlg, IDC_DATAPATH), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSEDP), SendMessage(GetDlgItem(hwndDlg, IDC_DATAPATHO), BM_GETCHECK,0,0)); + break; + case IDC_CUSTOMCOMMAND: + EnableWindow(GetDlgItem(hwndDlg, IDC_COMMANDLINE), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSECMDL), SendMessage(GetDlgItem(hwndDlg, IDC_CUSTOMCOMMAND), BM_GETCHECK,0,0)); + break; + case IDC_BROWSECMDL: + { + OPENFILENAMEA ofn={0}; + BOOL gofnResult; + char szFileName[MAX_PATH]; + char szAbsolutePath[MAX_PATH]; + + ofn.lStructSize=sizeof(ofn); + ofn.hwndOwner=hwndDlg; + ofn.lpstrFilter="Executable files (*.exe)\0*.exe\0All files (*.*)\0*.*\0"; + ofn.nMaxFile=sizeof(szFileName); + ofn.lpstrDefExt="exe"; + ofn.lpstrFile=szFileName; + ofn.Flags=OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLESIZING; + + GetDlgItemTextA(hwndDlg,IDC_COMMANDLINE,szFileName,sizeof(szFileName)); + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + strcpy (szFileName, szAbsolutePath); + + if (!(gofnResult = GetOpenFileNameA(&ofn)) && CommDlgExtendedError() == FNERR_INVALIDFILENAME){ + strcpy(szFileName, ".\\Skype.exe"); + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + strcpy (szFileName, szAbsolutePath); + gofnResult = GetOpenFileNameA(&ofn); + } + + if(gofnResult) + SetWindowTextA(GetDlgItem(hwndDlg, IDC_COMMANDLINE), szFileName); + + break; + } + case IDC_BROWSEDP: + { + BROWSEINFOA bi={0}; + LPITEMIDLIST pidl; + char szFileName[MAX_PATH]; + char szAbsolutePath[MAX_PATH]; + + GetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName, MAX_PATH); + + TranslateMirandaRelativePathToAbsolute(szFileName, szAbsolutePath, FALSE); + bi.hwndOwner = hwndDlg; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_SHAREABLE | BIF_NEWDIALOGSTYLE | BIF_NONEWFOLDERBUTTON; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)szAbsolutePath; + + if ( (pidl = SHBrowseForFolderA (&bi)) ) { + if (SHGetPathFromIDListA (pidl, szFileName)) + SetDlgItemTextA (hwndDlg, IDC_DATAPATH, szFileName); + CoTaskMemFree (pidl); + } + break; + } + +#ifdef SKYPE_AUTO_DETECTION + case IDC_AUTODETECTION: + DoAutoDetect(hwndDlg); + break; +#endif + } + if (!initDlg) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// OnDetailsInit - initializes user info dialog pages. + +int OnDetailsInit( WPARAM wParam, LPARAM lParam ) +{ + OPTIONSDIALOGPAGE odp = {0}; + HANDLE hContact = ( HANDLE )lParam; + + odp.cbSize = sizeof(odp); + odp.hIcon = NULL; + odp.hInstance = hInst; + + if ( hContact == NULL ) { + + char szTitle[256]; + + if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 7, 0, 27) && !bIsImoproxy) + { + mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Avatar" )); + + odp.pfnDlgProc = AvatarDlgProc; + odp.position = 1900000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETAVATAR); + odp.pszTitle = szTitle; + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + + mir_snprintf( szTitle, sizeof( szTitle ), "%s %s", SKYPE_PROTONAME, Translate( "Details" )); + + odp.pfnDlgProc = DetailsDlgProc; + odp.position = 1900000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_SETDETAILS); + odp.pszTitle = szTitle; + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + + return 0; +} + +/*AvatarDlgProc +* +* For setting the skype avatar +* +*/ +INT_PTR CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static RECT r; + + UNREFERENCED_PARAMETER(lParam); + + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + hAvatar = NULL; + if(ServiceExists(MS_AV_GETMYAVATAR)){ + struct avatarCacheEntry *ace = (struct avatarCacheEntry *)CallService(MS_AV_GETMYAVATAR, 0,(LPARAM) SKYPE_PROTONAME); + if (ace!=NULL) { + hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )ace->szFilename); + if ( hAvatar != NULL ) + SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); + } + } + + + + return TRUE; + + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_SETAVATAR: + { + char szFileName[ MAX_PATH ]; + if ( EnterBitmapFileName( szFileName ) != ERROR_SUCCESS ) + return FALSE; + + hAvatar = ( HBITMAP )CallService( MS_UTILS_LOADBITMAP, 0, ( LPARAM )szFileName); + if ( hAvatar != NULL ){ + SendDlgItemMessage(hwndDlg, IDC_AVATAR, STM_SETIMAGE, IMAGE_BITMAP, (WPARAM)hAvatar ); + CallService(SKYPE_SETAVATAR, 0, ( LPARAM )szFileName); + } + break; + } + case IDC_DELETEAVATAR: + if ( hAvatar != NULL ) { + DeleteObject( hAvatar ); + hAvatar = NULL; + CallService(SKYPE_SETAVATAR, 0, 0); + } + DBDeleteContactSetting( NULL, SKYPE_PROTONAME, "AvatarFile" ); + InvalidateRect( hwndDlg, NULL, TRUE ); + break; + } } + break; + + case WM_DESTROY: + if ( hAvatar != NULL ) + DeleteObject( hAvatar ); + break; + } + + return 0; +} + +/*DetailsDlgProc +* +* For setting the skype infos +* +*/ +INT_PTR CALLBACK DetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int sexM = 0,sexF = 0, sex; + + UNREFERENCED_PARAMETER(lParam); + + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + ZeroMemory (&myProfile, sizeof(myProfile)); + SkypeProfile_Load(&myProfile); + if(SkypeInitialized) + SkypeProfile_LoadFromSkype(&myProfile); + + SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)_T("")); + sexM = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("MALE")); + sexF = SendDlgItemMessage(hwndDlg,IDC_SEX,CB_ADDSTRING,0,(LPARAM)TranslateT("FEMALE")); + + switch(myProfile.Sex) { + case 0x4D: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexM, 0); break; + case 0x46: SendDlgItemMessage(hwndDlg,IDC_SEX,CB_SETCURSEL, sexF, 0); break; + } + + SetDlgItemText(hwndDlg, IDC_FULLNAME, myProfile.FullName); + SetDlgItemTextA(hwndDlg, IDC_HOMEPAGE, myProfile.HomePage); + SetDlgItemTextA(hwndDlg, IDC_HOMEPHONE, myProfile.HomePhone); + SetDlgItemTextA(hwndDlg, IDC_OFFICEPHONE, myProfile.OfficePhone); + SetDlgItemText(hwndDlg, IDC_CITY, myProfile.City); + SetDlgItemText(hwndDlg, IDC_PROVINCE, myProfile.Province); + DateTime_SetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), GDT_VALID, &myProfile.Birthday); + return TRUE; + + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_SAVEDETAILS: + GetDlgItemText(hwndDlg,IDC_FULLNAME,myProfile.FullName,sizeof(myProfile.FullName)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_HOMEPAGE,myProfile.HomePage,sizeof(myProfile.HomePage)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_HOMEPHONE,myProfile.HomePhone,sizeof(myProfile.HomePhone)/sizeof(TCHAR)); + GetDlgItemTextA(hwndDlg,IDC_OFFICEPHONE,myProfile.OfficePhone,sizeof(myProfile.OfficePhone)/sizeof(TCHAR)); + GetDlgItemText(hwndDlg,IDC_CITY,myProfile.City,sizeof(myProfile.City)/sizeof(TCHAR)); + GetDlgItemText(hwndDlg,IDC_PROVINCE,myProfile.Province,sizeof(myProfile.Province)/sizeof(TCHAR)); + sex = SendMessage(GetDlgItem(hwndDlg,IDC_SEX),CB_GETCURSEL,0,0); + + myProfile.Sex = 0; + if(sex == sexF) myProfile.Sex = 0x46; else + if(sex == sexM) myProfile.Sex = 0x4D; + DateTime_GetSystemtime (GetDlgItem (hwndDlg, IDC_BIRTHDAY), &myProfile.Birthday); + + SkypeProfile_Save(&myProfile); + if(SkypeInitialized) + SkypeProfile_SaveToSkype(&myProfile); + break; + } + } + break; + + case WM_DESTROY: + if ( hAvatar != NULL ) + DeleteObject( hAvatar ); + break; + } + + return 0; +} + +#ifdef SKYPE_AUTO_DETECTION +/** + * DoAutoDetect + * @param dlg The default option dialog handle + */ +void DoAutoDetect(HWND dlg) +{ + char basePath[MAX_PATH]; + char fileName[MAX_PATH]; + char tmpUser[255]; + ezxml_t f1, acc; + + if (FAILED(SHGetFolderPath(dlg,CSIDL_APPDATA,NULL,0,basePath))) + { + OUTPUT("Error in retrieving appdata path!"); + return; + } + + strcat(basePath,"\\Skype\\"); + sprintf (fileName, "%s\\shared.xml", basePath); + + if (f1 = ezxml_parse_file(fileName)) + { + if (acc = ezxml_get(f1, "Lib", 0, "Account", 0, "Default", -1)) + { + if (GetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),tmpUser,sizeof(tmpUser))) + SetWindowTextA(GetDlgItem(dlg,IDC_USERNAME),acc->txt); + /* Can't find this stuff in current Skype verions?? + sprintf (fileName, "%s\\%s\\config.xml", basePath, acc->txt); + if ((acc = ezxml_get(f1, "UI", 0, "Messages", 0, "OpenWindowInCompactMode", -1)) && *acc->txt!='0') + { + ezxml_set_txt (acc, "0"); + // ezXML doesn't supprot saving yet + } + */ + } + ezxml_free(f1); + } + else + { + OUTPUT("Failed to open skypes configuration files!"); + return; + } +} +#endif diff --git a/protocols/Skype/skypeopt.h b/protocols/Skype/skypeopt.h new file mode 100644 index 0000000000..23aa7a5212 --- /dev/null +++ b/protocols/Skype/skypeopt.h @@ -0,0 +1,49 @@ +/* + * RegisterOptions + * + * This function tells Miranda to add the configuration section of this plugin in + * the Options-dialog. + */ +int RegisterOptions(WPARAM wParam, LPARAM lParam); +/* + * OptionsDlgProc + * + * This callback function is called, when the options dialog in Miranda is shown + * The function contains all necessary stuff to process the options in the dialog + * and store them in the database, when changed, and fill out the settings-dialog + * correctly according to the current settings + */ +INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +INT_PTR CALLBACK OptionsDefaultDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK OptionsAdvancedDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK OptionsProxyDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +INT_PTR CALLBACK OptPopupDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +/* +* Procedure to call when the option page is asked +* +*/ +int OnDetailsInit( WPARAM wParam, LPARAM lParam ); + +/* +* Dialog to change avatar in user details. +* +* +*/ +INT_PTR CALLBACK AvatarDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +/* +* Dialog to change infos in user details. +* +* +*/ +INT_PTR CALLBACK DetailsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +/* + * Helper functions + * + */ +void DoAutoDetect(HWND dlg); + +; \ No newline at end of file diff --git a/protocols/Skype/skypeprofile.c b/protocols/Skype/skypeprofile.c new file mode 100644 index 0000000000..3bf3c0b955 --- /dev/null +++ b/protocols/Skype/skypeprofile.c @@ -0,0 +1,145 @@ +#pragma warning (disable: 4706) // assignment within conditional expression + +#include "skypeprofile.h" +#include "skypeapi.h" +#include "utf8.h" + +extern char g_szProtoName[]; + +void SkypeProfile_Save(SkypeProfile *pstProf) +{ + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "Gender", pstProf->Sex); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "HomePhone", pstProf->HomePhone); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "OfficePhone", pstProf->OfficePhone); + DBWriteContactSettingString(NULL, SKYPE_PROTONAME, "HomePage", pstProf->HomePage); + DBWriteContactSettingTString(NULL, SKYPE_PROTONAME, "Nick", pstProf->FullName); + DBWriteContactSettingTString(NULL, SKYPE_PROTONAME, "City", pstProf->City); + DBWriteContactSettingTString(NULL, SKYPE_PROTONAME, "Province", pstProf->Province); + DBWriteContactSettingWord(NULL, SKYPE_PROTONAME, "BirthYear", (WORD)pstProf->Birthday.wYear); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "BirthMonth", (BYTE)pstProf->Birthday.wMonth); + DBWriteContactSettingByte(NULL, SKYPE_PROTONAME, "BirthDay", (BYTE)pstProf->Birthday.wDay); +} + +void SkypeProfile_Load(SkypeProfile *pstProf) +{ + DBVARIANT dbv; + + pstProf->Sex = (BYTE)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "Gender", 0); + pstProf->Birthday.wYear = (WORD)DBGetContactSettingWord(NULL, SKYPE_PROTONAME, "BirthYear", 1900); + pstProf->Birthday.wMonth = (WORD)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "BirthMonth", 01); + pstProf->Birthday.wDay = (WORD)DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "BirthDay", 01); + if(!DBGetContactSettingTString(NULL,SKYPE_PROTONAME,"Nick",&dbv)) + { + _tcsncpy (pstProf->FullName, dbv.ptszVal, sizeof(pstProf->FullName)/sizeof(TCHAR)); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"HomePage",&dbv)) + { + strncpy (pstProf->HomePage, dbv.pszVal, sizeof(pstProf->HomePage)); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(NULL,SKYPE_PROTONAME,"Province",&dbv)) + { + _tcsncpy (pstProf->Province, dbv.ptszVal, sizeof(pstProf->Province)/sizeof(TCHAR)); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(NULL,SKYPE_PROTONAME,"City",&dbv)) + { + _tcsncpy (pstProf->City, dbv.ptszVal, sizeof(pstProf->City)/sizeof(TCHAR)); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"OfficePhone",&dbv)) + { + strncpy (pstProf->OfficePhone, dbv.pszVal, sizeof(pstProf->OfficePhone)); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingString(NULL,SKYPE_PROTONAME,"HomePhone",&dbv)) + { + strncpy (pstProf->HomePhone, dbv.pszVal, sizeof(pstProf->HomePhone)); + DBFreeVariant(&dbv); + } +} + +static void LoadSaveSkype(SkypeProfile *pstProf, BOOL bSet) +{ +#pragma warning (push) +#pragma warning (disable: 4204) // nonstandard extension used : non-constant aggregate initializer +#define ENTRY(x,y) {x, pstProf->y, sizeof(pstProf->y)/sizeof(pstProf->y[0]), sizeof(pstProf->y[0])} + const struct { + char *pszSetting; + LPVOID lpDest; + int iSize; + char cType; + } astSettings[] = { + ENTRY("FULLNAME", FullName), + ENTRY("PHONE_HOME", HomePhone), + ENTRY("PHONE_OFFICE", OfficePhone), + ENTRY("HOMEPAGE", HomePage), + ENTRY("CITY", City), + ENTRY("PROVINCE", Province) + }; +#pragma warning (pop) +#undef ENTRY + char *ptr; + int i; + + if (bSet) { + char *pBuf, szBirthday[16]; + for (i=0; iSex) + { + case 0x4D: SkypeSetProfile ("SEX", "MALE"); break; + case 0x46: SkypeSetProfile ("SEX", "FEMALE"); break; + } + sprintf (szBirthday, "%04d%02d%02d", pstProf->Birthday.wYear, pstProf->Birthday.wMonth, pstProf->Birthday.wDay); + SkypeSetProfile ("BIRTHDAY", szBirthday); + } else { + for (i=0; iSex=0x4D; else + if (!_stricmp(ptr, "FEMALE")) pstProf->Sex=0x46; + free (ptr); + } + if (ptr=SkypeGetProfile("BIRTHDAY")) + { + if (*ptr != '0') + sscanf(ptr, "%04hd%02hd%02hd", &pstProf->Birthday.wYear, &pstProf->Birthday.wMonth, + &pstProf->Birthday.wDay); + free(ptr); + } + } +} + +void SkypeProfile_LoadFromSkype(SkypeProfile *pstProf) +{ + LoadSaveSkype (pstProf, FALSE); +} + +void SkypeProfile_SaveToSkype(SkypeProfile *pstProf) +{ + LoadSaveSkype (pstProf, TRUE); +} \ No newline at end of file diff --git a/protocols/Skype/skypeprofile.h b/protocols/Skype/skypeprofile.h new file mode 100644 index 0000000000..60531128d1 --- /dev/null +++ b/protocols/Skype/skypeprofile.h @@ -0,0 +1,33 @@ +// System includes +#include +#include +#include +#include +#include +#include "resource.h" +#include "skype.h" + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +// Miranda database access +#include "../../include/newpluginapi.h" +#include "../../include/m_database.h" +#pragma warning (pop) + +typedef struct +{ + TCHAR FullName[256]; + char HomePhone[256]; + char OfficePhone[256]; + char HomePage[256]; + TCHAR City[256]; + TCHAR Province[256]; + BYTE Sex; + SYSTEMTIME Birthday; +} SkypeProfile; + +void SkypeProfile_Load(SkypeProfile *pstProf); +void SkypeProfile_Save(SkypeProfile *pstProf); +void SkypeProfile_Free(SkypeProfile *pstProf); +void SkypeProfile_LoadFromSkype(SkypeProfile *pstProf); +void SkypeProfile_SaveToSkype(SkypeProfile *pstProf); diff --git a/protocols/Skype/skypeproxy.h b/protocols/Skype/skypeproxy.h new file mode 100644 index 0000000000..8e1490803e --- /dev/null +++ b/protocols/Skype/skypeproxy.h @@ -0,0 +1,7 @@ +/* Commands for command mode of Skype proxy */ + +#define AUTHENTICATE 0x01 +#define CAPABILITIES 0x02 + +/* Capabilities flags of Skypeproxy */ +#define USE_AUTHENTICATION 0x01 \ No newline at end of file diff --git a/protocols/Skype/skypeproxy/skypeproxy.c b/protocols/Skype/skypeproxy/skypeproxy.c new file mode 100644 index 0000000000..fff9c1b916 --- /dev/null +++ b/protocols/Skype/skypeproxy/skypeproxy.c @@ -0,0 +1,651 @@ +/* + +Purpose +======= +This program opens a connection on a local TCP/IP port and sends/ +receives Skype-API calls on it so that you can remote-control +Skype over a network. +Note, that there are currently NO SECURITY mechanisms, so don't +use this over an untrusted network! + +Author +====== +This program was written by leecher in 2005 (mailto:leecher@dose.0wnz.at) +Please give feedback at http://forum.skype.com/viewtopic.php?t=16187 + +Protocol +======== +Basic protocol structure +------------------------ +Sender and receiver have the same protocol: + + [(UINT)Length of message][(char[])Message] + +The Length is so that you can malloc() enough space for the data buffer +to receive the next message. + +A special case is, if the [Length of message] is 0. In this case the +client tells the server that he wants to switch to command mode. + +Command mode +------------ +The server expects + + [(char)Command] + +next. Currently the following commands are supported: + + CAPABILITIES - returns the Server's capabilities + AUTHENTICATE - Starts the authentification process + +CAPABILITIES +------------ +The server returns + + [(char)Capabilities] + +where this currently can be the following: + + USE_AUTHENTICATION - The server supports and requires authentication + +AUTHENTICATE +------------ +The server returns + + [(char)0x01] + +if authentication is supported AND needed (skypeproxy started with -k switch) or + + [(char)0x00] + +if this is not the case. +If 0x01 was returned the server next expects a normal message +(see "Basic protocol structure) containing the password. +If the authentication was successful, the server replies with + + [(char)0x01] + +otherwise with + + [(char)0x00] + +PLEASE NOTE THAT THE AUTHENTICATION CURRENTLY IS PLAIN TEXT. SO DON'T +USE THIS PROGRAM OVER AN UNTRUSTED NETWORK, OTHERWISE THERE MAY BE THE +POSSIBILITY THAT SOMEONE SNIFFS YOUR PASSWORD! + +Code example +------------ + +SOCKET MySocket; + +int SendPacket(char *szSkypeMessage) { + unsigned int length=strlen(szSkypeMsg); + + if (send(MySocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR || + send(MySocket, szSkypeMsg, length, 0)==SOCKET_ERROR) + return -1; + return 0; +} + +// don't forget to free() the return value on my Heap!! +char *ReceivePacket(void) { + unsigned int lenght, received; + char *buf; + + if ((received=recv(MySocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || + received==0) + return NULL; + if (!(buf=calloc(1, length+1))) return NULL; + if (recv(MySocket, buf, length, 0)==SOCKET_ERROR) { + free(buf); + return NULL; + } + return buf; +} + + +License +======= +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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +History +======== +V1.0alpha - First preview release +V1.0 - Implemented killing & restarting Skype process when it dies + - BUGFIX: SendMessage() is a blocking call, if Skype hangs our app hangs too -> Fixed + - Added command line parsing. + - Renamed from Skype2Socket to skypeproxy + - Added authentication feature. +*/ + +#include +#include +#include +#include +#include "skypeproxy.h" + +UINT ControlAPIAttach, ControlAPIDiscover; +HWND hSkypeWnd=NULL, hWnd; +HANDLE SkypeReady, ServerThreadBye; +LONG AttachStatus=-1; +int exitcode=EXIT_SUCCESS; +char skype_path[MAX_PATH], *password=NULL; +BYTE WatchDog=1; +BOOL WatchDogRunning=FALSE, Authenticated=FALSE; +SOCKET ListenSocket, AcceptSocket; + + +void bail_out(int i) { + OUTPUT("Got termination signal, bailing out."); + if (i==1) exitcode=EXIT_FAILURE; + PostMessage(hWnd, WM_QUIT, 0, 0); +} + +BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) { + DWORD dwID ; + + GetWindowThreadProcessId(hwnd, &dwID) ; + if(dwID == (DWORD)lParam) + PostMessage(hwnd, WM_CLOSE, 0, 0) ; // May you be so kind to quit, please? + + return TRUE ; +} + +/* ConnectToSkypeAPI + * + * Purpose: Establish a connection to the Skype API + * Params : ForceRestart - Kill Skype if it's running before restarting + * Returns: 0 - Connecting succeeded + * -1 - Something went wrong + */ +void ConnectToSkypeAPI(void *ForceRestart) { + BOOL SkypeLaunched=FALSE; + int counter=0, i, j; + char *args[5]; + char *SkypeOptions[]={"/notray", "/nosplash", "/minimized"}; + char *szFuncName="ConnectToSkypeAPI"; + + ResetEvent(SkypeReady); + AttachStatus=-1; + if ((BOOL)ForceRestart) { + HANDLE hProc; + DWORD dwPID=0; + + if (!hSkypeWnd) { + OUTPUT("I can't kill Skype, as I don't even have its window handle!"); + return; + } + GetWindowThreadProcessId(hSkypeWnd, &dwPID); + LOG(("%s: Shutting down Skype as it was not behaving the way it should...", szFuncName)); + if (hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID)) { + + // Try to shutdown Skype the nice way by asking it to close + EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID); + + if(WaitForSingleObject(hProc, 10000)!=WAIT_OBJECT_0) { + // Try it the hard way by killing it + LOG(("%s: I tried it the nice way, but you were not listening! Now DIIIIEEE!", szFuncName)); + if (!TerminateProcess(hProc,0)) { + OUTPUT("Argh, process refused to die, it's too mighty for me, I've given up"); + CloseHandle(hProc); + return; + } + LOG(("%s: Process killed! >:)", szFuncName)); + } + CloseHandle(hProc); + } + } + do { + /* To initiate communication, Client should broadcast windows message + ('SkypeControlAPIDiscover') to all windows in the system, specifying its own + window handle in wParam parameter. + */ + LOG(("%s: Sending discover message..", szFuncName)); + SendMessageTimeout(HWND_BROADCAST, ControlAPIDiscover, (WPARAM)hWnd, 0, SMTO_ABORTIFHUNG, 3000, NULL); + LOG(("%s: Discover message sent, waiting for Skype to become ready..", szFuncName)); + + /* In response, Skype responds with + message 'SkypeControlAPIAttach' to the handle specified, and indicates + connection status + SkypeReady is set if there is an answer by Skype other than API_AVAILABLE. + If there is no answer after 3 seconds, launch Skype as it's propably + not running. + */ + if (WaitForSingleObject(SkypeReady, 3000)==WAIT_TIMEOUT && + AttachStatus!=SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION) + { + if (hWnd==NULL) { + LOG(("%s: hWnd of SkypeDispatchWindow not yet set..", szFuncName)); + continue; + } + if (!SkypeLaunched && skype_path) { + LOG(("%s: Starting Skype, as it's not running", szFuncName)); + args[0]=skype_path; + j=1; + for (i=0; i<3; i++) { + args[j]=SkypeOptions[i]; + LOG(("%s: Using Skype parameter: ", szFuncName, args[j])); + j++; + } + args[j]=NULL; + _spawnv(_P_NOWAIT, skype_path, args); + ResetEvent(SkypeReady); + SkypeLaunched=TRUE; + LOG(("%s: Skype process started.", szFuncName)); + // Skype launching iniciated, keep sending Discover messages until it responds. + continue; + } else { + LOG(("%s: Check if Skype was launchable..", szFuncName)); + if (!skype_path) { + OUTPUT("There was no correct path for Skype application"); + bail_out(1); + return; + } + LOG("%s: Trying to attach: #%d", szFuncName, counter)); + counter++; + if (counter==5) { + OUTPUT("ERROR: Skype not running / too old / working!"); + bail_out(1); + return; + } + } + } + LOG(("%s: Attachstatus %d", szFuncName, AttachStatus)); + } while (AttachStatus==SKYPECONTROLAPI_ATTACH_API_AVAILABLE || AttachStatus==-1); + + while (AttachStatus==SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION) Sleep(1000); + LOG(("%s: Attachstatus %d", szFuncName, AttachStatus)); + if (AttachStatus!=SKYPECONTROLAPI_ATTACH_SUCCESS) { + switch(AttachStatus) { + case SKYPECONTROLAPI_ATTACH_REFUSED: + OUTPUT("Skype refused the connection :("); + break; + case SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE: + OUTPUT("The Skype API is not available"); + break; + default: + LOG(("%s: ERROR: AttachStatus: %d", szFuncName, AttachStatus)); + OUTPUT("Wheee, Skype won't let me use the API. :("); + } + bail_out(1); + return; + } + OUTPUT("Attached to Skype successfully."); + if (!WatchDogRunning) + if (_beginthread(WatchDogTimer, 0, NULL)==-1) { + OUTPUT("Cannot start Watchdog."); + bail_out(1); + } + return; +} + +void SkypeSend(char *szMsg) { + COPYDATASTRUCT CopyData; + int count=0; + + if (!hSkypeWnd) { + LOG(("SkypeSend: DAMN! No Skype window handle! :(")); + return; + } + if (strcmp(szMsg, "PING")) {LOG(("> %s", szMsg));} + CopyData.dwData=0; + CopyData.lpData=szMsg; + CopyData.cbData=strlen(szMsg)+1; + while (!SendMessageTimeout(hSkypeWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&CopyData, SMTO_ABORTIFHUNG, 3000, NULL)) { + count++; + LOG(("SkypeSend: failed, try #%d", count)); + if (count==5) { + OUTPUT("Sending message to Skype failed too often."); + OUTPUT("Skype may have died unexpectedly, I will try to restart it."); + ConnectToSkypeAPI((void *)TRUE); + OUTPUT("Restart complete. Trying to deliver message one more time."); + if (!SendMessageTimeout(hSkypeWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&CopyData, SMTO_ABORTIFHUNG, 3000, NULL)) { + OUTPUT("It still failed. Skype seems to be completely f*cked up. I've given up. Bye.."); + bail_out(1); + break; + } else { + OUTPUT("Now it worked! :)"); + break; + } + } + Sleep(1000); + } +} + +void ServerThread(char *dummy) { + unsigned int length, received; + char *buf, command, reply; + + LOG(("ServerThread started")); + AcceptSocket=INVALID_SOCKET; + while( AcceptSocket == INVALID_SOCKET) { + if ((AcceptSocket = accept( ListenSocket, NULL, NULL ))==INVALID_SOCKET) { + LOG(("ServerThread: Byebye...")); + SetEvent(ServerThreadBye); + bail_out(1); + return; + } + OUTPUT("Connection by client"); + while(1) { + if ((received=recv(AcceptSocket, (char *)&length, sizeof(length), 0))==SOCKET_ERROR || + received==0) + { + OUTPUT("Connection was closed by client. See ya soon! :)"); + break; + } + // Command mode + if (length==0) { + reply=0; + if (recv(AcceptSocket, (char *)&command, 1, 0)==SOCKET_ERROR) { + OUTPUT("Connection to client was lost."); + break; + } +#ifdef USE_AUTHENTICATION + if (command==AUTHENTICATE) + if (password) reply=0x01; // Ok, go ahead + else command=0; +#endif + if (command==CAPABILITIES) + reply=password?USE_AUTHENTICATION:0; + + if (send(AcceptSocket, (char *)&reply, 1, 0)==SOCKET_ERROR) { + OUTPUT("Connection to client was lost."); + break; + } + continue; + } + // Normal Skype API-call + if (!(buf=calloc(1, length+1))) { + OUTPUT("Out of memory error while allocating buffer space."); + break; + } + if (recv(AcceptSocket, buf, length, 0)==SOCKET_ERROR) { + OUTPUT("Connection to client was lost."); + free(buf); + break; + } + switch (command) { +#ifdef USE_AUTHENTICATION + case 0x01: // Compare hash + if (password && !strcmp(password, buf)) Authenticated=TRUE; + else Authenticated=FALSE; + if (Authenticated) { + OUTPUT("User authenticated succesfully."); + reply=1; + } else { + OUTPUT("User authentication failed!! (Intruder?)"); + reply=0; + } + if (send(AcceptSocket, (char *)&reply, 1, 0)==SOCKET_ERROR) { + OUTPUT("Connection to client was lost."); + break; + } + command=0; + break; +#endif + default: +#ifdef USE_AUTHENTICATION + if (password && !Authenticated) break; +#endif + SkypeSend(buf); + } + command=0; + free(buf); + } + AcceptSocket=INVALID_SOCKET; +#ifdef USE_AUTHENTICATION + Authenticated=FALSE; +#endif + } +} + + +void WatchDogTimer(char *dummy) { + LOG(("WatchDogTimer started")); + WatchDogRunning=TRUE; + while (1) { + Sleep(PING_INTERVAL); + if (!WatchDog) { + OUTPUT("Ouch.. It seems that Skype has died unexpectedly. Trying to restart."); + ConnectToSkypeAPI((void *)TRUE); + } + WatchDog=0; + SkypeSend("PING"); + } +} + +LONG APIENTRY WndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) +{ + PCOPYDATASTRUCT CopyData; + char *szSkypeMsg=NULL; + + switch (message) + { + case WM_COPYDATA: +// LOG("WM_COPYDATA", "start"); + if(hSkypeWnd==(HWND)wParam) { + CopyData=(PCOPYDATASTRUCT)lParam; + szSkypeMsg=strdup(CopyData->lpData); + ReplyMessage(1); + if (!strcmp(szSkypeMsg, "PONG")) { + WatchDog=1; + break; + } // Hide PING-PONG + LOG(("< %s", szSkypeMsg)); + if (!strcmp(szSkypeMsg, "USERSTATUS LOGGEDOUT")) { + OUTPUT("Skype shut down gracefully. I'll leave too, bye.. :)"); + bail_out(1); + } +#ifdef USE_AUTHENTICATION + if (password && !Authenticated) break; +#endif + if (AcceptSocket!=INVALID_SOCKET) { + unsigned int length=strlen(szSkypeMsg); + + if (send(AcceptSocket, (char *)&length, sizeof(length), 0)==SOCKET_ERROR || + send(AcceptSocket, szSkypeMsg, length, 0)==SOCKET_ERROR) + OUTPUT("Cannot send to client :("); + } + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + if(message==ControlAPIAttach) { + // Skype responds with Attach to the discover-message + AttachStatus=lParam; + if (AttachStatus==SKYPECONTROLAPI_ATTACH_SUCCESS) + hSkypeWnd=(HWND)wParam; // Skype gave us the communication window handle + if (AttachStatus!=SKYPECONTROLAPI_ATTACH_API_AVAILABLE) + SetEvent(SkypeReady); + break; + } + return (DefWindowProc(hWnd, message, wParam, lParam)); + } +// LOG("WM_COPYDATA", "exit"); + if (szSkypeMsg) free(szSkypeMsg); + return 1; +} + + +void TellError(DWORD err) { + LPVOID lpMsgBuf; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION ); + LocalFree( lpMsgBuf ); + return; +} + +int main(int argc, char *argv[]) { + DWORD Buffsize; + HKEY MyKey; + BOOL SkypeInstalled=TRUE; + MSG Message; + WNDCLASS WndClass; + SOCKADDR_IN service; + WSADATA wsaData; + int ExitCode=STILL_ACTIVE; + unsigned short BindPort=1401; + char BindIP[16]="0.0.0.0"; + + printf("Skypeproxy V1.0, by leecher 2005 \n\n"); + + if (argc>1) { + int i; + + if (!stricmp(argv[1], "-h") || !stricmp(argv[1], "--help") || !stricmp(argv[1], "/?")) { + printf("Usage: %s [-i BindIP] [-p BindPort]", argv[0]); +#ifdef USE_AUTHENTICATION + printf(" [-k Password]"); +#endif + printf("\n\n"); + return EXIT_SUCCESS; + } + for (i=0;ii+1) + strncpy(BindIP, argv[i+1], sizeof(BindIP)); + if (!stricmp(argv[i], "-p") && argc>i+1) + if (!(BindPort=atoi(argv[i+1]))) { + OUTPUT("ERROR: Cannot convert port to int. bye.."); + return EXIT_FAILURE; + } +#ifdef USE_AUTHENTICATION + if (!stricmp(argv[i], "-k") && argc>i+1) + password=strdup(argv[i+1]); +#endif + } + } + + if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Skype\\Phone", 0, KEY_READ, &MyKey)!=ERROR_SUCCESS || + RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Skype\\Phone", 0, KEY_READ, &MyKey)!=ERROR_SUCCESS) + SkypeInstalled=FALSE; + Buffsize=sizeof(skype_path); + if (SkypeInstalled==FALSE || + RegQueryValueEx(MyKey, "SkypePath", NULL, NULL, skype_path, &Buffsize)!=ERROR_SUCCESS) { + OUTPUT("Skype was not found on this machine :("); + RegCloseKey(MyKey); + skype_path[0]=0; + return EXIT_FAILURE; + } + RegCloseKey(MyKey); + + if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + OUTPUT("Error at loading windows sockets."); + return EXIT_FAILURE; + } + + if ((ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { + printf("* Error at creating socket(): Error %d", WSAGetLastError()); + return EXIT_FAILURE; + } + + service.sin_family = AF_INET; + service.sin_addr.s_addr = inet_addr(BindIP); + service.sin_port = htons(BindPort); + + printf("* Binding to interface %s, Port %d..", BindIP, BindPort); + if (bind( ListenSocket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR || + listen( ListenSocket, 1 ) == SOCKET_ERROR) + { + OUTPUT("Failed."); + closesocket(ListenSocket); + return EXIT_FAILURE; + } + printf("OK\n"); + + + if (!(ControlAPIAttach=RegisterWindowMessage("SkypeControlAPIAttach")) || + !(ControlAPIDiscover=RegisterWindowMessage("SkypeControlAPIDiscover"))) { + OUTPUT("Cannot register Windows message."); + closesocket(ListenSocket); + return EXIT_FAILURE; + } + + // Create window class + hSkypeWnd=NULL; + WndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; + WndClass.lpfnWndProc = (WNDPROC)WndProc; + WndClass.cbClsExtra = 0; + WndClass.cbWndExtra = 0; + WndClass.hInstance = NULL; + WndClass.hIcon = NULL; + WndClass.hCursor = NULL; + WndClass.hbrBackground = NULL; + WndClass.lpszMenuName = NULL; + WndClass.lpszClassName = "SkypeApiDispatchWindow"; + RegisterClass(&WndClass); + // Do not check the retval of RegisterClass, because on non-unicode + // win98 it will fail, as it is a stub that returns false() there + + // Create main window + hWnd=CreateWindowEx( WS_EX_APPWINDOW|WS_EX_WINDOWEDGE, + "SkypeApiDispatchWindow", "", WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX, + CW_USEDEFAULT, CW_USEDEFAULT, 128, 128, NULL, 0, (HINSTANCE)WndClass.hInstance, 0); + + if (!hWnd) { + OUTPUT("Cannot create window."); + TellError(GetLastError()); + closesocket(ListenSocket); + CloseHandle(WndClass.hInstance); + return EXIT_FAILURE; + } + ShowWindow(hWnd, 0); + UpdateWindow(hWnd); + + if (!(SkypeReady=CreateEvent(NULL, TRUE, FALSE, NULL)) || + !(ServerThreadBye=CreateEvent(NULL, TRUE, FALSE, NULL))) { + OUTPUT("Unable to create Mutex!"); + closesocket(ListenSocket); + CloseHandle(WndClass.hInstance); + return EXIT_FAILURE; + } + + if (_beginthread(ConnectToSkypeAPI, 0, (void *)FALSE)==-1 || + _beginthread(ServerThread, 0, NULL)==-1) { + OUTPUT("Cannot create thread. Bye.."); + closesocket(ListenSocket); + CloseHandle(WndClass.hInstance); + CloseHandle(SkypeReady); + return EXIT_FAILURE; + } + + signal(SIGINT, &bail_out); + LOG(("Startup: Messagepump started.\nPress CTRL+C to terminate\n")); + + while (GetMessage(&Message, hWnd, 0, 0)) + { + TranslateMessage(&Message); + DispatchMessage(&Message); + } + + LOG(("Shutdown: Messagepump stopped")); + + if (password) free(password); + if (AcceptSocket != INVALID_SOCKET) closesocket(AcceptSocket); + closesocket(ListenSocket); + LOG(("Shutdown: Waiting for serverthread to quit...")); + if (WaitForSingleObject(ServerThreadBye, 3000)==WAIT_TIMEOUT) + {OUTPUT("Serverthread didn't terminate correctly, shutting down anyway...");} + else + {LOG(("ServerThread terminated"));} + CloseHandle(WndClass.hInstance); + CloseHandle(SkypeReady); + return exitcode; +} \ No newline at end of file diff --git a/protocols/Skype/skypeproxy/skypeproxy.h b/protocols/Skype/skypeproxy/skypeproxy.h new file mode 100644 index 0000000000..8ce122990b --- /dev/null +++ b/protocols/Skype/skypeproxy/skypeproxy.h @@ -0,0 +1,36 @@ +/*** Skype API ***/ +//Messages +#define SKYPECONTROLAPI_ATTACH_SUCCESS 0 +#define SKYPECONTROLAPI_ATTACH_PENDING_AUTHORIZATION 1 +#define SKYPECONTROLAPI_ATTACH_REFUSED 2 +#define SKYPECONTROLAPI_ATTACH_NOT_AVAILABLE 3 +#define SKYPECONTROLAPI_ATTACH_API_AVAILABLE 0x8001 + +// Errors +#define MISC_ERROR 1 +#define USER_NOT_FOUND 2 +#define USER_NOT_ONLINE 3 +#define USER_BLOCKED 4 +#define TYPE_UNSUPPORTED 5 +#define SENDER_NOT_FRIEND 6 +#define SENDER_NOT_AUTHORIZED 7 + + +/*** Debugging macros ***/ +#define OUTPUT(a) printf("* %s\n", a); +#define LOG(a, b) printf("- %s: %s\n", a, b); +#define LOGL(a, b) printf("- %s: %d\n", a, b); + +/*** Program settings ***/ +#define PING_INTERVAL 10000 // Ping every 10000 msec to see if Skype is still available +#define USE_AUTHENTICATION 0x01 // Program supports authentication -> Comment to disable! + +/*** Commands ***/ +#define AUTHENTICATE 0x01 +#define CAPABILITIES 0x02 + +/*** Sockets ***/ +#pragma comment(lib, "ws2_32") + +/*** Prototypes ***/ +void WatchDogTimer(char *); \ No newline at end of file diff --git a/protocols/Skype/skypesvc.c b/protocols/Skype/skypesvc.c new file mode 100644 index 0000000000..c6d02e6d3a --- /dev/null +++ b/protocols/Skype/skypesvc.c @@ -0,0 +1,188 @@ +#define __SKYPESVC_C__ +#include "skype.h" +#include "skypesvc.h" +#include "skypeapi.h" +#include "skypeopt.h" +#include "contacts.h" +#include "m_toptoolbar.h" + +// Exports +SKYPE_SVCNAMES g_svcNames; + +//From skype.c +extern char protocol, g_szProtoName[]; +extern HINSTANCE hInst; +extern DWORD mirandaVersion; +static HANDLE m_hPrebuildCMenu=NULL, m_hStatusHookContact=NULL, m_hContactDeleted=NULL, + m_hHookModulesLoaded=NULL, m_hHookOkToExit=NULL, m_hOptHook=NULL, m_hHookMirandaExit=NULL, + m_hTTBModuleLoadedHook = NULL, m_hHookOnUserInfoInit = NULL; + +void CreateProtoService(const char* szService, MIRANDASERVICE svc) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", SKYPE_PROTONAME, szService); + CreateServiceFunction(str, svc); +} + +#define CreateServiceName(srvce) _snprintf (g_svcNames.##srvce, sizeof(g_svcNames.##srvce), "%s/"#srvce, SKYPE_PROTONAME); + +void CreateServices(void) +{ + CreateServiceName(ChatNew); + CreateServiceName(SetAvatar); + CreateServiceName(SendFile); + CreateServiceName(HoldCall); + CreateServiceName(AnswerCall); + CreateServiceName(ImportHistory); + CreateServiceName(AddUser); + CreateServiceName(SkypeOutCallUser); + CreateServiceName(CallHangupUser); + CreateServiceName(CallUser); + + CreateServiceFunction(SKYPE_CALL, SkypeCall); + CreateServiceFunction(SKYPE_CALLHANGUP, SkypeCallHangup); + CreateServiceFunction(SKYPEOUT_CALL, SkypeOutCall); + CreateServiceFunction(SKYPE_HOLDCALL, SkypeHoldCall); + CreateServiceFunction(SKYPE_ADDUSER, SkypeAdduserDlg); + CreateServiceFunction(SKYPE_IMPORTHISTORY, ImportHistory); + CreateServiceFunction(SKYPE_ANSWERCALL, SkypeAnswerCall); + CreateServiceFunction(SKYPE_SENDFILE, SkypeSendFile); + CreateServiceFunction(SKYPE_SETAVATAR, SkypeSetAvatar); + + CreateProtoService(PS_GETCAPS, SkypeGetCaps); + CreateProtoService(PS_GETNAME, SkypeGetName); + CreateProtoService(PS_LOADICON, SkypeLoadIcon); + CreateProtoService(PS_SETSTATUS, SkypeSetStatus); + CreateProtoService(PS_GETSTATUS, SkypeGetStatus); + CreateProtoService(PS_ADDTOLIST, SkypeAddToList); + CreateProtoService(PS_ADDTOLISTBYEVENT, SkypeAddToListByEvent); + CreateProtoService(PS_BASICSEARCH, SkypeBasicSearch); + + CreateProtoService(PSS_GETINFO, SkypeGetInfo); + CreateProtoService(PSS_MESSAGE, SkypeSendMessage); + CreateProtoService(PSR_MESSAGE, SkypeRecvMessage); + CreateProtoService(PSS_USERISTYPING, SkypeUserIsTyping); + CreateProtoService(PSS_AUTHREQUEST, SkypeSendAuthRequest); + CreateProtoService(PSR_AUTH, SkypeRecvAuth); + CreateProtoService(PS_AUTHALLOW, SkypeAuthAllow); + CreateProtoService(PS_AUTHDENY, SkypeAuthDeny); + + CreateProtoService(PS_GETAVATARINFO, SkypeGetAvatarInfo); + CreateProtoService(PS_GETAVATARCAPS, SkypeGetAvatarCaps); + CreateProtoService(PS_GETMYAVATAR, SkypeGetAvatar); + CreateProtoService(PS_SETMYAVATAR, SkypeSetAvatar); + + CreateProtoService(PS_SETAWAYMSG, SkypeSetAwayMessage); + CreateProtoService(PS_SETAWAYMSGW, SkypeSetAwayMessageW); + CreateProtoService(PSS_GETAWAYMSG, SkypeGetAwayMessage); + CreateProtoService(PS_SETMYNICKNAME, SkypeSetNick); + + CreateProtoService(PSS_SKYPEAPIMSG, SkypeReceivedAPIMessage); + CreateProtoService(SKYPE_REGPROXY, SkypeRegisterProxy); +} + +void HookEvents(void) +{ + m_hPrebuildCMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); + + //HookEvent(ME_CLIST_DOUBLECLICKED, ClistDblClick); + m_hOptHook = HookEvent(ME_OPT_INITIALISE, RegisterOptions); + m_hStatusHookContact = HookEvent(ME_DB_CONTACT_ADDED,HookContactAdded); + m_hContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, HookContactDeleted ); + m_hHookModulesLoaded = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + m_hHookMirandaExit = HookEvent(ME_SYSTEM_OKTOEXIT, MirandaExit); + m_hHookOkToExit = HookEvent(ME_SYSTEM_PRESHUTDOWN, OkToExit); +} + +void HookEventsLoaded(void) +{ + // We cannot check for the TTB-service before this event gets fired... :-/ + m_hTTBModuleLoadedHook = HookEvent(ME_TTB_MODULELOADED, CreateTopToolbarButton); + m_hHookOnUserInfoInit = HookEvent( ME_USERINFO_INITIALISE, OnDetailsInit ); +} + +void UnhookEvents(void) +{ + UnhookEvent(m_hOptHook); + UnhookEvent(m_hTTBModuleLoadedHook); + UnhookEvent(m_hHookOnUserInfoInit); + UnhookEvent(m_hStatusHookContact); + UnhookEvent(m_hContactDeleted); + UnhookEvent(m_hHookModulesLoaded); + UnhookEvent(m_hPrebuildCMenu); + UnhookEvent(m_hHookOkToExit); + UnhookEvent(m_hHookMirandaExit); + //UnhookEvent(ClistDblClick); +} + +INT_PTR SkypeGetCaps(WPARAM wParam, LPARAM lParam) { + int ret = 0; + + UNREFERENCED_PARAMETER(lParam); + + switch (wParam) { + case PFLAGNUM_1: + ret = PF1_BASICSEARCH | PF1_IM | PF1_MODEMSG; // | PF1_AUTHREQ; + if (protocol>=5) ret |= PF1_ADDSEARCHRES; + break; + + case PFLAGNUM_2: + ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE | PF2_HEAVYDND; +#ifdef MAPDND + ret |= PF2_LIGHTDND | PF2_HEAVYDND; +#endif + if (!DBGetContactSettingByte(NULL, SKYPE_PROTONAME, "NoSkype3Stats", 0)) + ret |= PF2_LONGAWAY | PF2_FREECHAT; + break; + + case PFLAGNUM_3: + ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE; + break; + + case PFLAGNUM_4: + ret = PF4_FORCEAUTH | PF4_FORCEADDED | PF4_AVATARS | PF4_SUPPORTTYPING /* Not really, but libgaim compat. */; + if (mirandaVersion >= 0x070000) ret |= PF4_IMSENDUTF; + break; + case PFLAG_UNIQUEIDTEXT: + ret = (INT_PTR) "NAME"; + break; + case PFLAG_UNIQUEIDSETTING: + ret = (INT_PTR) SKYPE_NAME; + break; + } + return ret; + +} + +INT_PTR SkypeGetName(WPARAM wParam, LPARAM lParam) +{ + if (lParam) + { + strncpy((char *)lParam, SKYPE_PROTONAME, wParam); + return 0; // Success + } + return 1; // Failure +} + + +INT_PTR SkypeLoadIcon(WPARAM wParam,LPARAM lParam) +{ + UINT id; + + UNREFERENCED_PARAMETER(lParam); + + switch(wParam&0xFFFF) { + case PLI_PROTOCOL: id=IDI_SKYPE; break; // IDI_MAIN is the main icon for the protocol + default: return (int)(HICON)NULL; + } + return (int)LoadImage(hInst,MAKEINTRESOURCE(id),IMAGE_ICON,GetSystemMetrics(wParam&PLIF_SMALL?SM_CXSMICON:SM_CXICON),GetSystemMetrics(wParam&PLIF_SMALL?SM_CYSMICON:SM_CYICON),0); +} + +INT_PTR SkypeGetAvatar(WPARAM wParam,LPARAM lParam) +{ DBVARIANT dbv; + if (!DBGetContactSettingString(NULL,SKYPE_PROTONAME, "AvatarFile", &dbv)){ + lstrcpynA((char*)wParam, dbv.pszVal, (int)lParam); + DBFreeVariant(&dbv); + } + return 0; +} diff --git a/protocols/Skype/skypesvc.h b/protocols/Skype/skypesvc.h new file mode 100644 index 0000000000..74c8cd37bf --- /dev/null +++ b/protocols/Skype/skypesvc.h @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include "resource.h" + +void CreateProtoService(const char* szService, MIRANDASERVICE svc); +void HookEvents(void); +void HookEventsLoaded(void); +void UnhookEvents(void); +void CreateServices(void); +INT_PTR SkypeLoadIcon(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeGetName(WPARAM wParam, LPARAM lParam); +INT_PTR SkypeGetCaps(WPARAM wParam, LPARAM lParam); +/* SkypeGetAvatar + * + * Purpose: Return the avatar file name + * Params : wParam=0 + * lParam=0 + * Returns: 0 - Success + * -1 - Failure + */ +INT_PTR SkypeGetAvatar(WPARAM wParam,LPARAM lParam); \ No newline at end of file diff --git a/protocols/Skype/utf8.c b/protocols/Skype/utf8.c new file mode 100644 index 0000000000..8ae746e871 --- /dev/null +++ b/protocols/Skype/utf8.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2001 Peter Harris + * Copyright (C) 2001 Edmund Grimley Evans + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Convert a string between UTF-8 and the locale's charset. + */ + +#include +#include + +#include "utf8.h" + +#ifdef _WIN32 + + /* Thanks to Peter Harris for this win32 + * code. + */ + +#include +#include + +unsigned char *make_utf8_string(const wchar_t *unicode) +{ + int size = 0, index = 0, out_index = 0; + unsigned char *out; + unsigned short c; + + /* first calculate the size of the target string */ + c = unicode[index++]; + while(c) { + if(c < 0x0080) { + size += 1; + } else if(c < 0x0800) { + size += 2; + } else { + size += 3; + } + c = unicode[index++]; + } + + out = (unsigned char *) malloc(size + 1); + if (out == NULL) + return NULL; + index = 0; + + c = unicode[index++]; + while(c) + { + if(c < 0x080) { + out[out_index++] = (unsigned char)c; + } else if(c < 0x800) { + #pragma warning (suppress: 4244) // conversion from 'int' to 'unsigned char', possible loss of data + out[out_index++] = 0xc0 | (c >> 6); + out[out_index++] = 0x80 | (c & 0x3f); + } else { + out[out_index++] = 0xe0 | (c >> 12); + out[out_index++] = 0x80 | ((c >> 6) & 0x3f); + out[out_index++] = 0x80 | (c & 0x3f); + } + c = unicode[index++]; + } + out[out_index] = 0x00; + + return out; +} + +wchar_t *make_unicode_string(const unsigned char *utf8) +{ + int size = 0, index = 0, out_index = 0; + wchar_t *out; + unsigned char c; + + /* first calculate the size of the target string */ + c = utf8[index++]; + while(c) { + if((c & 0x80) == 0) { + index += 0; + } else if((c & 0xe0) == 0xe0) { + index += 2; + } else { + index += 1; + } + size += 1; + c = utf8[index++]; + } + + out = (wchar_t *) malloc((size + 1) * sizeof(wchar_t)); + if (out == NULL) + return NULL; + index = 0; + + c = utf8[index++]; + while(c) + { + if((c & 0x80) == 0) { + out[out_index++] = c; + } else if((c & 0xe0) == 0xe0) { + out[out_index] = (c & 0x1F) << 12; + c = utf8[index++]; + out[out_index] |= (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } else { + out[out_index] = (c & 0x3F) << 6; + c = utf8[index++]; + out[out_index++] |= (c & 0x3F); + } + c = utf8[index++]; + } + out[out_index] = 0; + + return out; +} + +int utf8_encode(const char *from, char **to) +{ + wchar_t *unicode; + int wchars, err; + + wchars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), NULL, 0); + + if(wchars == 0) + { +// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); + return -1; + } + + unicode = (wchar_t *) calloc(wchars + 1, sizeof(unsigned short)); + if(unicode == NULL) + { +// fprintf(stderr, "Out of memory processing string to UTF8\n"); + return -1; + } + + err = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, strlen(from), unicode, wchars); + if(err != wchars) + { + free(unicode); +// fprintf(stderr, "Unicode translation error %d\n"), GetLastError(); + return -1; + } + + /* On NT-based windows systems, we could use WideCharToMultiByte(), but + * MS doesn't actually have a consistent API across win32. + */ + *to = (char *) make_utf8_string(unicode); + + free(unicode); + return 0; +} + +int utf8_decode(const char *from, char **to) +{ + wchar_t *unicode; + int chars, err; +// LPCPINFO lpCPInfo; + + /* On NT-based windows systems, we could use MultiByteToWideChar(CP_UTF8), but + * MS doesn't actually have a consistent API across win32. + */ + unicode = make_unicode_string( (const unsigned char *)from); + if(unicode == NULL) + { + fprintf(stderr, "Out of memory processing string from UTF8 to UNICODE16\n"); + return -1; + } + + //if(GetCPInfo(CP_ACP,lpCPInfo)) + { + + chars = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + } + /*else + { + chars = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, NULL, 0, NULL, NULL); + }*/ + + if(chars == 0) + { + fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); + free(unicode); + return -1; + } + + *to = (char *) calloc(chars + 1, sizeof(unsigned char)); + if(*to == NULL) + { + fprintf(stderr, "Out of memory processing string to local charset\n"); + free(unicode); + return -1; + } + + //err = WideCharToMultiByte(GetConsoleCP(), WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); + err = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, unicode, -1, *to, chars, NULL, NULL); + if(err != chars) + { + fprintf(stderr, "Unicode translation error %ld\n", GetLastError()); + free(unicode); + free(*to); + *to = NULL; + return -1; + } + + free(unicode); + return 0; +} + +#ifndef _UNICODE +char *make_tchar_string(const unsigned char *utf8) { + char *ret; + if (utf8_decode((const char*)utf8, &ret)==-1) return NULL; + return ret; +} +#endif + +#else /* End win32. Rest is for real operating systems */ + + +#ifdef HAVE_LANGINFO_CODESET +#include +#endif + +int iconvert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen); + +static char *current_charset = "BIG-5"; /* means "US-ASCII" */ + +void convert_set_charset(const char *charset) +{ + + if (!charset) + charset = getenv("CHARSET"); + +#ifdef HAVE_LANGINFO_CODESET + if (!charset) + charset = nl_langinfo(CODESET); +#endif + + free(current_charset); + current_charset = 0; + if (charset && *charset) + current_charset = _strdup(charset); +} + +static int convert_buffer(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = -1; + +#ifdef HAVE_ICONV + ret = iconvert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + +#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ + ret = charset_convert(fromcode, tocode, from, fromlen, to, tolen); + if (ret != -1) + return ret; +#endif + + return ret; +} + +static int convert_string(const char *fromcode, const char *tocode, + const char *from, char **to, char replace) +{ + int ret; + size_t fromlen; + char *s; + + fromlen = lstrlen(from); + ret = convert_buffer(fromcode, tocode, from, fromlen, to, 0); + if (ret == -2) + return -1; + if (ret != -1) + return ret; + + s = malloc(fromlen + 1); + if (!s) + return -1; + lstrcpy(s, from); + *to = s; + for (; *s; s++) + if (*s & ~0x7f) + *s = replace; + return 3; +} + +int utf8_encode(const char *from, char **to) +{ + char *charset; + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string(charset, "UTF-8", from, to, '#'); +} + +int utf8_decode(const char *from, char **to) +{ + char *charset; + + if(*from == 0) { + *to = malloc(1); + **to = 0; + return 1; + } + + if (!current_charset) + convert_set_charset(0); + charset = current_charset ? current_charset : "US-ASCII"; + return convert_string("UTF-8", charset, from, to, '?'); +} + +#endif diff --git a/protocols/Skype/utf8.h b/protocols/Skype/utf8.h new file mode 100644 index 0000000000..70c533deca --- /dev/null +++ b/protocols/Skype/utf8.h @@ -0,0 +1,47 @@ +/* + * Convert a string between UTF-8 and the locale's charset. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * + * If the locale's charset is not set explicitly then it is + * obtained using nl_langinfo(CODESET), where available, the + * environment variable CHARSET, or assumed to be US-ASCII. + * + * Return value of conversion functions: + * + * -1 : memory allocation failed + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + * 3 : unknown encoding (but still converted, using '?') + */ + +#ifndef __UTF8_H +#define __UTF8_H + +#ifdef __cplusplus +extern "C" { +#endif + +void convert_set_charset(const char *charset); + +int utf8_encode(const char *from, char **to); +int utf8_decode(const char *from, char **to); +wchar_t *make_unicode_string(const unsigned char *utf8); +unsigned char *make_utf8_string(const wchar_t *unicode); +#ifdef _UNICODE +#define make_tchar_string make_unicode_string +// Helpers for strings that only can contain 7bit chars to not make unneccessary memory allocation +#define make_nonutf_tchar_string(x) make_tchar_string(x) +#define free_nonutf_tchar_string(x) if(x) free(x); +#else +char *make_tchar_string(const unsigned char *utf8); +#define make_nonutf_tchar_string(x) (char*)x +#define free_nonutf_tchar_string(x) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __UTF8_H */ diff --git a/protocols/Skype/util.c b/protocols/Skype/util.c new file mode 100644 index 0000000000..ce5ad9c756 --- /dev/null +++ b/protocols/Skype/util.c @@ -0,0 +1,57 @@ +#include + +char * __cdecl strtok_r ( + char * string, + const char * control, + char **nextoken + ) +{ + unsigned char *str; + const unsigned char *ctrl = (const unsigned char*)control; + + unsigned char map[32]; + int count; + + /* Clear control map */ + for (count = 0; count < 32; count++) + map[count] = 0; + + /* Set bits in delimiter table */ + do { + map[*ctrl >> 3] |= (1 << (*ctrl & 7)); + } while (*ctrl++); + + /* Initialize str. If string is NULL, set str to the saved + * pointer (i.e., continue breaking tokens out of the string + * from the last strtok call) */ + if (string) + str = (unsigned char*)string; + else + str = (unsigned char*)(*nextoken); + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets str to point to the terminal + * null (*str == '\0') */ + while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) + str++; + + string = (char*)str; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *str ; str++ ) + if ( map[*str >> 3] & (1 << (*str & 7)) ) { + *str++ = '\0'; + break; + } + + /* Update nextoken (or the corresponding field in the per-thread data + * structure */ + *nextoken = (char*)str; + + /* Determine if a token has been found. */ + if ( string == (char*)str ) + return NULL; + else + return string; +} diff --git a/protocols/Skype/util.h b/protocols/Skype/util.h new file mode 100644 index 0000000000..181f5d1878 --- /dev/null +++ b/protocols/Skype/util.h @@ -0,0 +1,7 @@ +char * __cdecl strtok_r ( + char * string, + const char * control, + char **nextoken + ); + +void TranslateMirandaRelativePathToAbsolute(LPCSTR cszPath, LPSTR szAbsolutePath, BOOL fQuoteSpaces); diff --git a/protocols/Skype/voiceservice.c b/protocols/Skype/voiceservice.c new file mode 100644 index 0000000000..b13ac097c1 --- /dev/null +++ b/protocols/Skype/voiceservice.c @@ -0,0 +1,156 @@ +#include "skype.h" +#include "skypeapi.h" +#include "skypesvc.h" +#include "voiceservice.h" +#include "sdk/m_voiceservice.h" + +#pragma warning (push) +#pragma warning (disable: 4100) // unreferenced formal parameter +#include "../../include/m_utils.h" +#pragma warning (pop) + +HANDLE hVoiceNotify = NULL; +BOOL has_voice_service = FALSE; + +extern char g_szProtoName[]; + + +BOOL HasVoiceService() +{ + return has_voice_service; +} + +void NofifyVoiceService(HANDLE hContact, char *callId, int state) +{ + VOICE_CALL vc = {0}; + vc.cbSize = sizeof(vc); + vc.szModule = SKYPE_PROTONAME; + vc.id = callId; + vc.flags = VOICE_CALL_CONTACT; + vc.state = state; + vc.hContact = hContact; + NotifyEventHooks(hVoiceNotify, (WPARAM) &vc, 0); +} + +static INT_PTR VoiceGetInfo(WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + return VOICE_SUPPORTED | VOICE_CALL_CONTACT | VOICE_CAN_HOLD; +} + +static HANDLE FindContactByCallId(char *callId) +{ + HANDLE hContact; + int iCmpRes; + for (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + hContact != NULL; + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0)) + { + char *szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + DBVARIANT dbv; + if (szProto != NULL + && !strcmp(szProto, SKYPE_PROTONAME) + && DBGetContactSettingByte(hContact, SKYPE_PROTONAME, "ChatRoom", 0) == 0 + && !DBGetContactSettingString(hContact, SKYPE_PROTONAME, "CallId", &dbv)) + { + iCmpRes = strcmp(callId, dbv.pszVal); + DBFreeVariant(&dbv); + if (iCmpRes == 0) return hContact; + } + } + + return NULL; +} + +static INT_PTR VoiceCall(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (DBGetContactSettingString((HANDLE)wParam, SKYPE_PROTONAME, SKYPE_NAME, &dbv)) + return -1; + + SkypeSend("CALL %s", dbv.pszVal); + DBFreeVariant (&dbv); + + return 0; +} + +static INT_PTR VoiceAnswer(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS INPROGRESS", callId); + testfor("ERROR", 200); + + return 0; +} + +static INT_PTR VoiceDrop(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS FINISHED", callId); + + return 0; +} + +static INT_PTR VoiceHold(WPARAM wParam, LPARAM lParam) +{ + char *callId = (char *) wParam; + + UNREFERENCED_PARAMETER(lParam); + + if (!wParam) return -1; + + if (FindContactByCallId(callId) == NULL) + return -1; + + SkypeSend("SET %s STATUS ONHOLD", callId); + + return 0; +} + +void VoiceServiceInit() +{ + // leecher, 26.03.2011: Did this ever work in the old versions?? + char szEvent[MAXMODULELABELLENGTH]; + + _snprintf (szEvent, sizeof(szEvent), "%s%s", SKYPE_PROTONAME, PE_VOICE_CALL_STATE); + hVoiceNotify = CreateHookableEvent( szEvent ); + CreateProtoService( PS_VOICE_GETINFO, VoiceGetInfo ); + CreateProtoService( PS_VOICE_CALL, VoiceCall ); + CreateProtoService( PS_VOICE_ANSWERCALL, VoiceAnswer ); + CreateProtoService( PS_VOICE_DROPCALL, VoiceDrop ); + CreateProtoService( PS_VOICE_HOLDCALL, VoiceHold ); +} + +void VoiceServiceExit() +{ + DestroyHookableEvent(hVoiceNotify); +} + +void VoiceServiceModulesLoaded() +{ + has_voice_service = ServiceExists(MS_VOICESERVICE_REGISTER); +} \ No newline at end of file diff --git a/protocols/Skype/voiceservice.h b/protocols/Skype/voiceservice.h new file mode 100644 index 0000000000..bbb333ec4b --- /dev/null +++ b/protocols/Skype/voiceservice.h @@ -0,0 +1,18 @@ +#ifndef _VOICESERVICE_H_ +#define _VOICESERVICE_H_ + +#pragma warning (push) +#pragma warning (disable: 4201) // nonstandard extension used : nameless struct/union +#include "sdk/m_voice.h" +#pragma warning (pop) + +BOOL HasVoiceService(); +void VoiceServiceInit(); +void VoiceServiceExit(); +void VoiceServiceModulesLoaded(); +void NofifyVoiceService(HANDLE hContact, char *callId, int state) ; + + + +#endif // _VOICESERVICE_H_ + -- cgit v1.2.3