From 271cf1987ef0dc4d6561d14e0ba89c17bb125903 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 10 Feb 2013 19:26:03 +0000 Subject: NotifyAnything plugin git-svn-id: http://svn.miranda-ng.org/main/trunk@3539 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/NotifyAnything/NotifyAnything_10.vcxproj | 200 ++++ .../NotifyAnything_10.vcxproj.filters | 41 + plugins/NotifyAnything/NotifyAnything_11.vcxproj | 204 ++++ .../NotifyAnything_11.vcxproj.filters | 41 + plugins/NotifyAnything/docs/NA.css | 34 + plugins/NotifyAnything/docs/Public Domain.txt | 1 + plugins/NotifyAnything/docs/Sendlog.htm | 122 +++ plugins/NotifyAnything/res/NotifyAnything.rc | 167 ++++ plugins/NotifyAnything/sendlog/SLImp.cpp | 94 ++ plugins/NotifyAnything/sendlog/SendLog.cpp | 38 + plugins/NotifyAnything/sendlog/SendLogWin.cpp | 30 + plugins/NotifyAnything/sendlog/compile.bat | 31 + plugins/NotifyAnything/src/common.h | 61 ++ plugins/NotifyAnything/src/main.cpp | 1057 ++++++++++++++++++++ plugins/NotifyAnything/src/options.cpp | 209 ++++ plugins/NotifyAnything/src/resource.h | 27 + plugins/NotifyAnything/src/stdafx.cpp | 18 + plugins/Nudge/src/main.cpp | 3 +- 18 files changed, 2376 insertions(+), 2 deletions(-) create mode 100644 plugins/NotifyAnything/NotifyAnything_10.vcxproj create mode 100644 plugins/NotifyAnything/NotifyAnything_10.vcxproj.filters create mode 100644 plugins/NotifyAnything/NotifyAnything_11.vcxproj create mode 100644 plugins/NotifyAnything/NotifyAnything_11.vcxproj.filters create mode 100644 plugins/NotifyAnything/docs/NA.css create mode 100644 plugins/NotifyAnything/docs/Public Domain.txt create mode 100644 plugins/NotifyAnything/docs/Sendlog.htm create mode 100644 plugins/NotifyAnything/res/NotifyAnything.rc create mode 100644 plugins/NotifyAnything/sendlog/SLImp.cpp create mode 100644 plugins/NotifyAnything/sendlog/SendLog.cpp create mode 100644 plugins/NotifyAnything/sendlog/SendLogWin.cpp create mode 100644 plugins/NotifyAnything/sendlog/compile.bat create mode 100644 plugins/NotifyAnything/src/common.h create mode 100644 plugins/NotifyAnything/src/main.cpp create mode 100644 plugins/NotifyAnything/src/options.cpp create mode 100644 plugins/NotifyAnything/src/resource.h create mode 100644 plugins/NotifyAnything/src/stdafx.cpp (limited to 'plugins') diff --git a/plugins/NotifyAnything/NotifyAnything_10.vcxproj b/plugins/NotifyAnything/NotifyAnything_10.vcxproj new file mode 100644 index 0000000000..99d6ebd770 --- /dev/null +++ b/plugins/NotifyAnything/NotifyAnything_10.vcxproj @@ -0,0 +1,200 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + NotifyAnything + {5B592088-D4C3-4BDA-8307-0B2A0EE24C40} + + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + true + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Full + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + OnlyExplicitInline + Size + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + false + $(IntDir)$(TargetName).lib + true + true + true + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + /PDBALTPATH:%_PDB% + + + + + Full + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + OnlyExplicitInline + Size + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + false + $(IntDir)$(TargetName).lib + true + true + true + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + /PDBALTPATH:%_PDB% + + + + + Disabled + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + common.h + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + true + false + $(IntDir)$(TargetName).lib + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + + + + + Disabled + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + true + false + $(IntDir)$(TargetName).lib + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/NotifyAnything/NotifyAnything_10.vcxproj.filters b/plugins/NotifyAnything/NotifyAnything_10.vcxproj.filters new file mode 100644 index 0000000000..863181e19a --- /dev/null +++ b/plugins/NotifyAnything/NotifyAnything_10.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {7e24b5e6-2653-4143-a42b-d3486d5c416f} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {596c44cc-f8d3-4837-8fb4-49d4aa913452} + h;hpp;hxx;hm;inl + + + {9c926bbb-252f-489c-8433-2db02ad00ba7} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/plugins/NotifyAnything/NotifyAnything_11.vcxproj b/plugins/NotifyAnything/NotifyAnything_11.vcxproj new file mode 100644 index 0000000000..1724a4d4a5 --- /dev/null +++ b/plugins/NotifyAnything/NotifyAnything_11.vcxproj @@ -0,0 +1,204 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + NotifyAnything + {F5E3FAFE-B650-4736-8D27-FA53866668C6} + + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + + + DynamicLibrary + Unicode + v110 + true + + + DynamicLibrary + Unicode + v110 + true + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Full + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + OnlyExplicitInline + Size + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + false + $(IntDir)$(TargetName).lib + true + true + true + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + /PDBALTPATH:%_PDB% + + + + + Full + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + OnlyExplicitInline + Size + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + false + $(IntDir)$(TargetName).lib + true + true + true + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + /PDBALTPATH:%_PDB% + + + + + Disabled + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + common.h + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + true + false + $(IntDir)$(TargetName).lib + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + + + + + Disabled + ..\..\include;..\ExternalAPI%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use + common.h + Level3 + 4996;%(DisableSpecificWarnings) + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + true + false + $(IntDir)$(TargetName).lib + Windows + ws2_32.lib;comctl32.lib;%(AdditionalDependencies) + $(ProfileDir)..\..\bin11\lib + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/NotifyAnything/NotifyAnything_11.vcxproj.filters b/plugins/NotifyAnything/NotifyAnything_11.vcxproj.filters new file mode 100644 index 0000000000..863181e19a --- /dev/null +++ b/plugins/NotifyAnything/NotifyAnything_11.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {7e24b5e6-2653-4143-a42b-d3486d5c416f} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {596c44cc-f8d3-4837-8fb4-49d4aa913452} + h;hpp;hxx;hm;inl + + + {9c926bbb-252f-489c-8433-2db02ad00ba7} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/plugins/NotifyAnything/docs/NA.css b/plugins/NotifyAnything/docs/NA.css new file mode 100644 index 0000000000..21655b76ff --- /dev/null +++ b/plugins/NotifyAnything/docs/NA.css @@ -0,0 +1,34 @@ +BODY +{ + font-size: 11pt; + color: #000000; + font-family: Tahoma; + background-color: #ffffff; + text-align: justify; +} +TD +{ + font-size: 11pt; + font-family: Tahoma; + vertical-align: top; +} +PRE +{ + color: #002277; + text-align: left; + margin-bottom: 3pt; +} +TABLE +{ + border: thin; +} +.crow +{ + background-color: #f7f7f7; +} +.popup +{ + font-size: 12px; + padding-left: 5px; + border: solid 1px #000000; +} diff --git a/plugins/NotifyAnything/docs/Public Domain.txt b/plugins/NotifyAnything/docs/Public Domain.txt new file mode 100644 index 0000000000..f4d97e589e --- /dev/null +++ b/plugins/NotifyAnything/docs/Public Domain.txt @@ -0,0 +1 @@ +NotifyAnything was placed in public domain in 2003 by Daniel Wesslén, do with it as you please. diff --git a/plugins/NotifyAnything/docs/Sendlog.htm b/plugins/NotifyAnything/docs/Sendlog.htm new file mode 100644 index 0000000000..3adaa6594f --- /dev/null +++ b/plugins/NotifyAnything/docs/Sendlog.htm @@ -0,0 +1,122 @@ + + + Sendlog Documentation + + + +

Sendlog

+

Version 0.0.1.5
+ by Daniel Wesslén

+

Frequently Asked Questions

+

+ + + + + + + + + + + + + + + + + + + + + + + + +
QWhat does this program do anyway?
A + Sendlog sends the arguments you give it as a message to NotifyAnything, which + will forward them to the PopUp plugin, which will display a nice little window.
 
QHow should the messages be formatted?
A +

Read the Protocol Reference section in the NotifyAnything documentation.

+
+

+

+ Requirements

+

Miranda IM with the + PopUp and + NotifyAnything plugins.

+

Usage

+

Simply run sendlog.exe or sendlog32.exe, giving the message as an argument.

+
c:\> sendlog Hello
c:\> sendlog32 Hello
+

If -T is specified, the message is sent through TCP/IP, otherwise it is sent as + a single UDP message.

+

If you start sendlog without any arguments it will accept input and send each + line as a separate message. (Not applicable to sendlog32.)

+
c:\> sendlog
Hello
+

A prefix may be prepended to every line.

+
c:\> sendlog -p Bob#
Hello
+

It is possible to send messages to a port different from the default (12001) by + providing it with -P, or to a different computer using -H.

+
c:\> sendlog -P 12345 Hello
c:\> sendlog -H my.computer.com Hi there!
+

Version History

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
0.0.1.5 +
    +
  • + Can now send messages through TCP as well as UDP.
+
0.0.1.4 +
    +
  • + Can now send messages to other computers.
+
0.0.1.3 +
    +
  • + Fixed problem with -P argument without message arguments.
+
0.0.1.2 +
    +
  • + Can now send messages to any port.
+
0.0.1.1 +
    +
  • + Option to prepend a prefix to every message.  +
  • + Separated Sendlog from the NotifyAnything package. +
  • + Package now includes Sendlog32, a Win32 application, usable when Sendlog causes + a console window to appear and rapidly disappear.
  • +
+
0.0.1.0 +
    +
  • + Initial release.
+
+

+

Known Bugs

+

None.

+ + diff --git a/plugins/NotifyAnything/res/NotifyAnything.rc b/plugins/NotifyAnything/res/NotifyAnything.rc new file mode 100644 index 0000000000..d89d3bfda2 --- /dev/null +++ b/plugins/NotifyAnything/res/NotifyAnything.rc @@ -0,0 +1,167 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + NA_OPTIONS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 229 + VERTGUIDE, 13 + VERTGUIDE, 55 + VERTGUIDE, 61 + TOPMARGIN, 7 + BOTTOMMARGIN, 184 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +NA_OPTIONS DIALOGEX 0, 0, 236, 191 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE | WS_CHILD | WS_CAPTION +CAPTION "Property Page" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + GROUPBOX "Security",IDC_STATIC,7,7,222,77 + CONTROL "Only listen to localhost",NA_LOCAL_CHECK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,13,19,209,10 + GROUPBOX "Sound",IDC_STATIC,7,91,222,43 + CONTROL "Play sounds",NA_SOUND_CHECK,"Button",BS_AUTO3STATE | WS_GROUP | WS_TABSTOP,13,102,114,10 + CONTROL "Use internal speaker",NA_PCSPEAKER_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,118,127,10 + GROUPBOX "Debug",IDC_STATIC,7,142,222,42 + CONTROL "Log to file",NA_LOG_CHECK,"Button",BS_AUTO3STATE | WS_GROUP | WS_TABSTOP,13,152,98,10 + CONTROL "Message debugging",NA_DEBUG_MSG_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,152,102,10 + EDITTEXT NA_PORT,49,31,40,14,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Port:",IDC_STATIC,13,33,17,8 + LTEXT "(Default is 12001)",IDC_STATIC,95,33,89,8 + CONTROL "Allow actions to execute programs",NA_ALLOW_EXECUTE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,66,207,10 + EDITTEXT NA_PASSWORD,49,48,77,14,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Password:",IDC_STATIC,13,51,34,8 + EDITTEXT NA_LOG_FILENAME,13,165,187,13,ES_AUTOHSCROLL + PUSHBUTTON "...",NA_LOG_BROWSE,206,165,17,13 +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Swedish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) +#ifdef _WIN32 +LANGUAGE LANG_SWEDISH, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,2,8 + PRODUCTVERSION 0,0,2,8 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Receives popup descriptions from external sources and forward them to the PopUp plugin." + VALUE "CompanyName", "Daniel Wesslen" + VALUE "FileDescription", "NotifyAnything Miranda IM plugin" + VALUE "FileVersion", "0, 0, 2, 8" + VALUE "InternalName", "NotifyAnything" + VALUE "LegalCopyright", "Placed in public domain 2003" + VALUE "OriginalFilename", "NotifyAnything.dll" + VALUE "ProductName", "NotifyAnything Miranda plugin" + VALUE "ProductVersion", "0, 0, 2, 8" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // Swedish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/NotifyAnything/sendlog/SLImp.cpp b/plugins/NotifyAnything/sendlog/SLImp.cpp new file mode 100644 index 0000000000..0a4b69e81c --- /dev/null +++ b/plugins/NotifyAnything/sendlog/SLImp.cpp @@ -0,0 +1,94 @@ +#define _WINSOCKAPI_ // don't include winsock 1.x +#include +#include +#include +#include + +#include +#include + +#include +#include + +void implementation(int argc, char **argv, bool console) +{ + int port = 12001; + bool tcp = false; + const char *target = "127.0.0.1"; + + if (argc >= 2 && !strcmp("-T", argv[1])) { + tcp = true; + argc -= 1; + argv += 1; + } + + if (argc >= 3 && !strcmp("-H", argv[1])) { + target = argv[2]; + argc -= 2; + argv += 2; + } + + if (argc >= 3 && !strcmp("-P", argv[1])) { + port = atoi(argv[2]); + argc -= 2; + argv += 2; + } + + WSADATA wsaData; + int err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err) + throw (DWORD) err; + + char portbuf[10]; + sprintf(portbuf, "%i", port); + + ADDRINFO hints; + memset(&hints, 0, sizeof hints); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = PF_INET; + ADDRINFO *res; + err = getaddrinfo(target, portbuf, &hints, &res); + + if (err || !res) + throw (DWORD) err; + + SOCKET sock; + SOCKADDR_IN to = *(SOCKADDR_IN*)res->ai_addr; + + sock = socket(AF_INET, tcp ? SOCK_STREAM : SOCK_DGRAM, tcp ? IPPROTO_TCP : IPPROTO_UDP); + if (sock == INVALID_SOCKET) + throw (DWORD) WSAGetLastError(); + + SOCKADDR_IN self; + ZeroMemory(&self, sizeof self); + self.sin_family = AF_INET; + + if (bind(sock, (const SOCKADDR *) &self, sizeof self)) + throw (DWORD) WSAGetLastError(); + + if (connect(sock, (const SOCKADDR *) &to, sizeof to)) + throw (DWORD) WSAGetLastError(); + + if (console && (argc == 1 || argc == 3 && !strcmp("-p", argv[1]))) { + std::string prefix; + if (argc == 3) + prefix = argv[2]; + std::string line; + while (std::getline(std::cin, line)) { + std::string data = prefix + line; + send(sock, data.data(), data.size(), 0); + } + } else { + std::string message = argv[1]; + for (int i=2; i +#include + +#include +#include + +void implementation(int argc, char **argv, bool console); + +int main(int argc, char **argv) +try +{ + if (argc == 2 && !strcmp("/?", argv[1])) { + std::cout << "\n" + "Syntax: sendlog [-T] [-H host] [-P port] [-p prefix]\n" + "\tSends each input line as a separate message, with optional prefix.\n" + "\n" + "Syntax: sendlog text\n" + "\tSends single text message.\n" + "\n" + << std::flush; + return 0; + } + + implementation(argc, argv, true); +} +catch (DWORD err) { + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + std::cerr << (LPCTSTR)lpMsgBuf << std::endl; + if (!std::cerr) + MessageBox(NULL, (LPCTSTR)lpMsgBuf, "sendlog", MB_OK); + + LocalFree(lpMsgBuf); + + return 1; +} diff --git a/plugins/NotifyAnything/sendlog/SendLogWin.cpp b/plugins/NotifyAnything/sendlog/SendLogWin.cpp new file mode 100644 index 0000000000..37f112efb8 --- /dev/null +++ b/plugins/NotifyAnything/sendlog/SendLogWin.cpp @@ -0,0 +1,30 @@ +#include +#include + +#include +#include + +void implementation(int argc, char **argv, bool console); + +int main(int argc, char **argv) +try +{ + if (argc == 1 || argc == 2 && !strcmp("/?", argv[1])) { + MessageBox(NULL, "Syntax: sendlog32 [-T] [-H host] [-P port] text\n" + "\tSends single text message.", "Sendlog32", MB_OK); + return 0; + } + + implementation(argc, argv, false); +} +catch (DWORD err) { + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + MessageBox(NULL, (LPCTSTR)lpMsgBuf, "sendlog32", MB_OK); + + LocalFree(lpMsgBuf); + + return 1; +} diff --git a/plugins/NotifyAnything/sendlog/compile.bat b/plugins/NotifyAnything/sendlog/compile.bat new file mode 100644 index 0000000000..f5dc4d40f0 --- /dev/null +++ b/plugins/NotifyAnything/sendlog/compile.bat @@ -0,0 +1,31 @@ +rem @echo off +if not "%VS100COMNTOOLS%" == "" ( + call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" + "%VS100COMNTOOLS%\..\..\vc\bin\cl.exe" /MD /O2 /Os /EHsc SendLog.cpp SLImp.cpp /link ws2_32.lib user32.lib + "%VS100COMNTOOLS%\..\..\vc\bin\cl.exe" /MD /O2 /Os /EHsc SendLogWin.cpp SLImp.cpp /link ws2_32.lib user32.lib + call :ProcessFiles 10 +) + +if not "%VS110COMNTOOLS%" == "" ( + call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" + "%VS110COMNTOOLS%\..\..\vc\bin\cl.exe" /MD /O2 /Os /EHsc SendLog.cpp SLImp.cpp /link ws2_32.lib user32.lib + "%VS110COMNTOOLS%\..\..\vc\bin\cl.exe" /MD /O2 /Os /EHsc SendLogWin.cpp SLImp.cpp /link ws2_32.lib user32.lib + call :ProcessFiles 11 +) +goto :eof + +:ProcessFiles +mkdir ..\..\..\bin%1\Debug 2>nul +copy /Y *.exe ..\..\..\bin%1\Debug >nul + +mkdir ..\..\..\bin%1\Debug64 2>nul +copy /Y *.exe ..\..\..\bin%1\Debug64 >nul + +mkdir ..\..\..\bin%1\Release 2>nul +copy /Y *.exe ..\..\..\bin%1\Release >nul + +mkdir ..\..\..\bin%1\Release64 2>nul +copy /Y *.exe ..\..\..\bin%1\Release64 >nul + +del *.obj;*.exe >nul +goto :eof diff --git a/plugins/NotifyAnything/src/common.h b/plugins/NotifyAnything/src/common.h new file mode 100644 index 0000000000..264b5adee8 --- /dev/null +++ b/plugins/NotifyAnything/src/common.h @@ -0,0 +1,61 @@ +// disable warnings about underscore in stdc functions +#pragma warning(disable: 4996) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "newpluginapi.h" +#include "m_system_cpp.h" +#include "m_options.h" +#include "m_skin.h" +#include "m_langpack.h" +#include "m_database.h" +#include "m_utils.h" + +#include "m_popup.h" +#include "m_LogService.h" + +extern HINSTANCE hInst; + +const char PlugName[] = "NotifyAnything"; + +//--------------------------- +//---Internal Hooks (see main.c) +//---(Workaround till CallServiceSync is available) + +struct NASettings { + enum sound_t { never, always, request }; + + bool local_only, debug_messages, log_to_file, use_pcspeaker, allow_execute; + sound_t sound; + int port; + std::string password, log_filename; +}; + +extern NASettings g_settings; + +void stop_threads(); +void start_threads(); + +void save_settings(); +void load_settings(); + +int OptionsInitialize(WPARAM wParam, LPARAM lParam); + +extern std::string g_mirandaDir; +extern bool IsLogService; +#define LOG_ID "NotifyAnything" diff --git a/plugins/NotifyAnything/src/main.cpp b/plugins/NotifyAnything/src/main.cpp new file mode 100644 index 0000000000..7ef581fb24 --- /dev/null +++ b/plugins/NotifyAnything/src/main.cpp @@ -0,0 +1,1057 @@ +#include "common.h" + +#define EnterCS(cs) EnterCriticalSection(cs) +#define LeaveCS(cs) LeaveCriticalSection(cs) + +//--------------------------- +//---Internal Hooks +//---(Workaround till CallServiceSync is available) + +/* +Stolen from NewEventNotify: +The idea for this is taken from "NewStatusNotify" by Hrk, thx *g* +This is needed to send a message with safe multithrading. +We'll create a private hook and we'll call it via NotifyEventHooks, which brings execution +back to the main thread. +*/ + +void cslog(const char *what, const char *file, int line) +{ + if (IsLogService){ + std::string LogString; + char buf[10]; + LogString = what; + LogString += ": "; + LogString += file; + LogString += ":"; + LogString += itoa(line, buf, 10); + logservice_log(LOG_ID, NULL, (TCHAR *) LogString.c_str()); + } + else { + if (g_settings.log_to_file) { + time_t t_; + time(&t_); + tm *t = localtime(&t_); + //FILE *f = fopen("na.log", "a"); + FILE *f = fopen(g_settings.log_filename.c_str(), "a"); + if (f) { + //fprintf(f, "%s: %s:%i\n", what, file, line); + fprintf(f, "[%04i-%02i-%02i %02i:%02i:%02i cs] %s: %s:%i\n", + int(t->tm_year+1900), int(t->tm_mon), int(t->tm_mday), + int(t->tm_hour), int(t->tm_min), int(t->tm_sec), what, file, line); + fclose(f); + } + } + } +} + +void EnterCSHelper(CRITICAL_SECTION *cs, const char *file, int line) +{ + cslog(">enter", file, line); + EnterCriticalSection(cs); + cslog("leave", file, line); + LeaveCriticalSection(cs); + cslog(" popups_t; +typedef std::set anon_popups_t; +popups_t g_popups; +anon_popups_t g_anon_popups; +CRITICAL_SECTION g_popups_cs; + +std::string strip(std::string str) +{ + while (!str.empty() && isspace(str[0])) + str.erase(0, 1); + while (!str.empty() && isspace(*(str.end()-1))) + str.erase(str.size()-1); + return str; +} + +void dbg_msg(std::string str, int type) +{ + str = strip(str); + + if (g_settings.debug_messages) + CallServiceSync(MS_POPUP_SHOWMESSAGE, (WPARAM) const_cast(str.c_str()), (LPARAM) type); + + if (IsLogService){ + logservice_log(LOG_ID, NULL, (TCHAR *) str.c_str()); + } + else { + if (g_settings.log_to_file) { + time_t t_; + time(&t_); + tm *t = localtime(&t_); + FILE *f = fopen(g_settings.log_filename.c_str(), "a"); + if (f) { + fprintf(f, "[%04i-%02i-%02i %02i:%02i:%02i dbg_msg] %s\n", + int(t->tm_year+1900), int(t->tm_mon), int(t->tm_mday), + int(t->tm_hour), int(t->tm_min), int(t->tm_sec), str.c_str()); + fclose(f); + } + } + } +} + +void showLastError() +{ + int err = GetLastError(); + + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); + + dbg_msg((char *) lpMsgBuf, SM_WARNING); + + LocalFree(lpMsgBuf); +} + +struct enum_icons_t { + int nr; + LPCTSTR name; + bool found; +}; + +BOOL CALLBACK enum_icons_func(HMODULE, LPCTSTR, LPTSTR name, LONG_PTR data) +{ + enum_icons_t *info = (enum_icons_t *) data; + if (!--info->nr) { + info->found = true; + info->name = name; + return FALSE; + } + return TRUE; +} + +void registerSound(const std::string &name) +{ + static std::set sset; + + if (sset.find(name) != sset.end()) + return; + sset.insert(name); + + std::string id = "NotifyAnything_" + name; + std::string desc = "NotifyAnything: " + name; + std::string file = name + ".wav"; + SkinAddNewSound(id.c_str(), Translate(desc.c_str()), file.c_str()); +} + +HICON getIcon(const std::string &name) +{ + static std::map icons; + static HICON deficon; + static bool init; + if (!init) { + init = true; + + // windows icons + icons["exclamation"] = icons["warning"] = LoadIcon(NULL, IDI_WARNING); + deficon = icons["information"] = icons["asterisk"] = LoadIcon(NULL, IDI_ASTERISK); + icons["hand"] = icons["error"] = LoadIcon(NULL, IDI_ERROR); + icons["question"] = LoadIcon(NULL, IDI_QUESTION); + icons["winlogo"] = LoadIcon(NULL, IDI_WINLOGO); + + // miranda icons + icons["online"] = LoadSkinnedIcon(SKINICON_STATUS_ONLINE); + icons["offline"] = LoadSkinnedIcon(SKINICON_STATUS_OFFLINE); + icons["away"] = LoadSkinnedIcon(SKINICON_STATUS_AWAY); + icons["na"] = LoadSkinnedIcon(SKINICON_STATUS_NA); + icons["occupied"] = LoadSkinnedIcon(SKINICON_STATUS_OCCUPIED); + icons["dnd"] = LoadSkinnedIcon(SKINICON_STATUS_DND); + icons["free4chat"] = LoadSkinnedIcon(SKINICON_STATUS_FREE4CHAT); + icons["invisible"] = LoadSkinnedIcon(SKINICON_STATUS_INVISIBLE); + icons["onthephone"] = LoadSkinnedIcon(SKINICON_STATUS_ONTHEPHONE); + icons["outtolunch"] = LoadSkinnedIcon(SKINICON_STATUS_OUTTOLUNCH); + + icons["message"] = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + icons["url"] = LoadSkinnedIcon(SKINICON_EVENT_URL); + icons["file"] = LoadSkinnedIcon(SKINICON_EVENT_FILE); + } + + std::map::iterator i = icons.find(name); + if (i != icons.end()) + return i->second; + + size_t p = name.rfind(','); + if (p == name.npos) { + // try to load icon file + HANDLE h = LoadImageA(NULL, name.c_str(), IMAGE_ICON, 16, 16, LR_LOADFROMFILE); + if (h != NULL) + return icons[name] = (HICON) h; + + showLastError(); + return deficon; + } + + std::tstring file((TCHAR*)_A2T(name.c_str()), 0, p); + + std::tstring rname(file.c_str(), p+1); + if (rname.empty()) { + dbg_msg(Translate("No resource name given."), SM_WARNING); + return deficon; + } + + HMODULE module = LoadLibraryEx(file.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE); + if (!module) { + showLastError(); + return deficon; + } + + LPCTSTR resname = rname.c_str(); + if (isdigit(rname[0])) { + enum_icons_t info; + info.found = false; + info.nr = _ttoi(rname.c_str()); + if (info.nr <= 0) { + dbg_msg(Translate("Icon indices start at 1."), SM_WARNING); + return deficon; + } + + BOOL ok = EnumResourceNames(module, RT_GROUP_ICON, enum_icons_func, (LONG_PTR) &info); + if (!info.found) { + if (!ok) { + if (GetLastError()) { + showLastError(); + return deficon; + } + } + dbg_msg(Translate("Could not find the requested icon."), SM_WARNING); + return deficon; + } + resname = info.name; + } + + HICON icon = (HICON) LoadImage(module, resname, IMAGE_ICON, 16, 16, 0); + FreeLibrary(module); + + if (!icon) { + showLastError(); + return deficon; + } + + return icons[name] = (HICON) icon; +} + +bool getNext(std::string &out, std::string &in, char sep) +{ + while (!in.empty() && in[0] == ' ') + in.erase(0, 1); + + out.erase(); + + while (!in.empty()) { + if (in[0] == sep) { + in.erase(0,1); + return true; + } + if (in[0] == '\"') { + in.erase(0,1); + size_t p = in.find('\"'); + if (p == in.npos) + throw "Unterminated quote: \"" + in; + out += '"'; + out.append(in, 0, p); + out += '"'; + in.erase(0, p+1); + return true; + } + if (!in.compare(0, 3, "<[[")) { + in.erase(0, 3); + size_t p = in.find("]]>"); + if (p == in.npos) + throw "Unterminated \"<[[\": <[[" + in; + out.append(in, 0, p); + in.erase(0, p+3); + return true; + } + + out += in[0]; + in.erase(0,1); + return true; + } + return false; +} + +std::string unquote(std::string str) +{ + size_t p; + while ((p = str.find('\"')) != str.npos) + str.erase(p, 1); + return str; +} + +void getAll(std::vector &out, std::string &in, char sep, bool unquote_) +{ + std::string arg; + while (getNext(arg, in, sep)) + if (!arg.empty()) { + if (unquote_) + arg = unquote(arg); + out.push_back(arg); + } +} + +const char *decode_se_arg(std::string &str) +{ + return (str.empty()) ? 0 : str.c_str(); +} + +void processSingleAction(const std::string &what, bool &closeflag) +{ + if (!what.compare(0, 7, "system:")) { + if (!g_settings.allow_execute) { + dbg_msg(Translate("Application launching is disabled."), SM_WARNING); + return; + } + + std::string argstr(what, 7); + + if (system(argstr.c_str()) == -1) + dbg_msg("Failed to execute: " + argstr, SM_WARNING); + } + else if (!what.compare(0, 4, "cmd:")) { + if (!g_settings.allow_execute) { + dbg_msg(Translate("Application launching is disabled."), SM_WARNING); + return; + } + + std::string argstr(what, 4); + std::vector args; + + getAll(args, argstr, ' ', true); + + if (args.empty()) + throw "Insufficient arguments: " + what; + + std::vector cargs; + for (std::vector::iterator i=args.begin(), e=args.end(); i!=e; ++i) + cargs.push_back(i->c_str()); + cargs.push_back(0); + + if (_spawnvp(_P_DETACH, cargs[0], &cargs[0]) == -1) + dbg_msg("Failed to execute: " + what.substr(4), SM_WARNING); + + } + else if (!what.compare(0, 5, "open:")) { + if (!g_settings.allow_execute) { + dbg_msg(Translate("Application launching is disabled."), SM_WARNING); + return; + } + + std::string argstr(what, 5); + + std::string file, args; + if (!getNext(file, argstr, ' ')) + throw "No filename provided: " + what; + file = strip(file); + args = strip(argstr); + + const char *cargs = decode_se_arg(args); + + if ((int) ShellExecuteA(0, "open", file.c_str(), cargs, 0, SW_SHOWNORMAL) <= 32) + throw "Failed to open: " + file + " " + args; + + } else if (!what.compare(0, 6, "shell:")) { + if (!g_settings.allow_execute) { + dbg_msg(Translate("Application launching is disabled."), SM_WARNING); + return; + } + + std::string argstr(what, 6); + + std::string verb, file, args, dir; + if (!getNext(verb, argstr, ':')) + throw "No verb provided: " + what; + if (!getNext(file, argstr, ',')) + throw "No filename provided: " + what; + getNext(args, argstr, ','); + getNext(dir, argstr, ','); + verb = unquote(strip(verb)); + file = /*unquote(*/strip(file)/*)*/; + args = strip(args); + dir = /*unquote(*/strip(dir)/*)*/; + + if ((int) ShellExecuteA(0, decode_se_arg(verb), decode_se_arg(file), + decode_se_arg(args), decode_se_arg(dir), SW_SHOWNORMAL) <= 32) + throw "Failed: " + what; + } else if (what == "close") + closeflag = true; + else + throw "Action not recognized: " + what; +} + +void processAction(const std::string &what, bool &closeflag) +{ + try + { + std::string argstr = what; + std::vector actions; + + std::string action; + while (getNext(action, argstr, ';')) + if (!action.empty()) + processSingleAction(action, closeflag); + } + catch (std::string err) { + dbg_msg(err, SM_WARNING); + } +} + +static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + popup_t *pd = 0; + pd = (popup_t *) CallService(MS_POPUP_GETPLUGINDATA, (WPARAM) hWnd, (LPARAM) pd); + if (!pd) + return FALSE; + + switch (message) { + case WM_COMMAND: + { + EnterCS(&g_popups_cs); + std::string left; + if (pd) + left = pd->left; + LeaveCS(&g_popups_cs); + + if (left.empty()) + PUDeletePopUp(hWnd); + else { + bool closeflag = false; + processAction(left, closeflag); + if (closeflag) + PUDeletePopUp(hWnd); + } + } + return TRUE; + + case WM_CONTEXTMENU: + { + EnterCS(&g_popups_cs); + std::string right; + if (pd) + right = pd->right; + LeaveCS(&g_popups_cs); + + if (right.empty()) + PUDeletePopUp(hWnd); + else { + bool closeflag = false; + processAction(right, closeflag); + if (closeflag) + PUDeletePopUp(hWnd); + } + } + return TRUE; + + case UM_INITPOPUP: + EnterCS(&g_popups_cs); + pd->hwnd = hWnd; + LeaveCS(&g_popups_cs); + return TRUE; + + case UM_FREEPLUGINDATA: + EnterCS(&g_popups_cs); + std::string closed; + if (pd) + closed = pd->closed; + + g_popups.erase(pd->id); + g_anon_popups.erase(pd); + delete pd; + LeaveCS(&g_popups_cs); + + if (!closed.empty()) { + bool closeflag = false; + processAction(closed, closeflag); + } + + return TRUE; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +int showMessage(const popup_t &msg) +{ + POPUPDATAEX ppd = { 0 }; + strncpy(ppd.lpzText, strip(msg.message).c_str(), MAX_SECONDLINE); + strncpy(ppd.lpzContactName, msg.contact.c_str(), MAX_CONTACTNAME); + ppd.colorBack = msg.background; + ppd.colorText = msg.foreground; + ppd.lchIcon = getIcon(msg.icon); + ppd.PluginWindowProc = (WNDPROC) PopupDlgProc; + ppd.iSeconds = msg.delay; + + EnterCS(&g_popups_cs); + + popup_t *msgp = new popup_t(msg); + + if (!msg.id.empty()) + g_popups[msg.id] = msgp; + g_anon_popups.insert(msgp); + ppd.PluginData = msgp; + + LeaveCS(&g_popups_cs); + + return CallServiceSync(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); +} + +void replaceMessage(const popup_t &msg) +{ + EnterCS(&g_popups_cs); + + popups_t::iterator i = g_popups.find(msg.id); + if (i != g_popups.end()) { + if (i->second->hwnd) { + + popup_t &nmsg = *i->second; + + switch (msg.replace) { + case xreplace: + nmsg.message = msg.message; break; + case xappend: + nmsg.message += msg.message; break; + case xprepend: + nmsg.message = msg.message + nmsg.message; break; + default: + break; + } + + if (!msg.left.empty()) + nmsg.left = msg.left; + if (!msg.right.empty()) + nmsg.right = msg.right; + if (!msg.opened.empty()) + nmsg.opened = msg.opened; + if (!msg.closed.empty()) + nmsg.closed = msg.closed; + + LeaveCS(&g_popups_cs); + + CallServiceSync(MS_POPUP_CHANGETEXT, (WPARAM)i->second->hwnd, (LPARAM)strip(i->second->message).c_str()); + return; + } + } + + LeaveCS(&g_popups_cs); +} + +inline int dehex(int c) { + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else + return 0; +} + +COLORREF parseColor(const std::string &buf, bool &ok) +{ + ok = false; + for (int i=0; i!=buf.size(); ++i) + if (!isxdigit(buf[i])) + return RGB(0,0,0); + if (buf.size() == 6) { + int r = (dehex(buf[0]) << 4) + dehex(buf[1]); + int g = (dehex(buf[2]) << 4) + dehex(buf[3]); + int b = (dehex(buf[4]) << 4) + dehex(buf[5]); + ok = true; + return RGB(r,g,b); + } else if (buf.size() == 3) { + int r = dehex(buf[0])*17; + int g = dehex(buf[1])*17; + int b = dehex(buf[2])*17; + ok = true; + return RGB(r,g,b); + } else + return RGB(0,0,0); +} + +void loadDefaults(popup_t &msg, char ch) +{ + msg.hwnd = NULL; + msg.replace = xno; + msg.delay = 0; + switch (ch) { + case '%': + msg.icon = "message"; + msg.background = RGB(173,206,247); + msg.foreground = RGB(0,0,0); + msg.contact = "Message"; + msg.beep = true; + msg.sound = "Message"; + return; + case '!': + msg.icon = "exclamation"; + msg.background = RGB(191,0,0); + msg.foreground = RGB(255,245,225); + msg.contact = "Error"; + msg.beep = true; + msg.sound = "Error"; + return; + case ' ': + default: + msg.icon = "information"; + msg.background = RGB(255,245,225); + msg.foreground = RGB(0,0,0); + msg.contact = "Notice"; + msg.beep = true; + msg.sound = "Notice"; + return; + } +} + +bool parseSimpleMessage(const std::string &buf, popup_t &msg, char sep) +{ + size_t p = buf.find(sep); + if (p == buf.npos) + msg.message = buf; + else { + msg.contact.assign(buf, 0, p); + msg.message.assign(buf, p+1, buf.npos); + } + return true; +} + +bool parseComplexMessage(const std::string &buf, popup_t &msg, char sep) +{ + const char *p = buf.c_str(); + const char *npos = strchr(p, sep); + bool passok = false; + + while ((p = npos)) { + ++p; + const char *cpos = strchr(p, ':'); + npos = strchr(p, sep); + + const char *wend = cpos; + if (!wend || npos && npos < wend) + wend = npos; + if (!wend) { + dbg_msg(Translate("Unterminated option."), SM_WARNING); + return false; + } + + std::string what(p, wend); + std::string arg; + if (wend == cpos && wend && npos) + arg.assign(cpos+1, npos); + else if (!cpos) + arg.erase(); + else + arg = cpos+1; + + if (!g_settings.password.empty() && !passok) { + if (what == "passwd" && arg == g_settings.password) { + passok = true; + continue; + } else + return false; + } + + if (what == "passwd") + ; + else if (what == "icon") + msg.icon = arg; + else if (what == "msg") { + if (!cpos) { + dbg_msg(Translate("No argument given to msg option."), SM_WARNING); + return false; + } else if (msg.replace != xno && msg.id.empty()) { + dbg_msg(Translate("Id is required for replacement."), SM_WARNING); + return false; + } + msg.message = arg; + return true; + } else if (what == "replace") { + if (arg == "yes") + msg.replace = xreplace; + else if (arg == "append") + msg.replace = xappend; + else if (arg == "prepend") + msg.replace = xprepend; + else if (arg == "no") + msg.replace = xno; + else + dbg_msg(Translate("Invalid argument for replace option: ") + arg, SM_WARNING); + } else if (what == "sound") { + if (arg.empty()) + msg.beep = false; + else { + msg.beep = true; + msg.sound = arg; + registerSound(arg); + } + } else if (what == "left") { + msg.left = arg; + } else if (what == "right") { + msg.right = arg; + } else if (what == "opened") { + msg.opened = arg; + } else if (what == "closed") { + msg.closed = arg; + } else if (what == "delay") { + msg.delay = atoi(arg.c_str()); + } else if (what == "id") { + msg.id = arg; + } else if (what == "bg") { + bool ok; + msg.background = parseColor(arg, ok); + if (!ok) + dbg_msg("Invalid color: " + arg, SM_WARNING); + } else if (what == "fg") { + bool ok; + msg.foreground = parseColor(arg, ok); + if (!ok) + dbg_msg("Invalid color: " + arg, SM_WARNING); + } else if (what == "from") + msg.contact = arg; + else if (what == "sep") { + if (arg.size() == 1) + sep = arg[0]; + else + dbg_msg("Invalid argument for sep option: " + arg, SM_WARNING); + } else if (what == "beep") { + if (arg == "1") + msg.beep = true; + else if (arg == "0") + msg.beep = false; + else + dbg_msg("Invalid argument for beep option: " + arg, SM_WARNING); + } else + dbg_msg("Unknown option: " + what, SM_NOTIFY); + } + return true; +} + +bool parseMessage(const std::string &abuf, popup_t &msg) +{ + if (abuf.empty()) { + dbg_msg(Translate("Empty message ignored."), SM_NOTIFY); + return false; + } + + std::string buf = abuf; + char sep = '#'; + if (buf.size() >= 3 && !isalnum(buf[0]) && buf[0] == buf[1] && buf[1] == buf[2]) { + sep = buf[0]; + buf.erase(0, 3); + } + + if (strchr("*!%", buf[0]) && sep != buf[0]) { + if (buf.size() < 2) return false; + loadDefaults(msg, buf[0]); + buf.erase(0, 1); + } else + loadDefaults(msg, ' '); + + if (buf[0] == sep) + return parseComplexMessage(buf, msg, sep); + else if (g_settings.password.empty()) + return parseSimpleMessage(buf, msg, sep); + else + return false; +} + +void processMessage(std::string buf) +{ + if (IsLogService){ + logservice_log(LOG_ID, NULL, (TCHAR *) buf.c_str()); + } + else { + if (g_settings.log_to_file) { + time_t t_; + time(&t_); + tm *t = localtime(&t_); + FILE *f = fopen(g_settings.log_filename.c_str(), "a"); + if (f) { + bool err = fprintf(f, "[%04i-%02i-%02i %02i:%02i:%02i] %s\n", + int(t->tm_year+1900), int(t->tm_mon+1), int(t->tm_mday), + int(t->tm_hour), int(t->tm_min), int(t->tm_sec), buf.c_str()) < 0; + if (fclose(f) == EOF || err) + dbg_msg(Translate("Failed to write to log file."), SM_WARNING); + } else + dbg_msg(Translate("Failed to open log file."), SM_WARNING); + } + } + + popup_t msg; + if (parseMessage(buf, msg)) { + + if (!msg.opened.empty()) { + bool close = false; + processAction(msg.opened, close); + if (close) + return; + } + + if (msg.replace) { + replaceMessage(msg); + return; + } + + showMessage(msg); + + if (g_settings.sound == g_settings.always + || g_settings.sound == g_settings.request + && msg.beep) + { + if (g_settings.use_pcspeaker) + Beep(650, 50); + else { + std::string sname = "NotifyAnything_" + + msg.sound; + SkinPlaySound(sname.c_str()); + } + } + } +} + +void initWinsock() +{ + EnterCS(&g_wsocklock); + if (g_firstrun) { + // probably not needed, but just in case... + // give PopUp a second to sort itself out + Sleep(1000); + g_firstrun = false; + + WSADATA wsaData; + int err = WSAStartup(MAKEWORD(2, 0), &wsaData); + if (err) + throw "WSAStartup failed"; + } + LeaveCS(&g_wsocklock); +} + +DWORD udptcpThreadFunc(LPVOID useUdp) +{ + try + { + initWinsock(); + + SOCKET sock = socket(AF_INET, useUdp ? SOCK_DGRAM : SOCK_STREAM, 0/*IPPROTO_UDP*/); + if (sock == INVALID_SOCKET) + throw "socket failed"; + + if (useUdp) + g_udp_socket = sock; + else + g_tcp_socket = sock; + + SOCKADDR_IN addr; + ZeroMemory(&addr, sizeof addr); + addr.sin_family = AF_INET; + addr.sin_port = htons(g_settings.port); + if (g_settings.local_only) { + addr.sin_addr.S_un.S_un_b.s_b1 = 127; + addr.sin_addr.S_un.S_un_b.s_b2 = 0; + addr.sin_addr.S_un.S_un_b.s_b3 = 0; + addr.sin_addr.S_un.S_un_b.s_b4 = 1; + } + + if (bind(sock, reinterpret_cast(&addr), sizeof addr)) + throw "bind failed"; + + SOCKADDR_IN from; + char buf[4097]; + + if (useUdp) { + while (!g_exit_threads) { + int fromSize = sizeof from; + int err = recvfrom(sock, buf, sizeof buf - 1, 0, reinterpret_cast(&from), &fromSize); + + if (g_exit_threads) + return 0; + + if (err == SOCKET_ERROR) + throw "socket error"; + + buf[err] = '\0'; + + if (err > 0) + processMessage(buf); + } + } else { + listen(sock, SOMAXCONN); + while (!g_exit_threads) { + int fromSize = sizeof from; + SOCKET msgsock = accept(sock, reinterpret_cast(&from), &fromSize); + + if (g_exit_threads) + return 0; + + if (msgsock == INVALID_SOCKET) + throw "socket error"; + + std::string totalbuf; + int totallen = 0; + while (true) { + int err = recv(msgsock, buf, sizeof buf - 1, 0); + if (err < 0) { + totalbuf.clear(); + break; + } else if (err == 0) + break; + else { + totallen += err; + buf[err] = '\0'; + totalbuf += buf; + } + } + if (!totalbuf.empty()) + processMessage(buf); + } + } + return 0; + } + catch (const char *err) { + std::string t = err; + t += "\nWSAGetLastError: "; + + DWORD ec = WSAGetLastError(); + + char buf[4096]; + strcpy(buf, Translate("N/A: Failed to format error message")); + + DWORD fm = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, ec, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 4096, NULL); + + if (!fm) { + t += Translate("N/A: FormatMessage failed, error code was 0x"); + char tbuf[10]; + t += itoa(ec, tbuf, 16); + } else + t += buf; + + MessageBoxA(0, t.c_str(), Translate("Error"), MB_OK); + return 1; + } +} + +void start_threads() +{ + g_exit_threads = false; + DWORD id; + g_udp_thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) udptcpThreadFunc, (LPVOID) 1, 0, &id); + g_tcp_thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) udptcpThreadFunc, NULL, 0, &id); +} + +void stop_threads() +{ + g_exit_threads = true; + shutdown(g_udp_socket, 2); + shutdown(g_tcp_socket, 2); + closesocket(g_udp_socket); + closesocket(g_tcp_socket); + WaitForSingleObject(g_udp_thread, INFINITE); + WaitForSingleObject(g_tcp_thread, INFINITE); +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + IsLogService = ServiceExists(MS_LOGSERVICE_REGISTER) != 0; + if (IsLogService) + logservice_register(LOG_ID, LPGENT(LOG_ID), NULL, NULL); + + return 0; +} + +extern "C" int __declspec(dllexport) Load() +{ + g_firstrun = true; + mir_getLP(&pluginInfo); + + char buf[MAX_PATH+1]; + strcpy(buf, "."); + g_mirandaDir = getcwd(buf, MAX_PATH); + + InitializeCriticalSection(&g_popups_cs); + InitializeCriticalSection(&g_wsocklock); + + registerSound("Notice"); + registerSound("Message"); + registerSound("Error"); + + load_settings(); + + HookEvent(ME_OPT_INITIALISE, OptionsInitialize); + HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + + start_threads(); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + stop_threads(); + WSACleanup(); + + DeleteCriticalSection(&g_popups_cs); + DeleteCriticalSection(&g_wsocklock); + return 0; +} diff --git a/plugins/NotifyAnything/src/options.cpp b/plugins/NotifyAnything/src/options.cpp new file mode 100644 index 0000000000..53c06ecf23 --- /dev/null +++ b/plugins/NotifyAnything/src/options.cpp @@ -0,0 +1,209 @@ + +#include + +#include "common.h" +#include "resource.h" + +NASettings g_settings; + +INT_PTR CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + char buf[10]; + CheckDlgButton(hwndDlg, NA_LOCAL_CHECK, g_settings.local_only ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, NA_DEBUG_MSG_CHECK, g_settings.debug_messages ? BST_CHECKED : BST_UNCHECKED); + if (IsLogService) { + LS_LOGINFO pli; + pli.szID = LOG_ID; + pli.hContact = NULL; + pli.szLogPath = NULL; + pli.Flags = 0; + pli.cbSize = sizeof(LS_LOGINFO); + if (!CallService(MS_LOGSERVICE_GETLOGINFO, (WPARAM)(LS_LOGINFO *) &pli, 0)) { + CheckDlgButton(hwndDlg, NA_LOG_CHECK, (pli.Flags && LSLI_LOGENABLED) ? BST_CHECKED : BST_UNCHECKED); + } + std::tstring InLogService = TranslateT("Services"); + InLogService += _T(" -> "); + InLogService += TranslateT("LogService"); + InLogService += _T(" -> "); + InLogService += TranslateT(LOG_ID); + SetDlgItemText(hwndDlg, NA_LOG_FILENAME, InLogService.c_str()); + } + else { + CheckDlgButton(hwndDlg, NA_LOG_CHECK, g_settings.log_to_file ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemTextA(hwndDlg, NA_LOG_FILENAME, g_settings.log_filename.c_str()); + } + EnableWindow(GetDlgItem(hwndDlg, NA_LOG_CHECK), !IsLogService); + EnableWindow(GetDlgItem(hwndDlg, NA_LOG_FILENAME), !IsLogService); + EnableWindow(GetDlgItem(hwndDlg, NA_LOG_BROWSE), !IsLogService); + EnableWindow(GetDlgItem(hwndDlg, NA_DEBUG_MSG_CHECK), IsDlgButtonChecked(hwndDlg, NA_LOG_CHECK) ? 1 : 0); + CheckDlgButton(hwndDlg, NA_PCSPEAKER_CHECK, g_settings.use_pcspeaker ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, NA_ALLOW_EXECUTE, g_settings.allow_execute ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemTextA(hwndDlg, NA_PORT, itoa(g_settings.port, buf, 10)); + SetDlgItemTextA(hwndDlg, NA_PASSWORD, g_settings.password.c_str()); + UINT state; + switch (g_settings.sound) { + case g_settings.always: + state = BST_CHECKED; break; + case g_settings.never: + state = BST_UNCHECKED; break; + case g_settings.request: + default: + state = BST_INDETERMINATE; break; + } + CheckDlgButton(hwndDlg, NA_SOUND_CHECK, state); + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case NA_SOUND_CHECK: + case NA_PCSPEAKER_CHECK: + case NA_LOCAL_CHECK: + case NA_DEBUG_MSG_CHECK: + case NA_LOG_CHECK: + case NA_PORT: + case NA_PASSWORD: + case NA_LOG_FILENAME: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + + if (HIWORD(wParam) == BN_CLICKED) { + switch (LOWORD(wParam)) { + case NA_LOG_BROWSE: + TCHAR szTemp[MAX_PATH+1], szTemp1[MAX_PATH+1], szProfileDir[MAX_PATH+1]; + GetDlgItemText(hwndDlg, NA_LOG_FILENAME, szTemp, MAX_PATH); + OPENFILENAME ofn = {0}; + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szTemp; + ofn.nMaxFile = MAX_PATH; + ofn.hwndOwner = hwndDlg; + ofn.lpstrFilter = TranslateT("Log (*.log)\0*.log\0Text (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"); + ofn.nFilterIndex = 1; + // Use profile directory as default, if path is not specified + CallService(MS_DB_GETPROFILEPATH, (WPARAM)MAX_PATH, (LPARAM) szProfileDir); + ofn.lpstrInitialDir = szProfileDir; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt = _T("log"); + if ( GetOpenFileName(&ofn)) { + CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)(char*) szTemp, (LPARAM)(char*) szTemp1); + SetDlgItemText(hwndDlg, NA_LOG_FILENAME, szTemp1); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); + } + + return 0; + } + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom != 0) + break; + + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + return TRUE; + + case PSN_APPLY: { + UINT state = IsDlgButtonChecked(hwndDlg, NA_SOUND_CHECK); + NASettings s; + switch (state) { + case BST_CHECKED: + s.sound = s.always; break; + case BST_INDETERMINATE: + s.sound = s.request; break; + case BST_UNCHECKED: + default: + s.sound = s.never; break; + } + s.local_only = IsDlgButtonChecked(hwndDlg, NA_LOCAL_CHECK) != BST_UNCHECKED; + s.debug_messages = IsDlgButtonChecked(hwndDlg, NA_DEBUG_MSG_CHECK) != BST_UNCHECKED; + s.log_to_file = IsDlgButtonChecked(hwndDlg, NA_LOG_CHECK) != BST_UNCHECKED; + s.use_pcspeaker = IsDlgButtonChecked(hwndDlg, NA_PCSPEAKER_CHECK) != BST_UNCHECKED; + s.allow_execute = IsDlgButtonChecked(hwndDlg, NA_ALLOW_EXECUTE) != BST_UNCHECKED; + + TCHAR buf[1000]; + if (!GetDlgItemText(hwndDlg, NA_PORT, buf, sizeof buf - 1)) + buf[0] = '\0'; + int port = _ttoi(buf); + if (port <= 0 || port > 65535) + MessageBox(0, TranslateT("Invalid port number"), TranslateT("NotifyAnything"), MB_ICONWARNING | MB_OK); + else + s.port = port; + + if (!GetDlgItemText(hwndDlg, NA_PASSWORD, buf, sizeof buf - 1)) + buf[0] = '\0'; + s.password = _T2A(buf); + + if (!IsLogService) { + if (!GetDlgItemText(hwndDlg, NA_LOG_FILENAME, buf, sizeof buf - 1)) + buf[0] = '\0'; + s.log_filename = _T2A(buf); + } + + g_settings = s; + save_settings(); + stop_threads(); + start_threads(); + return TRUE; + } + } + break; + } + return FALSE; +} + +void save_settings() +{ + db_set_b(NULL, PlugName, "local_only", g_settings.local_only); + db_set_b(NULL, PlugName, "debug_messages", g_settings.debug_messages); + db_set_b(NULL, PlugName, "log_to_file", g_settings.log_to_file); + db_set_b(NULL, PlugName, "beep", g_settings.sound); + db_set_b(NULL, PlugName, "use_pcspeaker", g_settings.use_pcspeaker); + db_set_b(NULL, PlugName, "allow_execute", g_settings.allow_execute); + db_set_dw(NULL, PlugName, "port", g_settings.port); + db_set_s(NULL, PlugName, "password", g_settings.password.c_str()); + db_set_s(NULL, PlugName, "log_filename", g_settings.log_filename.c_str()); +} + +void load_settings() +{ + g_settings.local_only = db_get_b(NULL, PlugName, "local_only", 1) != 0; + g_settings.debug_messages = db_get_b(NULL, PlugName, "debug_messages", 0) != 0; + g_settings.log_to_file = db_get_b(NULL, PlugName, "log_to_file", 0) != 0; + g_settings.sound = NASettings::sound_t(db_get_b(NULL, PlugName, "beep", g_settings.request)); + g_settings.use_pcspeaker = db_get_b(NULL, PlugName, "use_pcspeaker", 0) != 0; + g_settings.allow_execute = db_get_b(NULL, PlugName, "allow_execute", 0) != 0; + g_settings.port = db_get_dw(NULL, PlugName, "port", 12001); + + DBVARIANT dbv; + if(!DBGetContactSetting(NULL, PlugName, "password", &dbv)) { + g_settings.password = dbv.pszVal; + DBFreeVariant(&dbv); + } + + if(!DBGetContactSetting(NULL, PlugName, "log_filename", &dbv)) { + g_settings.log_filename = dbv.pszVal; + DBFreeVariant(&dbv); + } + else + g_settings.log_filename = g_mirandaDir + "\\"+LOG_ID+".log"; +} + +int OptionsInitialize(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { sizeof(odp) }; + odp.pszTemplate = MAKEINTRESOURCEA(NA_OPTIONS); + odp.pfnDlgProc = DlgProcOpts; + odp.pszTitle = "Notify Anything"; + odp.pszGroup = Translate("Plugins"); + odp.position = 100000000; + odp.hInstance = hInst; + odp.groupPosition = 910000000; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + return 0; +} diff --git a/plugins/NotifyAnything/src/resource.h b/plugins/NotifyAnything/src/resource.h new file mode 100644 index 0000000000..8eee335059 --- /dev/null +++ b/plugins/NotifyAnything/src/resource.h @@ -0,0 +1,27 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by NotifyAnything.rc +// +#define NA_OPTIONS 106 +#define NA_LOCAL_CHECK 1002 +#define NA_SOUND_CHECK 1007 +#define NA_LOG_CHECK 1008 +#define NA_DEBUG_MSG_CHECK 1009 +#define NA_PCSPEAKER_CHECK 1011 +#define NA_PORT 1012 +#define NA_ALLOW_EXECUTE 1013 +#define NA_PASSWORD 1014 +#define NA_LOG_FILENAME 1015 +#define NA_LOG_SELECT 1016 +#define NA_LOG_BROWSE 1017 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1018 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/NotifyAnything/src/stdafx.cpp b/plugins/NotifyAnything/src/stdafx.cpp new file mode 100644 index 0000000000..7a516adf58 --- /dev/null +++ b/plugins/NotifyAnything/src/stdafx.cpp @@ -0,0 +1,18 @@ +/* +Copyright (C) 2012 Miranda NG team (http://miranda-ng.org) + +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 version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "common.h" \ No newline at end of file diff --git a/plugins/Nudge/src/main.cpp b/plugins/Nudge/src/main.cpp index 67a5b3526c..8d0f495101 100644 --- a/plugins/Nudge/src/main.cpp +++ b/plugins/Nudge/src/main.cpp @@ -363,7 +363,7 @@ void RegisterToDbeditorpp(void) CallService("DBEditorpp/RegisterSingleModule", (WPARAM)"Nudge", 0); } -static IconItem iconList[] = +static IconItem iconList[] = { { LPGEN("Nudge as Default"), "Nudge_Default", IDI_NUDGE } }; @@ -465,7 +465,6 @@ int AccListChanged(WPARAM wParam,LPARAM lParam) HANDLE hShakeClist=NULL,hShakeChat=NULL,hNudgeSend=NULL,hNudgeShowMenu=NULL; extern "C" int __declspec(dllexport) Load(void) { - mir_getLP(&pluginInfo); g_hEventModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED,ModulesLoaded); -- cgit v1.2.3