From 5b0a53a6d3f1b8d70b34631d96d3815d0a334dd3 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 16 Jul 2012 16:31:53 +0000 Subject: Clist_mw, Clist_nicer, CmdLine, Console: folder structure change git-svn-id: http://svn.miranda-ng.org/main/trunk@988 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CmdLine/src/CmdLine.cpp | 87 ++ plugins/CmdLine/src/commonheaders.h | 112 ++ plugins/CmdLine/src/hooked_events.cpp | 113 ++ plugins/CmdLine/src/hooked_events.h | 43 + plugins/CmdLine/src/mimcmd_data.cpp | 43 + plugins/CmdLine/src/mimcmd_data.h | 120 ++ plugins/CmdLine/src/mimcmd_handlers.cpp | 2307 +++++++++++++++++++++++++++++++ plugins/CmdLine/src/mimcmd_handlers.h | 55 + plugins/CmdLine/src/mimcmd_ipc.cpp | 105 ++ plugins/CmdLine/src/mimcmd_ipc.h | 56 + plugins/CmdLine/src/resource.h | 15 + plugins/CmdLine/src/services.cpp | 106 ++ plugins/CmdLine/src/services.h | 34 + plugins/CmdLine/src/utils.cpp | 461 ++++++ plugins/CmdLine/src/utils.h | 62 + plugins/CmdLine/src/version.h | 49 + 16 files changed, 3768 insertions(+) create mode 100644 plugins/CmdLine/src/CmdLine.cpp create mode 100644 plugins/CmdLine/src/commonheaders.h create mode 100644 plugins/CmdLine/src/hooked_events.cpp create mode 100644 plugins/CmdLine/src/hooked_events.h create mode 100644 plugins/CmdLine/src/mimcmd_data.cpp create mode 100644 plugins/CmdLine/src/mimcmd_data.h create mode 100644 plugins/CmdLine/src/mimcmd_handlers.cpp create mode 100644 plugins/CmdLine/src/mimcmd_handlers.h create mode 100644 plugins/CmdLine/src/mimcmd_ipc.cpp create mode 100644 plugins/CmdLine/src/mimcmd_ipc.h create mode 100644 plugins/CmdLine/src/resource.h create mode 100644 plugins/CmdLine/src/services.cpp create mode 100644 plugins/CmdLine/src/services.h create mode 100644 plugins/CmdLine/src/utils.cpp create mode 100644 plugins/CmdLine/src/utils.h create mode 100644 plugins/CmdLine/src/version.h (limited to 'plugins/CmdLine/src') diff --git a/plugins/CmdLine/src/CmdLine.cpp b/plugins/CmdLine/src/CmdLine.cpp new file mode 100644 index 0000000000..4d19c19ccc --- /dev/null +++ b/plugins/CmdLine/src/CmdLine.cpp @@ -0,0 +1,87 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +char ModuleName[] = "CmdLine"; +HINSTANCE hInstance; +int hLangpack; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_DISPLAY_NAME, + VERSION, + __DESC, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, //unicode aware + {0x2f1a117c, 0x3c1b, 0x4c01, {0x89, 0xea, 0x6d, 0x8f, 0xd8, 0x5a, 0x9b, 0x4c}} //{2f1a117c-3c1b-4c01-89ea-6d8fd85a9b4c} +}; //not used + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +static const MUUID interfaces[] = {MIID_CMDLINE, MIID_LAST}; + +extern "C" __declspec(dllexport) const MUUID *MirandaPluginInterfaces() +{ + return interfaces; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfo); + +// InitServices(); + if (InitServer()) + { + MessageBox(0, "Could not initialize CmdLine plugin property", "Error", MB_ICONEXCLAMATION | MB_OK); + } + + HookEvents(); + + return 0; +} + +extern "C" int __declspec(dllexport) Unload() +{ + bWaitForUnload = 0; + + UnhookEvents(); + + DestroyServer(); + + return 0; +} + +bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + hInstance = hinstDLL; + if (fdwReason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(hinstDLL); + } + + return TRUE; +} \ No newline at end of file diff --git a/plugins/CmdLine/src/commonheaders.h b/plugins/CmdLine/src/commonheaders.h new file mode 100644 index 0000000000..b7a332c9d6 --- /dev/null +++ b/plugins/CmdLine/src/commonheaders.h @@ -0,0 +1,112 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_CMDLINE_COMMONHEADERS_H +#define M_CMDLINE_COMMONHEADERS_H + +#define MIRANDA_VER 0x0A00 +#define _CRT_SECURE_NO_WARNINGS + +#define MIID_CMDLINE {0xcf8d9633, 0x7744, 0x4a5c, {0xb4, 0x8c, 0x2b, 0xd6, 0x36, 0xa4, 0x6c, 0xde}} + +#include +#include +#include +#include +#include + +#include "newpluginapi.h" +#include "m_database.h" +#include "m_system.h" +#include "m_clist.h" +#include "m_clui.h" +#include "m_contacts.h" +#include "m_langpack.h" +#include "m_options.h" +#include "m_protosvc.h" +#include "m_protocols.h" +#include "m_popup.h" +#include "m_utils.h" +#include "m_message.h" +#include "m_ignore.h" + +#include "m_versioninfo.h" +#include "m_statusplugins.h" + +#include "version.h" +#include "utils.h" +#include "resource.h" +#include "hooked_events.h" +#include "utils.h" +#include "mimcmd_ipc.h" +#include "services.h" +#include "mimcmd_handlers.h" +#include "mimcmd_data.h" + +extern char ModuleName[]; +extern HINSTANCE hInstance; + +//extern PLUGINLINK *pluginLink; + +extern int bUseANSIStrings; + +extern int bWaitForUnload; + +#define ID_ICQ_EXIT 40001 + +static __inline int mir_old_snprintf(char *buffer, size_t count, const char* fmt, ...) { + va_list va; + int len; + + va_start(va, fmt); + len = _vsnprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +static __inline int mir_old_sntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, ...) { + va_list va; + int len; + + va_start(va, fmt); + len = _vsntprintf(buffer, count-1, fmt, va); + va_end(va); + buffer[count-1] = 0; + return len; +} + +static __inline int mir_old_vsnprintf(char *buffer, size_t count, const char* fmt, va_list va) { + int len; + + len = _vsnprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +static __inline int mir_old_vsntprintf(TCHAR *buffer, size_t count, const TCHAR* fmt, va_list va) { + int len; + + len = _vsntprintf(buffer, count-1, fmt, va); + buffer[count-1] = 0; + return len; +} + +#endif //M_CMDLINE_COMMONHEADERS_H \ No newline at end of file diff --git a/plugins/CmdLine/src/hooked_events.cpp b/plugins/CmdLine/src/hooked_events.cpp new file mode 100644 index 0000000000..6ccac9080a --- /dev/null +++ b/plugins/CmdLine/src/hooked_events.cpp @@ -0,0 +1,113 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +HANDLE hModulesLoaded; +HANDLE hOptionsInitialize; +HANDLE hShutdown; +HANDLE hProtoAck; + +int bShouldProcessAcks = FALSE; + +ACKDATA acks[50] = {0}; +int cAcks = sizeof(acks) / sizeof(acks[0]); + +int HookEvents() +{ + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + hShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown); + hProtoAck = HookEvent(ME_PROTO_ACK, OnProtoAck); +// hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, OnOptionsInitialise); + + return 0; +} + +int UnhookEvents() +{ + UnhookEvent(hModulesLoaded); + UnhookEvent(hShutdown); + UnhookEvent(OnProtoAck); +// UnhookEvent(hOptionsInitialize); + + return 0; +} + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + StartServer(); + + return 0; +} + +int OnShutdown(WPARAM wParam, LPARAM lParam) +{ + SetEvent(heServerClose); //tell the listening server to stop + + return 0; +} + +int QueueAck(ACKDATA *ack) +{ + int i; + for (i = cAcks - 1; i > 0; i--) + { + acks[i] = acks[i - 1]; + } + + acks[0] = *ack; + + return 0; +} + +int ClearAckQueue() +{ + memset(acks, 0, cAcks * sizeof(ACKDATA)); + + return 0; +} + +ACKDATA *GetAck(HANDLE hProcess) +{ + int i; + for (i = 0; i < cAcks; i++) + { + if (acks[i].hProcess == hProcess) + { + return &acks[i]; + } + } + + return NULL; +} + +int OnProtoAck(WPARAM wParam, LPARAM lParam) +{ + if (bShouldProcessAcks) + { + ACKDATA *ack = (ACKDATA *) lParam; + if ((ack) && (ack->type == ACKTYPE_MESSAGE)) //if it's a message ack + { + QueueAck(ack); + } + } + + return 0; +} \ No newline at end of file diff --git a/plugins/CmdLine/src/hooked_events.h b/plugins/CmdLine/src/hooked_events.h new file mode 100644 index 0000000000..11b9fea363 --- /dev/null +++ b/plugins/CmdLine/src/hooked_events.h @@ -0,0 +1,43 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + + +#ifndef M_CMDLINE_HOOKED_EVENTS_H +#define M_CMDLINE_HOOKED_EVENTS_H + +extern HANDLE hModulesLoaded; +extern HANDLE hOptionsInitialise; +extern HANDLE hShutdown; +extern HANDLE hProtoAck; + +extern int bShouldProcessAcks; + +int HookEvents(); +int UnhookEvents(); + +int ClearQueue(); +ACKDATA *GetAck(HANDLE hProcess); + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam); +int OnOptionsInitialise(WPARAM wParam, LPARAM lParam); +int OnShutdown(WPARAM wParam, LPARAM lParam); +int OnProtoAck(WPARAM wParam, LPARAM lParam); + +#endif \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_data.cpp b/plugins/CmdLine/src/mimcmd_data.cpp new file mode 100644 index 0000000000..95550ed778 --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_data.cpp @@ -0,0 +1,43 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +TCommand mimCommands[] = {{MIMCMD_STATUS, "status", MIMCMD_HELP_STATUS}, + {MIMCMD_AWAYMSG, "awaymsg", MIMCMD_HELP_AWAYMSG}, + {MIMCMD_XSTATUS, "xstatus", MIMCMD_HELP_XSTATUS}, + {MIMCMD_POPUPS, "popups", MIMCMD_HELP_POPUPS}, + {MIMCMD_SOUNDS, "sounds", MIMCMD_HELP_SOUNDS}, + {MIMCMD_CLIST, "clist", MIMCMD_HELP_CLIST}, + {MIMCMD_QUIT, "quit", MIMCMD_HELP_QUIT}, + {MIMCMD_HELP, "help", MIMCMD_HELP_HELP}, + {MIMCMD_EXCHANGE, "exchange", MIMCMD_HELP_EXCHANGE}, + {MIMCMD_YAMN, "yamn", MIMCMD_HELP_YAMN}, + {MIMCMD_CALLSERVICE, "callservice", MIMCMD_HELP_CALLSERVICE}, + {MIMCMD_MESSAGE, "message", MIMCMD_HELP_MESSAGE}, + {MIMCMD_DATABASE, "db", MIMCMD_HELP_DATABASE}, + {MIMCMD_PROXY, "proxy", MIMCMD_HELP_PROXY}, + {MIMCMD_CONTACTS, "contacts", MIMCMD_HELP_CONTACTS}, + {MIMCMD_HISTORY, "history", MIMCMD_HELP_HISTORY}, + {MIMCMD_VERSION, "version", MIMCMD_HELP_VERSION}, + {MIMCMD_SETNICKNAME, "setnickname", MIMCMD_HELP_SETNICKNAME}, + {MIMCMD_IGNORE, "ignore", MIMCMD_HELP_IGNORE}, + }; +int cMimCommands = sizeof(mimCommands) / sizeof(mimCommands[0]); \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_data.h b/plugins/CmdLine/src/mimcmd_data.h new file mode 100644 index 0000000000..2ef39bc4dd --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_data.h @@ -0,0 +1,120 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_MIMCMD_DATA_H +#define M_MIMCMD_DATA_H + +#define COMMAND_SIZE 64 +#define HELP_SIZE 1024 +#define REPLY_SIZE 8096 + +#define MIMFOLDER_SIZE 300 + +#define MAX_ARGUMENTS 20 +#define ARGUMENT_SIZE 512 + +typedef char TArgument[ARGUMENT_SIZE]; + +struct TReply{ + int code; + char message[REPLY_SIZE]; + static const int cMessage = REPLY_SIZE; +}; + +typedef TReply *PReply; + +struct TCommand{ + long ID; + char command[COMMAND_SIZE]; + char help[HELP_SIZE]; +}; + +typedef TCommand *PCommand; + +struct TSharedData{ + char mimFolder[MIMFOLDER_SIZE]; + TCommand command; + TArgument arguments[MAX_ARGUMENTS]; + int cArguments; + TReply reply; + int instances; +}; + +typedef TSharedData *PSharedData; + +//return codes +#define MIMRES_SUCCESS 0 //command was successful +#define MIMRES_FAILURE 1 //command was not successful +#define MIMRES_NOTFOUND 2 //command not found +#define MIMRES_UNKNOWNPARAM 3 //command parameter is unknown +#define MIMRES_NOMIRANDA 4 //could not link to Miranda +#define MIMRES_WRONGPARAMSCOUNT 5 //wrong number of parameters + + +#define MIMCMD_UNKNOWN -1 //unknown command +#define MIMCMD_STATUS 1 +#define MIMCMD_AWAYMSG 2 +#define MIMCMD_XSTATUS 3 +#define MIMCMD_POPUPS 4 +#define MIMCMD_SOUNDS 5 +#define MIMCMD_CLIST 6 +#define MIMCMD_QUIT 7 +#define MIMCMD_HELP 8 +#define MIMCMD_EXCHANGE 9 +#define MIMCMD_YAMN 10 +#define MIMCMD_CALLSERVICE 11 +#define MIMCMD_MESSAGE 12 +#define MIMCMD_DATABASE 13 +#define MIMCMD_PROXY 14 +#define MIMCMD_CONTACTS 15 +#define MIMCMD_HISTORY 16 +#define MIMCMD_VERSION 17 +#define MIMCMD_SETNICKNAME 18 +#define MIMCMD_IGNORE 19 + +#define MIMCMD_HELP_STATUS "Change account status either globally or per account.\nUsage: status [].\nPossible values for are: offline, online, away, dnd, na, occupied, freechat, invisible, onthephone, outtolunch.\n is the name of the account. If it's not specified then the command will issue a global status change." +#define MIMCMD_HELP_AWAYMSG "Change away message either globally or per account.\nUsage: awaymsg [].\n is the new away message.\n is an optional parameter specifying the account to set the away message for. If not specified then the away message will be set globally." +#define MIMCMD_HELP_XSTATUS "Change extended status either globally or per account.\nUsage xstatus [].\n is the new extended status to set. Possible values are:...\n is an optional parameter specifying the account for which extended status is set. If not specified then extended status for all accounts will be changed.\nNOTE: Not all accounts/protocols support extended status." +#define MIMCMD_HELP_POPUPS "Disables or enables popups display.\nUsage popups (disable | enable | toggle).\nThe command will either enable or disable popups display." +#define MIMCMD_HELP_SOUNDS "Disables or enables sounds.\nUsage: sounds (disable | enable | toggle).\nThe command will either disable or enable sounds." +#define MIMCMD_HELP_CLIST "Hides or shows the contact list window.\nUsage: clist (show | hide | toggle).\nThe command will either show or hide the contact list window." +#define MIMCMD_HELP_QUIT "Closes Miranda.\nUsage: quit [wait]. If wait is used then the command will return only when CmdLine plugin has been unloaded by Miranda." +#define MIMCMD_HELP_HELP "Provides help on other commands.\nUsage: help [].\nThe command will print help information for other commands. If run without any parameters it will print available commands." +#define MIMCMD_HELP_EXCHANGE "Notifies Exchange plugin to check for email.\nUsage: exchange check" +#define MIMCMD_HELP_YAMN "Notifies YAMN plugin to check for email.\nUsage: yamn check." +#define MIMCMD_HELP_CALLSERVICE "Calls a Miranda service.\nUsage: callservice (d|s) (d|s). The command will call Miranda service using wParam and lParam as arguments; the first letter of the paramater must be either 'd' if the parameter is a decimal number or 's' if the parameter is a string. Be careful when you use this function as you can only pass numbers and strings as data.\nNOTE:If you pass invalid data to a service Miranda might crash." +#define MIMCMD_HELP_MESSAGE "Sends a message to the specified contact(s).\nUsage: message [ [ [...]]] . The command will send to the specified contact(s) - at least one contact must be specified - all parameters except the last one are considered recipients.\n has the following format:[:]. is the contact display name or unique ID and is an optional parameter representing the account of the contact (useful in case there is more than one contact with the same name).\nNOTE:The message string cannot exceed 512 characters." +#define MIMCMD_HELP_DATABASE "Allows you to manage database settings.\nUsage:\n db set (b|i|d|s|w)\n db delete \n db get .\nThe command can set a database entry to the specified value (if the entry does not exist it will be created) as well as read or delete a specified database entry. is the name of the module where the key should be located, is the name of the key and is the value to be written. A character must be placed before in order to specify what kind of data to write: b - byte, i - integer (word), d - double word, s - string, w - wide string." +#define MIMCMD_HELP_PROXY "Configures proxy settings either globally or per account.\nUsage: proxy (global|) [].\n is one of the following settings:\n status (disable | enable | toggle).\n server " +#define MIMCMD_HELP_CONTACTS "Allows you to search/list contacts or open a message windows for specified contacts.\nUsage:\n contacts list [ [account:] [id:] [status:] [ [...]]]. The command will search all contacts and display the ones matching the search criteria. To search for a specific account use the keyword 'account:'. To search for contacts that have a certain id use the keyword 'id:'. To search for contacts that have a certain status use 'status:'.\n contacts open [ [account:] [id:] [status:] [ [...]]]. The command will open a message window for all contacts that match the search criteria. To search for a specific account use the keyword 'account:'. To search for contacts that have a certain id use the keyword 'id:'. To search for contacts that have a certain status use 'status:'. If no keyword is specified the command will open a message window for all contacts that have unread messages." +#define MIMCMD_HELP_HISTORY "Shows history or unread messages for a contact.\nUsage:\n history .\n is one of the following commands:\n unread - show unread messages for that contact.\n show - show history from event number to . If any number is negative it is interpreted as a relative index from the last event number + 1 (so the last event for a contact is -1)." +#define MIMCMD_HELP_VERSION "Shows version information for Miranda and CmdLine plugin. If VersionInfo plugin is installed it will use its report instead.\nUsage:\n version. The command will print Miranda's and CmdLine's version numbers or, if VersionInfo plugin is installed, it will show VersionInfo's report." +#define MIMCMD_HELP_SETNICKNAME "Changes the user's nickname on the given protocol to the new name.\nUsage:\n setnickname new_nickname" +#define MIMCMD_HELP_IGNORE "Ignores or removes ignore flags for specific contacts.\nUsage:\n ignore (block | unblock) [ [ [..]]]. Ignores or removes ignore flags for the specified contacts." + +#define MIMMEM_REPLY 1 //data is a PReply structure + +extern TCommand mimCommands[]; +extern int cMimCommands; + +void InitCommandData(); +void DestroyCommandData(); + +#endif //M_MIMCMD_DATA_H \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_handlers.cpp b/plugins/CmdLine/src/mimcmd_handlers.cpp new file mode 100644 index 0000000000..9b2d89b696 --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_handlers.cpp @@ -0,0 +1,2307 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +#define STATE_UNKNOWN -1 +#define STATE_OFF 0 +#define STATE_ON 1 +#define STATE_TOGGLE 2 + +#define PROXY_SOCKS4 1 +#define PROXY_SOCKS5 2 +#define PROXY_HTTP 3 +#define PROXY_HTTPS 4 + +#define VALUE_UNKNOWN -1 +#define VALUE_ERROR 0 +#define VALUE_BYTE 1 +#define VALUE_WORD 2 +#define VALUE_DWORD 3 +#define VALUE_STRING 4 +#define VALUE_WIDE 5 + +__inline static int matches(char *command, char *lower) +{ + return ((strcmp(lower, command) == 0) || (strcmp(lower, Translate(command)) == 0)); +} + +int Get2StateValue(char *state) +{ + char lower[512]; + STRNCPY(lower, state, sizeof(lower)); + _strlwr(lower); + + //if ((strcmp(lower, "enable") == 0) || (strcmp(lower, "show") == 0) || (strcmp(lower, "on") == 0)) + if ((matches("enable", lower)) || (matches("show", lower)) || (matches("on", lower))) + { + return STATE_ON; + } + + //if ((strcmp(lower, "disable") == 0) || (strcmp(lower, "hide") == 0) || (strcmp(lower, "off") == 0)) + if ((matches("disable", lower)) || (matches("hide", lower)) || (matches("off", lower))) + { + return STATE_OFF; + } + + //if (strcmp(lower, "toggle") == 0) + if (matches("toggle", lower)) + { + return STATE_TOGGLE; + } + + return STATE_UNKNOWN; +} + +int AccountName2Protocol(const char *accountName, OUT char *uniqueProtocolName, size_t length) +{ + int count; + PROTOACCOUNT **accounts = NULL; + + ProtoEnumAccounts(&count, &accounts); + + STRNCPY(uniqueProtocolName, accountName, length); + + for (int i = 0; i < count; i++) + { + if (accounts[i]->bIsEnabled) + { + if (_stricmp(accountName, accounts[i]->tszAccountName) == 0) + { + STRNCPY(uniqueProtocolName, accounts[i]->szModuleName, length); + + return 0; + } + + //the account name may be unicode, try comparing with an unicode string too + char *account = mir_u2a((wchar_t *) accounts[i]->tszAccountName); + if (_stricmp(accountName, account) == 0) + { + STRNCPY(uniqueProtocolName, accounts[i]->szModuleName, length); + + mir_free(account); + return 0; + } + + mir_free(account); + } + } + + return 1; +} + +void HandleCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (command->ID) + { + case MIMCMD_STATUS: + { + HandleStatusCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_AWAYMSG: + { + HandleAwayMsgCommand(command, argv, argc, reply); + + break; + } + // + //case MIMCMD_XSTATUS: + //{ + // + // break; + //} + + case MIMCMD_POPUPS: + { + HandlePopupsCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_SOUNDS: + { + HandleSoundsCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_CLIST: + { + HandleClistCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_QUIT: + { + HandleQuitCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_EXCHANGE: + { + HandleExchangeCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_YAMN: + { + HandleYAMNCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_CALLSERVICE: + { + HandleCallServiceCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_MESSAGE: + { + HandleMessageCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_DATABASE: + { + HandleDatabaseCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_PROXY: + { + HandleProxyCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_CONTACTS: + { + HandleContactsCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_HISTORY: + { + HandleHistoryCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_VERSION: + { + HandleVersionCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_SETNICKNAME: + { + HandleSetNicknameCommand(command, argv, argc, reply); + + break; + } + + case MIMCMD_IGNORE: + { + HandleIgnoreCommand(command, argv, argc, reply); + + break; + } + + default: + { + reply->code = MIMRES_NOTFOUND; + mir_snprintf(reply->message, reply->cMessage, Translate("Command '%s' is not currently supported."), command->command); + + break; + } + } +} + +void HandleWrongParametersCount(PCommand command, PReply reply) +{ + reply->code = MIMRES_WRONGPARAMSCOUNT; + mir_snprintf(reply->message, reply->cMessage, Translate("Wrong number of parameters for command '%s'."), command->command); +} + +void HandleUnknownParameter(PCommand command, char *param, PReply reply) +{ + reply->code = MIMRES_UNKNOWNPARAM; + mir_snprintf(reply->message, reply->cMessage, Translate("Unknown parameter '%s' for command '%s'."), param, command->command); +} + +int ParseValueParam(char *param, void *&result) +{ + int ok = VALUE_UNKNOWN; + if (strlen(param) > 0) + { + switch (*param) + { + case 's': + { + size_t len = strlen(param); //- 1 + 1 + result = (char *) malloc(len * sizeof(char)); + STRNCPY((char *) result, param + 1, len); + ((char *) result)[len - 1] = 0; + + ok = VALUE_STRING; + + break; + } + + case 'w': + { + size_t len = strlen(param); + result = (WCHAR *) malloc(len * sizeof(WCHAR)); + char *buffer = (char *) malloc(len * sizeof(WCHAR)); + STRNCPY(buffer, param + 1, len); + + MultiByteToWideChar(CP_ACP, 0, buffer, -1, (WCHAR *) result, (int) len); + + free(buffer); + + ok = VALUE_WIDE; + + break; + } + + case 'b': + { + result = (char *) malloc(sizeof(char)); + long tmp; + char *stop; + + tmp = strtol(param + 1, &stop, 10); + * ((char *) result) = tmp; + + ok = (*stop == 0) ? VALUE_BYTE : VALUE_ERROR; + + break; + } + + case 'i': + { + result = (int *) malloc(sizeof(int)); + long tmp; + char *stop; + + tmp = strtol(param + 1, &stop, 10); + * ((int *) result) = tmp; + + ok = (*stop == 0) ? VALUE_WORD : VALUE_ERROR; + + break; + } + + case 'd': + { + result = (long *) malloc(sizeof(long)); + char *stop; + * ((long *) result) = strtol(param + 1, &stop, 10); + + ok = (*stop == 0) ? VALUE_DWORD : VALUE_ERROR; + + break; + } + } + } + + return ok; +} + +int ParseStatusParam(char *status) +{ + int res = 0; + char lower[256]; + STRNCPY(lower, status, sizeof(lower)); + + if (strcmp(lower, "offline") == 0) + { + res = ID_STATUS_OFFLINE; + } + else{ + if (strcmp(lower, "online") == 0) + { + res = ID_STATUS_ONLINE; + } + else{ + if (strcmp(lower, "away") == 0) + { + res = ID_STATUS_AWAY; + } + else{ + if (strcmp(lower, "dnd") == 0) + { + res = ID_STATUS_DND; + } + else{ + if (strcmp(lower, "na") == 0) + { + res = ID_STATUS_NA; + } + else{ + if (strcmp(lower, "occupied") == 0) + { + res = ID_STATUS_OCCUPIED; + } + else{ + if (strcmp(lower, "freechat") == 0) + { + res = ID_STATUS_FREECHAT; + } + else{ + if (strcmp(lower, "invisible") == 0) + { + res = ID_STATUS_INVISIBLE; + } + else{ + if (strcmp(lower, "onthephone") == 0) + { + res = ID_STATUS_ONTHEPHONE; + } + else{ + if (strcmp(lower, "outtolunch") == 0) + { + res = ID_STATUS_OUTTOLUNCH; + }//outtolunch + }//onthephone + }//invisible + }//freechat + }//occupied + }//na + } //dnd + } //away + } //online + } //offline + + return res; +} + +char *PrettyStatusMode(int status, char *buffer, int size) +{ + *buffer = 0; + char *data = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, 0); + if (data) + { + STRNCPY(buffer, data, size); + } + + return buffer; +} + +void HandleStatusCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 2: + { + INT_PTR status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0); + char pretty[128]; + PrettyStatusMode(status, pretty, sizeof(pretty)); + + const int cPerAccountStatus = 1024 * 5; + char *perAccountStatus = (char *) malloc(cPerAccountStatus); + + perAccountStatus[0] = 0; + + int count; + PROTOACCOUNT **accounts = NULL; + + char pn[128]; + + ProtoEnumAccounts(&count, &accounts); + + for (int i = 0; i < count; i++) + { + if (accounts[i]->bIsEnabled) + { + INT_PTR status = CallProtoService(accounts[i]->szModuleName, PS_GETSTATUS, 0, 0); + PrettyStatusMode(status, pn, sizeof(pn)); + + strncat(perAccountStatus, "\n", cPerAccountStatus); + + char *account = mir_u2a((wchar_t *) accounts[i]->tszAccountName); + strncat(perAccountStatus, account, cPerAccountStatus); + mir_free(account); + + strncat(perAccountStatus, ": ", cPerAccountStatus); + strncat(perAccountStatus, pn, cPerAccountStatus); + } + } + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Current global status: %s.%s"), pretty, perAccountStatus); + + free(perAccountStatus); + + break; + } + + case 3: + { + int status = ParseStatusParam(argv[2]); + if (status) + { + INT_PTR old = CallService(MS_CLIST_GETSTATUSMODE, 0, 0); + char po[128]; + if (ServiceExists(MS_KS_ANNOUNCESTATUSCHANGE)) + { + announce_status_change(NULL, status, NULL); + } + + PrettyStatusMode(old, po, sizeof(po)); + CallService(MS_CLIST_SETSTATUSMODE, status, 0); + char pn[128]; + PrettyStatusMode(status, pn, sizeof(pn)); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Changed global status to '%s' (previous status was '%s')."), pn, po); + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + + break; + } + + case 4: + { + int status = ParseStatusParam(argv[2]); + if (status) + { + char protocol[128]; + char *account = argv[3]; + AccountName2Protocol(account, protocol, sizeof(protocol)); + + INT_PTR old = CallProtoService(protocol, PS_GETSTATUS, 0, 0); + char po[128]; + if (ServiceExists(MS_KS_ANNOUNCESTATUSCHANGE)) + { + announce_status_change(protocol, status, NULL); + } + + PrettyStatusMode(old, po, sizeof(po)); + INT_PTR res = CallProtoService(protocol, PS_SETSTATUS, status, 0); + char pn[128]; + PrettyStatusMode(status, pn, sizeof(pn)); + + switch (res) + { + case 0: + { + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Changed '%s' status to '%s' (previous status was '%s')."), account, pn, po); + + break; + } + + case CALLSERVICE_NOTFOUND: + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account); + + break; + } + + default: + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Failed to change status for account '%s' to '%s'."), account, pn); + + break; + } + } + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } +} + +void GetProtocols(int *count, PROTOCOLDESCRIPTOR ***protocols) +{ + CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) count, (LPARAM) protocols); +} + +void HandleAwayMsgCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 3: + { + char *awayMsg = argv[2]; + int count = 0; + PROTOACCOUNT **accounts = NULL; + ProtoEnumAccounts(&count, &accounts); + + int i; + INT_PTR status; + INT_PTR res = 0; + char *protocol; + char buffer[1024]; + char pn[128]; + for (i = 0; i < count; i++) + { + if (accounts[i]->bIsEnabled) + { + protocol = accounts[i]->szModuleName; + if ((CallProtoService(protocol, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) != 0) //if the protocol supports away messages + { + status = CallProtoService(protocol, PS_GETSTATUS, 0, 0); + res = CallProtoService(protocol, PS_SETAWAYMSG, status, (LPARAM) awayMsg); + PrettyStatusMode(status, pn, sizeof(pn)); + if (res) + { + mir_snprintf(buffer, sizeof(buffer), Translate("Failed to set '%S' status message to '%s' (status is '%s')."), accounts[i]->tszAccountName , awayMsg, pn); + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Successfully set '%S' status message to '%s' (status is '%s')."), accounts[i]->tszAccountName, awayMsg, pn); + } + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Account '%S' does not support away messages, skipping."), accounts[i]->tszAccountName); + } + + if (i != 0) + { + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + } + else{ + STRNCPY(reply->message, buffer, reply->cMessage); + } + } + } + reply->code = MIMRES_SUCCESS; + + break; + } + + case 4: + { + char *awayMsg = argv[2]; + char protocol[128]; + char *account = argv[3]; + AccountName2Protocol(account, protocol, sizeof(protocol)); + + INT_PTR res = 0; + char pn[128]; + if ((res = CallProtoService(protocol, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) != 0) //if the protocol supports away messages + { + INT_PTR status = CallProtoService(protocol, PS_GETSTATUS, 0, 0); + res = CallProtoService(protocol, PS_SETAWAYMSG, status, (LPARAM) awayMsg); + + PrettyStatusMode(status, pn, sizeof(pn)); + } + else{ + if (CallProtoService(protocol, PS_GETSTATUS, 0, 0) == CALLSERVICE_NOTFOUND) + { + res = CALLSERVICE_NOTFOUND; + } + else { + res = -2; + } + } + + switch (res) + { + case 0: + { + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Changed '%s' status message to '%s' (status is '%s')."), account, awayMsg, pn); + + break; + } + + case CALLSERVICE_NOTFOUND: + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account); + + break; + } + + case -2: + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Account '%s' does not support away messages, skipping."), account); + + break; + } + + default: + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Failed to change status message for account '%s' to '%s' (status is '%s')."), account, awayMsg, pn); + + break; + } + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } +} + +void Set2StateReply(PReply reply, int state, int failure, char *successTrue, char *failureTrue, char *successFalse, char *failureFalse) +{ + if (state) + { + if (failure) + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate(failureTrue)); + } + else{ + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate(successTrue)); + } + } + else{ + if (failure) + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate(failureFalse)); + } + else{ + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate(successFalse)); + } + } +} + +void HandlePopupsCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 2: + { + int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0); + Set2StateReply(reply, state, 0, "Popups are currently enabled.", "", "Popups are currently disabled.", ""); + + break; + } + + case 3: + { + int failure; + int state = 0; + int error = 0; + + switch (Get2StateValue(argv[2])) + { + case STATE_ON: + { + failure = CallService(MS_POPUP_QUERY, PUQS_ENABLEPOPUPS, 0); + state = TRUE; + + break; + } + + case STATE_OFF: + { + failure = CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0); + state = FALSE; + + break; + } + + case STATE_TOGGLE: + { + int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0); + failure = CallService(MS_POPUP_QUERY, (state) ? PUQS_DISABLEPOPUPS : PUQS_ENABLEPOPUPS, 0); + state = 1 - state; + + break; + } + + default: + { + HandleUnknownParameter(command, argv[2], reply); + error = 1; + + break; + } + } + if (!error) + { + Set2StateReply(reply, state, failure, "Popups were enabled successfully.", "Popups could not be enabled.", "Popups were disabled successfully.", "Popups could not be disabled."); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + + } +} + +void HandleSoundsCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 2: + { + int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0); + Set2StateReply(reply, state, 0, "Sounds are currently enabled.", "", "Sounds are currently disabled.", ""); + + break; + } + + case 3: + { + int failure; + int state = 0; + int error = 0; + + switch (Get2StateValue(argv[2])) + { + case STATE_ON: + { + failure = 0; + DBWriteContactSettingByte(NULL, "Skin", "UseSound", 1); + state = TRUE; + + break; + } + + case STATE_OFF: + { + failure = 0; + DBWriteContactSettingByte(NULL, "Skin", "UseSound", 0); + state = FALSE; + + break; + } + + case STATE_TOGGLE: + { + state = DBGetContactSettingByte(NULL, "Skin", "UseSound", 1); + + failure = 0; + state = 1 - state; + DBWriteContactSettingByte(NULL, "Skin", "UseSound", state); + + break; + } + + default: + { + HandleUnknownParameter(command, argv[2], reply); + error = 1; + + break; + } + } + if (!error) + { + Set2StateReply(reply, state, failure, "Sounds were enabled successfully.", "Sounds could not be enabled.", "Sounds were disabled successfully.", "Sounds could not be disabled."); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } +} + +void HandleClistCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 2: + { + HWND hClist = (HWND) CallService(MS_CLUI_GETHWND, 0, 0); + int state = IsWindowVisible(hClist); + Set2StateReply(reply, state, 0, "Contact list is currectly shown.", "", "Contact list is currently hidden.", ""); + + break; + } + + case 3: + { + int failure; + int state = 0; + int error = 0; + HWND hClist = (HWND) CallService(MS_CLUI_GETHWND, 0, 0); + + switch (Get2StateValue(argv[2])) + { + case STATE_ON: + { + failure = 0; + ShowWindow(hClist, SW_SHOW); + + state = TRUE; + + break; + } + + case STATE_OFF: + { + failure = 0; + ShowWindow(hClist, SW_HIDE); + state = FALSE; + + break; + } + + case STATE_TOGGLE: + { + state = IsWindowVisible(hClist); + + failure = 0; + state = 1 - state; + ShowWindow(hClist, (state) ? SW_SHOW : SW_HIDE); + + break; + } + + default: + { + HandleUnknownParameter(command, argv[2], reply); + error = 1; + + break; + } + } + if (!error) + { + Set2StateReply(reply, state, failure, "Contact list was shown successfully.", "Contact list could not be shown.", "Contact list was hidden successfully.", "Contact list could not be hidden."); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } +} + +void HandleQuitCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 2: + { + CallService("CloseAction", 0, 0); + + //try another quit method + HWND hWndMiranda = (HWND)CallService(MS_CLUI_GETHWND, 0, 0); + PostMessage(hWndMiranda, WM_COMMAND, ID_ICQ_EXIT, 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, "Issued a quit command."); + + break; + } + + case 3: + { + char lower[128]; + STRNCPY(lower, argv[2], sizeof(lower)); + _strlwr(lower); + + if (strcmp(lower, "wait") == 0) + { + CallService("CloseAction", 0, 0); + + //try another quit method + HWND hWndMiranda = (HWND)CallService(MS_CLUI_GETHWND, 0, 0); + PostMessage(hWndMiranda, WM_COMMAND, ID_ICQ_EXIT, 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, "Issued a quit and wait command."); + + SetEvent(heServerBufferFull); + + bWaitForUnload = 1; + + while (bWaitForUnload) + { + Sleep(250); //wait for Miranda to quit. + } + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } +} + +void HandleExchangeCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 3: + { + char lower[128]; + STRNCPY(lower, argv[2], sizeof(lower)); + _strlwr(lower); + if (strcmp(lower, "check") == 0) + { + if (ServiceExists(MS_EXCHANGE_CHECKEMAIL)) + { + CallService(MS_EXCHANGE_CHECKEMAIL, 0, 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Issued check email command to Exchange plugin.")); + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Exchange plugin is not running.")); + } + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + + } +} + +void HandleYAMNCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 3: + { + char lower[128]; + STRNCPY(lower, argv[2], sizeof(lower)); + _strlwr(lower); + if (strcmp(lower, "check") == 0) + { + if (ServiceExists(MS_YAMN_FORCECHECK)) + { + CallService(MS_YAMN_FORCECHECK, 0, 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Issued check email command to YAMN plugin.")); + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("YAMN plugin is not running.")); + } + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + + } +} + +void HandleCallServiceCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + switch (argc) + { + case 5: + { + char *service = argv[2]; + if (ServiceExists(service)) + { + void *wParam = NULL; + void *lParam = NULL; + INT_PTR res1 = ParseValueParam(argv[3], wParam); + INT_PTR res2 = ParseValueParam(argv[4], lParam); + if ((res1 != 0) && (res2 != 0)) + { + //very dangerous but the user asked + INT_PTR res = CallService(service, ((res1 == 1) ? *((long *) wParam) : (WPARAM) wParam), (LPARAM) ((res2 == 1) ? *((long *) lParam) : (LPARAM) lParam)); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("CallService call successful: service '%s' returned %p."), service, res); + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Invalid parameter '%s' passed to CallService command."), (wParam) ? argv[4] : argv[3]); + } + + if (wParam) { free(wParam); } + if (lParam) { free(lParam); } + + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Service '%s' does not exist."), service); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + } + } +} + + +HANDLE ParseContactParam(char *contact) +{ + char name[512]; + char account[128]; + char protocol[128]; + char *p = strrchr(contact, ':'); + HANDLE hContact = NULL; + if (p) + { + *p = 0; + STRNCPY(name, contact, p - contact + 1); + STRNCPY(account, p + 1, sizeof(account)); + *p = ':'; + AccountName2Protocol(account, protocol, sizeof(protocol)); + + hContact = GetContactFromID(name, protocol); + + } + else{ + hContact = GetContactFromID(contact, (char *) NULL); + } + + return hContact; +} + +void HandleMessageCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 4) + { + char *message = argv[argc - 1]; //get the message + int i; + char *contact; + char buffer[1024]; + HANDLE hContact; + HANDLE hProcess = NULL; + ACKDATA *ack = NULL; + for (i = 2; i < argc - 1; i++) + { + contact = argv[i]; + hContact = ParseContactParam(contact); + + if (hContact) + { + bShouldProcessAcks = TRUE; + hProcess = (HANDLE) CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM) message); + const int MAX_COUNT = 60; + int counter = 0; + while (((ack = GetAck(hProcess)) == NULL) && (counter < MAX_COUNT)) + { + SleepEx(250, TRUE); + counter++; + } + bShouldProcessAcks = FALSE; + + if (counter < MAX_COUNT) + { + if (ack->result == ACKRESULT_SUCCESS) + { + if (ack->szModule) + { + mir_snprintf(buffer, sizeof(buffer), Translate("Message sent to '%s'."), contact); + + DBEVENTINFO e = {0}; + char module[128]; + e.cbSize = sizeof(DBEVENTINFO); + e.eventType = EVENTTYPE_MESSAGE; + e.flags = DBEF_SENT; + + e.pBlob = (PBYTE) message; + e.cbBlob = (DWORD) strlen((char *) message) + 1; + + STRNCPY(module, ack->szModule, sizeof(module)); + e.szModule = module; + e.timestamp = (DWORD) time(NULL); + + CallService(MS_DB_EVENT_ADD, (WPARAM) ack->hContact, (LPARAM) &e); + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Message to '%s' was marked as sent but the account seems to be offline"), contact); + } + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Could not send message to '%s'."), contact); + } + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Timed out while waiting for acknowledgement for contact '%s'."), contact); + } + } + else{ + mir_snprintf(buffer, sizeof(buffer), Translate("Could not find contact handle for contact '%s'."), contact); + } + + if (i == 3) + { + STRNCPY(reply->message, buffer, reply->cMessage); + } + else{ + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + } + } + } + else{ + HandleWrongParametersCount(command, reply); + } +} + +int ParseDatabaseData(DBVARIANT *var, char *buffer, int size, int free) +{ + int ok = 1; + switch (var->type) + { + case DBVT_BYTE: + { + mir_snprintf(buffer, size, "byte:%d", var->bVal); + + break; + } + + case DBVT_WORD: + { + mir_snprintf(buffer, size, "word:%d", var->wVal); + + break; + } + + case DBVT_DWORD: + { + mir_snprintf(buffer, size, "dword:%ld", var->dVal); + + break; + } + + case DBVT_ASCIIZ: + { + mir_snprintf(buffer, size, "string:'%s'", var->pszVal); + if (free) { mir_free(var->pszVal); } + + break; + } + + case DBVT_WCHAR: + { + mir_snprintf(buffer, size, "wide string:'%S'", var->pwszVal); + if (free) { mir_free(var->pwszVal); } + + break; + } + + case DBVT_UTF8: + { + mir_snprintf(buffer, size, "utf8:'%s'", var->pszVal); + if (free) { mir_free(var->pszVal); } + } + + case DBVT_BLOB: + { + mir_snprintf(buffer, size, "blob:N/A"); + if (free) { mir_free(var->pbVal); } + + break; + } + + + default: + { + ok = 0; + mir_snprintf(buffer, size, "unknown value"); + + break; + } + } + + return ok; +} + +void HandleDatabaseCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 3) //we have something to parse + { + char dbcmd[128]; + STRNCPY(dbcmd, argv[2], sizeof(dbcmd)); + dbcmd[sizeof(dbcmd) - 1] = 0; + _strlwr(dbcmd); + if (strcmp(dbcmd, "delete") == 0) + { + if (argc == 5) + { + char *module = argv[3]; + char *key = argv[4]; + + DBDeleteContactSetting(NULL, module, key); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Setting '%s/%s' deleted."), module, key); + } + else{ + HandleWrongParametersCount(command, reply); + } + } + else{ + if (strcmp(dbcmd, "set") == 0) + { + if (argc == 6) + { + char *module = argv[3]; + char *key = argv[4]; + + int ok = 1; + + void *value = NULL; + char *wrote = NULL; + int type = ParseValueParam(argv[5], value); + + + switch (type) + { + case VALUE_STRING: + { + DBWriteContactSettingString(NULL, module, key, (char *) value); + wrote = "string"; + + break; + } + + case VALUE_BYTE: + { + DBWriteContactSettingByte(NULL, module, key, (* (char *) value)); + wrote = "byte"; + + break; + } + + case VALUE_WORD: + { + DBWriteContactSettingWord(NULL, module, key, (* (WORD *) value)); + wrote = "word"; + + break; + } + + case VALUE_DWORD: + { + DBWriteContactSettingDword(NULL, module, key, (* (DWORD *) value)); + wrote = "dword"; + + break; + } + + case VALUE_WIDE: + { + DBWriteContactSettingWString(NULL, module, key, (WCHAR *) value); + wrote = "wide string"; + + break; + } + + default: + { + HandleUnknownParameter(command, argv[5], reply); + ok = 0; + + break; + } + } + + if (ok) + { + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Wrote '%s:%s' to database entry '%s/%s'."), wrote, argv[5] + 1, module, key); + } + + if (value) + { + free(value); + } + } + else{ + HandleWrongParametersCount(command, reply); + } + } + else{ + if (strcmp(dbcmd, "get") == 0) + { + if (argc == 5) + { + char *module = argv[3]; + char *key = argv[4]; + + DBVARIANT var = {0}; + + int res = DBGetContactSetting(NULL, module, key, &var); + if (!res) + { + char buffer[1024]; + + if (ParseDatabaseData(&var, buffer, sizeof(buffer), TRUE)) + { + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("'%s/%s' - %s."), module, key, buffer); + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Could not retrieve setting '%s/%s': %s."), module, key, buffer); + } + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Setting '%s/%s' was not found."), module, key); + } + + } + else{ + HandleWrongParametersCount(command, reply); + } + } + else{ + HandleUnknownParameter(command, dbcmd, reply); + } + } + + } + + } + else{ + HandleWrongParametersCount(command, reply); + } +} + +int ParseProxyType(char *type) +{ + char lower[128]; + STRNCPY(lower, type, sizeof(lower)); + lower[sizeof(lower) - 1] = 0; + _strlwr(lower); + int proxy = 0; + + if (strcmp(lower, "socks4") == 0) + { + proxy = PROXY_SOCKS4; + } + else{ + if (strcmp(lower, "socks5") == 0) + { + proxy = PROXY_SOCKS5; + } + else{ + if (strcmp(lower, "http") == 0) + { + proxy = PROXY_HTTP; + } + else{ + if (strcmp(lower, "https") == 0) + { + proxy = PROXY_HTTPS; + } + } + } + } + + return proxy; +} + +char *PrettyProxyType(int type, char *buffer, int size) +{ + char *pretty = ""; + switch (type) + { + case PROXY_SOCKS4: + { + pretty = "SOCKS4"; + + break; + } + + case PROXY_SOCKS5: + { + pretty = "SOCKS5"; + + break; + } + + case PROXY_HTTP: + { + pretty = "HTTP"; + + break; + } + + case PROXY_HTTPS: + { + pretty = "HTTPS"; + + break; + } + + default: + { + pretty = "Unknown"; + + break; + } + } + + STRNCPY(buffer, pretty, size); + + return buffer; +} + +void HandleProtocolProxyCommand(PCommand command, TArgument *argv, int argc, PReply reply, char *module, char *protocol) +{ + char proxycmd[128]; + STRNCPY(proxycmd, argv[3], sizeof(proxycmd)); + proxycmd[sizeof(proxycmd) - 1] = 0; + _strlwr(proxycmd); + + char buffer[1024]; + int ok = 1; + + + if (strcmp(proxycmd, "status") == 0) + {//status command + switch (argc) + { + case 4: + { + int value = DBGetContactSettingByte(NULL, module, "NLUseProxy", 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), "%s proxy status is %s", protocol, (value) ? "enabled" : "disabled"); + + break; + } + + case 5: + { + int state = Get2StateValue(argv[4]); + switch (state) + { + case STATE_OFF: + { + DBWriteContactSettingByte(NULL, module, "NLUseProxy", 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), Translate("'%s' proxy was disabled."), protocol); + + break; + } + + case STATE_ON: + { + DBWriteContactSettingByte(NULL, module, "NLUseProxy", 1); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), Translate("'%s' proxy was enabled."), protocol); + + break; + } + + case STATE_TOGGLE: + { + int value = DBGetContactSettingByte(NULL, module, "NLUseProxy", 0); + value = 1 - value; + DBWriteContactSettingByte(NULL, module, "NLUseProxy", value); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), (value) ? Translate("'%s' proxy was enabled.") : Translate("'%s' proxy was disabled.")); + + break; + } + + default: + { + HandleUnknownParameter(command, argv[4], reply); + + break; + } + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + ok = 0; + + break; + } + } + } + else{ + if (strcmp(proxycmd, "server") == 0) + { + switch (argc) + { + case 4: + { + char host[256]; + int port; + char type[256]; + GetStringFromDatabase(NULL, module, "NLProxyServer", "", host, sizeof(host)); + port = DBGetContactSettingWord(NULL, module, "NLProxyPort", 0); + PrettyProxyType(DBGetContactSettingByte(NULL, module, "NLProxyType", 0), type, sizeof(type)); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), Translate("%s proxy server: %s %s:%d."), protocol, type, host, port); + + break; + } + + case 7: + { + int type = ParseProxyType(argv[4]); + char *host = argv[5]; + long port; + char *stop = NULL; + port = strtol(argv[6], &stop, 10); + + if ((*stop == 0) && (type > 0)) + { + DBWriteContactSettingString(NULL, module, "NLProxyServer", host); + DBWriteContactSettingWord(NULL, module, "NLProxyPort", port); + DBWriteContactSettingByte(NULL, module, "NLProxyType", type); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(buffer, sizeof(buffer), Translate("%s proxy set to %s %s:%d."), protocol, argv[4], host, port); + } + else { + reply->code = MIMRES_FAILURE; + mir_snprintf(buffer, sizeof(buffer), Translate("%s The port or the proxy type parameter is invalid."), protocol); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + ok = 0; + + break; + } + } + } + else{ + ok = 0; + HandleUnknownParameter(command, proxycmd, reply); + } + } + + + if (ok) + { + if (strlen(reply->message) > 0) + { + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + reply->message[reply->cMessage - 1] = 0; + } + else{ + mir_snprintf(reply->message, reply->cMessage, buffer); + } + } +} + +void HandleProxyCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 4) + { + char account[128]; + char protocol[128]; + STRNCPY(account, argv[2], sizeof(account)); + account[sizeof(account) - 1] = 0; + + AccountName2Protocol(account, protocol, sizeof(protocol)); + + int count = 0; + PROTOACCOUNT **accounts = NULL; + ProtoEnumAccounts(&count, &accounts); + + int i; + int global = (strcmp(protocol, "GLOBAL") == 0); + + reply->message[0] = 0; + + int found = 0; + if (global) + { + HandleProtocolProxyCommand(command, argv, argc, reply, "Netlib", protocol); + found = 1; + } + + char *match; + + for (i = 0; i < count; i++) + { + if (accounts[i]->bIsEnabled) + { + match = accounts[i]->szModuleName; + if ((global) || (strcmp(protocol, match) == 0)) + { + HandleProtocolProxyCommand(command, argv, argc, reply, match, match); + found = 1; + } + } + } + + if (!found) + { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account); + } + } + else{ + HandleWrongParametersCount(command, reply); + } +} + +int ContactMatchSearch(HANDLE hContact, char *contact, char *id, char *account, TArgument *argv, int argc) +{ + int matches = 1; + int i; + + char lwrName[2048] = "\0"; + char lwrAccount[128] = "\0"; + char lwrKeyword[512] = "\0"; + char lwrID[512] = "\0"; + char *pos; + + STRNCPY(lwrName, contact, sizeof(lwrName)); + STRNCPY(lwrAccount, account, sizeof(lwrAccount)); + + if (id) { STRNCPY(lwrID, id, sizeof(lwrID)); } + + _strlwr(lwrName); + _strlwr(lwrAccount); + _strlwr(lwrID); + + for (i = 0; i < argc; i++) + { + STRNCPY(lwrKeyword, argv[i], sizeof(lwrKeyword)); + _strlwr(lwrKeyword); + + pos = strstr(lwrKeyword, "account:"); + if (pos) + { + pos += 8; + if (strstr(lwrAccount, pos) == NULL) + { + matches = 0; + + break; + } + } + else{ + pos = strstr(lwrKeyword, "status:"); + if (pos) + { + int searchStatus = ParseStatusParam(pos + 7); + char protocol[128]; + + AccountName2Protocol(account, protocol, sizeof(protocol)); + WORD contactStatus = DBGetContactSettingWord(hContact, protocol, "Status", ID_STATUS_ONLINE); + + if (searchStatus != contactStatus) + { + matches = 0; + + break; + } + } + else{ + pos = strstr(lwrKeyword, "id:"); + if (pos) + { + pos += 3; + if (strstr(lwrID, pos) == NULL) + { + matches = 0; + + break; + } + } + else{ + if ((strstr(lwrName, lwrKeyword) == NULL)) + { + matches = 0; + + break; + } + } + } + } + } + + return matches; +} + +DWORD WINAPI OpenMessageWindowThread(void *data) +{ + HANDLE hContact = (HANDLE) data; + if (hContact) + { + CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM) hContact, 0); + CallServiceSync("SRMsg/LaunchMessageWindow", (WPARAM) hContact, 0); + } + + return 0; +} + + +void HandleContactsCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 3) + { + if (_stricmp(argv[2], "list") == 0) + { + HANDLE hContact = NULL; + char buffer[1024]; + char protocol[128]; + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + int count = 0; + + reply->code = MIMRES_SUCCESS; + while (hContact) + { + + GetContactProtocol(hContact, protocol, sizeof(protocol)); + + char *contact = GetContactName(hContact, protocol); + char *id = GetContactID(hContact, protocol); + if (ContactMatchSearch(hContact, contact, id, protocol, &argv[3], argc - 3)) + { + mir_snprintf(buffer, sizeof(buffer), "%s:[%s]:%s (%08d)", contact, id, protocol, hContact); + if (count) + { + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + } + else{ + STRNCPY(reply->message, buffer, reply->cMessage); + } + + if (strlen(reply->message) > 4096) + { + SetEvent(heServerBufferFull); + Sleep(750); //wait a few milliseconds for the event to be processed + count = 0; + *reply->message = 0; + } + + count++; + } + + free(contact); + free(id); + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + } + else{ + if (_stricmp(argv[2], "open") == 0) + { + if (argc > 3) + { + HANDLE hContact = NULL; + char protocol[128]; + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + + reply->code = MIMRES_SUCCESS; + *reply->message = 0; + while (hContact) + { + GetContactProtocol(hContact, protocol, sizeof(protocol)); + + char *contact = GetContactName(hContact, protocol); + char *id = GetContactID(hContact, protocol); + if (ContactMatchSearch(hContact, contact, id, protocol, &argv[3], argc - 3)) + { + DWORD threadID; + HANDLE thread = CreateThread(NULL, NULL, OpenMessageWindowThread, hContact, NULL, &threadID); + } + + free(contact); + free(id); + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + } + else{ + if (argc == 3) + { + HANDLE hContact = NULL; + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + + reply->code = MIMRES_SUCCESS; + *reply->message = 0; + + while (hContact) + { + HANDLE hUnreadEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); + if (hUnreadEvent != NULL) + { + DWORD threadID; + HANDLE thread = CreateThread(NULL, NULL, OpenMessageWindowThread, hContact, NULL, &threadID); + } + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + } + else { + HandleWrongParametersCount(command, reply); + } + } + } + else{ + HandleUnknownParameter(command, argv[2], reply); + } + } + } + else{ + HandleWrongParametersCount(command, reply); + } +} + +void AddHistoryEvent(DBEVENTINFO *dbEvent, char *contact, PReply reply) +{ + struct tm * tEvent = localtime((time_t *) &dbEvent->timestamp); + char timestamp[256]; + + strftime(timestamp, sizeof(timestamp), "%H:%M:%S %d/%b/%Y", tEvent); + + static char buffer[6144]; + char *sender = (dbEvent->flags & DBEF_SENT) ? Translate("[me]") : contact; + + char message[4096] = {0}; + STRNCPY(message, (char *) dbEvent->pBlob, sizeof(message)); + message[dbEvent->cbBlob] = message[strlen(message)] = 0; + + //if ((strlen(message) <= 0) && (dbEvent->cbBlob > 0)) + //{ + // WCHAR *tmp = (WCHAR *) dbEvent->pBlob[dbEvent->cbBlob + 1]; + // WideCharToMultiByte(CP_ACP, 0, tmp, -1, message, sizeof(message), NULL, NULL); + //} + + mir_snprintf(buffer, sizeof(buffer), "[%s] %15s: %s", timestamp, sender, message); + + + if (strlen(reply->message) > 0) + { + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + } + else{ + STRNCPY(reply->message, buffer, reply->cMessage); + } + + if (strlen(reply->message) > (reply->cMessage / 2)) + { + SetEvent(heServerBufferFull); + + Sleep(750); + strcpy(reply->message, "\n"); + } +} + +void HandleHistoryCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 3) + { + char *cmd = argv[2]; + switch (argc) + { + case 3: + { + if (_stricmp(cmd, "unread") == 0) + { + HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + char buffer[4096]; + int count; + int contacts = 0; + DBEVENTINFO dbEvent = {0}; + dbEvent.cbSize = sizeof(DBEVENTINFO); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("No unread messages found.")); + + while (hContact) + { + HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); + if (hEvent != NULL) + { + char *contact; + char protocol[128]; + + count = 0; + while (hEvent != NULL) + { + if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent)) + { + if (!(dbEvent.flags & DBEF_READ)) + { + count++; + } + } + + hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0); + } + + GetContactProtocol(hContact, protocol, sizeof(protocol)); + contact = GetContactName(hContact, protocol); + mir_snprintf(buffer, sizeof(buffer), Translate("%s:%s - %d unread events."), contact, protocol, count); + + if (contacts > 0) + { + strncat(reply->message, "\n", reply->cMessage); + strncat(reply->message, buffer, reply->cMessage); + } + else{ + STRNCPY(reply->message, buffer, reply->cMessage); + } + contacts++; + + free(contact); + } + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + } + else{ + if (_stricmp(cmd, "show") == 0) + { + HandleWrongParametersCount(command, reply); + } + else{ + HandleUnknownParameter(command, cmd, reply); + } + } + + break; + } + + case 4: + { + char *contact = argv[3]; + HANDLE hContact = ParseContactParam(contact); + if (hContact) + { + if (_stricmp(cmd, "unread") == 0) + { + HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); + DBEVENTINFO dbEvent = {0}; + dbEvent.cbSize = sizeof(DBEVENTINFO); + + char *message[4096]; + dbEvent.pBlob = (PBYTE) message; + + reply->code = MIMRES_SUCCESS; + + while (hEvent) + { + dbEvent.cbBlob = sizeof(message); + if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent)) //if successful call + { + if (!(dbEvent.flags & DBEF_READ)) + { + AddHistoryEvent(&dbEvent, contact, reply); + } + } + + hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0); + } + } + else{ + if (_stricmp(cmd, "show") == 0) + { + int count = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM) hContact, 0); + + reply->code = MIMRES_SUCCESS; + mir_snprintf(reply->message, reply->cMessage, Translate("Contact '%s' has '%d' events in history."), contact, count); + } + else{ + HandleUnknownParameter(command, cmd, reply); + } + } + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Could not find contact handle for contact '%s'."), contact); + } + + break; + } + + case 6: + { + char *contact = argv[3]; + HANDLE hContact = ParseContactParam(contact); + + if (hContact) + { + if (_stricmp(cmd, "show") == 0) + { + char *stop1 = NULL; + char *stop2 = NULL; + long start = strtol(argv[4], &stop1, 10); + long stop = strtol(argv[5], &stop2, 10); + if (!(*stop1) && !(*stop2)) + { + int size = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM) hContact, 0); + if (start < 0) { start = size + start + 1; } + if (stop < 0) { stop = size + stop + 1; } + + reply->code = MIMRES_SUCCESS; + + int count = stop - start + 1; + if (count > 0) + { + int index = 0; + HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRST, (WPARAM) hContact, 0); + DBEVENTINFO dbEvent = {0}; + dbEvent.cbSize = sizeof(DBEVENTINFO); + char message[4096]; + dbEvent.pBlob = (PBYTE) message; + + while (hEvent) + { + dbEvent.cbBlob = sizeof(message); + if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent)) // if successful call + { + dbEvent.pBlob[dbEvent.cbBlob] = 0; + if ((index >= start) && (index <= stop)) + { + AddHistoryEvent(&dbEvent, contact, reply); + } + } + + if (index > stop) + { + break; + } + + hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0); + index++; + } + } + } + else{ + HandleUnknownParameter(command, (*stop1) ? argv[4] : argv[5], reply); + } + } + else{ + if (_stricmp(cmd, "unread") == 0) + { + HandleWrongParametersCount(command, reply); + } + else{ + HandleUnknownParameter(command, cmd, reply); + } + } + } + else{ + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Could not find contact handle for contact '%s'."), contact); + } + + break; + } + + default: + { + HandleWrongParametersCount(command, reply); + + break; + } + } + } + else{ + HandleWrongParametersCount(command, reply); + } +} + +void HandleVersionCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc == 2) + { + reply->code = MIMRES_SUCCESS; + if (ServiceExists(MS_VERSIONINFO_GETINFO)) + { + char *data; + CallService(MS_VERSIONINFO_GETINFO, (WPARAM) FALSE, (LPARAM) &data); + mir_snprintf(reply->message, reply->cMessage, data); + mir_free(data); + } + else{ + char miranda[512]; + char cmdline[512]; + DWORD v = pluginInfo.version; + CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM) sizeof(miranda), (LPARAM) miranda); + mir_snprintf(cmdline, sizeof(cmdline), "%d.%d.%d.%d", ((v >> 24) & 0xFF), ((v >> 16) & 0xFF), ((v >> 8) & 0xFF), (v & 0xFF)); + mir_snprintf(reply->message, reply->cMessage, "Miranda %s\nCmdLine v.%s", miranda, cmdline); + } + } + else{ + HandleWrongParametersCount(command, reply); + } +} +void HandleSetNicknameCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc == 4) + { + char protocol[512]; + char nickname[512]; + strcpy(protocol, argv[2]); + strcpy(nickname, argv[3]); + + int res = CallProtoService(protocol, PS_SETMYNICKNAME, SMNN_TCHAR, (LPARAM) nickname); + + if (res == 0) + { + reply->code = MIMRES_SUCCESS; + *reply->message = 0; + } + else { + reply->code = MIMRES_FAILURE; + mir_snprintf(reply->message, reply->cMessage, Translate("Error setting nickname to '%s' for protocol '%s'"), nickname, protocol); + } + } + else { + HandleWrongParametersCount(command, reply); + } +} + +void HandleIgnoreCommand(PCommand command, TArgument *argv, int argc, PReply reply) +{ + if (argc >= 4) + { + BOOL block = FALSE; + BOOL goodCommand = FALSE; + if (_stricmp(argv[2], "block") == 0) + { + block = TRUE; + goodCommand = TRUE; + } + + if (_stricmp(argv[2], "unblock") == 0) + { + block = FALSE; + goodCommand = TRUE; + } + + if (!goodCommand) + { + HandleUnknownParameter(command, argv[2], reply); + + return; + } + + HANDLE hContact = NULL; + char *contact; + + for (int i = 3; i < argc; i++) + { + contact = argv[i]; + hContact = ParseContactParam(contact); + + if (hContact) + { + CallService(block ? MS_IGNORE_IGNORE : MS_IGNORE_UNIGNORE, (WPARAM) hContact, IGNOREEVENT_ALL); + } + } + + reply->code = MIMRES_SUCCESS; + *reply->message = 0; + } + else { + HandleWrongParametersCount(command, reply); + } +} \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_handlers.h b/plugins/CmdLine/src/mimcmd_handlers.h new file mode 100644 index 0000000000..565c7e3ec5 --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_handlers.h @@ -0,0 +1,55 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_MIMCMD_HANDLERS_H +#define M_MIMCMD_HANDLERS_H + +#include "mimcmd_data.h" + +//aditional services +#define MS_EXCHANGE_CHECKEMAIL "Exchange/CheckEmail" +#define MS_YAMN_FORCECHECK "YAMN/Service/ForceCheck" + +extern PCommand GetCommand(char *command); + +extern HANDLE heServerBufferFull; +extern PLUGININFOEX pluginInfo; + +void HandleCommand(PCommand command, TArgument *argv, int argc, PReply reply); + +void HandleStatusCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleAwayMsgCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandlePopupsCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleSoundsCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleClistCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleQuitCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleExchangeCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleYAMNCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleCallServiceCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleMessageCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleDatabaseCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleProxyCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleContactsCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleHistoryCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleVersionCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleSetNicknameCommand(PCommand command, TArgument *argv, int argc, PReply reply); +void HandleIgnoreCommand(PCommand command, TArgument *argv, int argc, PReply reply); + +#endif //M_MIMCMD_HANDLERS_H \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_ipc.cpp b/plugins/CmdLine/src/mimcmd_ipc.cpp new file mode 100644 index 0000000000..d16de2e7a8 --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_ipc.cpp @@ -0,0 +1,105 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +HANDLE hsmCmdLine = NULL; +HANDLE hmClient = NULL; +HANDLE heServerExec = NULL; +HANDLE heServerDone = NULL; +HANDLE heServerClose = NULL; +HANDLE heServerBufferFull = NULL; + +PSharedData sdCmdLine = NULL; + + +int InitClient() +{ + int res = (CreateSystemEvents() || CreateMutexes() || CreateSharedMem()); + + return res; +} + +int InitServer() +{ + int res = (CreateSystemEvents() || CreateSharedMem()); + + return res; +} + +int DestroyClient() +{ + int res = (DestroySystemEvents() || DestroyMutexes() || DestroySharedMem()); + + return res; +} + +int DestroyServer() +{ + int res = (DestroySystemEvents() || DestroySharedMem()); + + return res; +} + +int CreateSystemEvents() +{ + heServerExec = CreateEvent(NULL, FALSE, FALSE, EVENT_SERVER_EXEC); + heServerDone = CreateEvent(NULL, FALSE, FALSE, EVENT_SERVER_DONE); + heServerClose = CreateEvent(NULL, FALSE, FALSE, EVENT_SERVER_CLOSE); + heServerBufferFull = CreateEvent(NULL, FALSE, FALSE, EVENT_SERVER_BUFFERFULL); + + return ((heServerExec == NULL) || (heServerDone == NULL) || (heServerClose == NULL) || (heServerBufferFull == NULL)); +} + +int CreateMutexes() +{ + hmClient = CreateMutex(NULL, FALSE, MUTEX_CLIENT_NAME); + + return (hmClient == NULL); +} + +int CreateSharedMem() +{ + hsmCmdLine = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TSharedData), SHAREDMEM_NAME); + sdCmdLine = (PSharedData) MapViewOfFile(hsmCmdLine, FILE_MAP_WRITE, 0, 0, sizeof(TSharedData)); + + return ((hsmCmdLine == NULL) || (sdCmdLine == NULL)); +} + +int DestroySystemEvents() +{ + int res = (!CloseHandle(heServerExec)) || (!CloseHandle(heServerDone)) || (!CloseHandle(heServerClose) || (!CloseHandle(heServerBufferFull))); + + return res; +} + +int DestroyMutexes() +{ + int res = !CloseHandle(hmClient); + + return res; +} + +int DestroySharedMem() +{ + int res = (!UnmapViewOfFile(sdCmdLine)) || (!CloseHandle(hsmCmdLine)); + + return res; +} \ No newline at end of file diff --git a/plugins/CmdLine/src/mimcmd_ipc.h b/plugins/CmdLine/src/mimcmd_ipc.h new file mode 100644 index 0000000000..d12a4a993f --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_ipc.h @@ -0,0 +1,56 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_MIMCMD_IPC_H +#define M_MIMCMD_IPC_H + +#include "mimcmd_data.h" + +#define SHAREDMEM_NAME "MirandaCmdLine|SharedMem" +#define MUTEX_CLIENT_NAME "MirandaCmdLine|Mutex|Client" +#define EVENT_SERVER_EXEC "MirandaCmdLine|Event|Exec" +#define EVENT_SERVER_DONE "MirandaCmdLine|Event|Done" +#define EVENT_SERVER_CLOSE "MirandaCmdLine|Event|Close" +#define EVENT_SERVER_BUFFERFULL "MirandaCmdLine|Buffer|Full" + +extern HANDLE hsmCmdLine; +extern HANDLE hmClient; +extern HANDLE heServerExec; +extern HANDLE heServerDone; +extern HANDLE heServerClose; +extern HANDLE heServerBufferFull; + +extern PSharedData sdCmdLine; + +int InitClient(); +int InitServer(); + +int DestroyClient(); +int DestroyServer(); + +int CreateSystemEvents(); +int CreateMutexes(); +int CreateSharedMem(); + +int DestroySystemEvents(); +int DestroyMutexes(); +int DestroySharedMem(); + +#endif \ No newline at end of file diff --git a/plugins/CmdLine/src/resource.h b/plugins/CmdLine/src/resource.h new file mode 100644 index 0000000000..0268ce4765 --- /dev/null +++ b/plugins/CmdLine/src/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by CmdLine.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/CmdLine/src/services.cpp b/plugins/CmdLine/src/services.cpp new file mode 100644 index 0000000000..9e006a0046 --- /dev/null +++ b/plugins/CmdLine/src/services.cpp @@ -0,0 +1,106 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +int bWaitForUnload = 0; + +int InitServices() +{ + return 0; +} + +int DestroyServices() +{ + return 0; +} + +extern "C" __declspec(dllexport) void ProcessConsoleCommand(PCommand command, TArgument *arguments, int count, PReply reply) +{ + HandleCommand(command, arguments, count, reply); +} + +DWORD WINAPI ServerWorkerThread(void *data) +{ + int done = FALSE; + const HANDLE events[] = {heServerExec, heServerClose}; + const int cEvents = sizeof(events) / sizeof(events[0]); + + while (!done) + { + switch (WaitForMultipleObjects(cEvents, events, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: //need to process something + { + ProcessConsoleCommand(&sdCmdLine->command, sdCmdLine->arguments, sdCmdLine->cArguments, &sdCmdLine->reply); + SetEvent(heServerDone); //notify the client we've finished + + break; + } + + case WAIT_OBJECT_0 + 1: //server is closing + { + done = TRUE; //stop the thread + + break; + } + } + } + + return 0; +} + +int StartServer() +{ + int failure = 1; + if (sdCmdLine) + { + if (sdCmdLine->instances == 0) + { + DWORD threadID; + HANDLE server = CreateThread(NULL, NULL, ServerWorkerThread, NULL, 0, &threadID); + if (server) + { + char path[MIMFOLDER_SIZE]; + GetModuleFileName(GetModuleHandle(NULL), path, sizeof(path)); + char *p = strrchr(path, '\\'); + if (p) { *p = 0; } + STRNCPY(sdCmdLine->mimFolder, path, MIMFOLDER_SIZE); + sdCmdLine->instances++; + + failure = 0; + } + else{ + PUShowMessage(Translate("Could not create CommandLine listening server!"), SM_WARNING); + } + } + else{ + MessageBox(NULL, Translate("You can only run one instance of CmdLine plugin."), Translate("Error"), MB_ICONERROR | MB_OK); + } + } + + return failure; +} + +extern "C" __declspec(dllexport) void ListCommands(PCommand * commands, int *count) +{ + *commands = mimCommands; + *count = cMimCommands; +} \ No newline at end of file diff --git a/plugins/CmdLine/src/services.h b/plugins/CmdLine/src/services.h new file mode 100644 index 0000000000..b4beb1d44b --- /dev/null +++ b/plugins/CmdLine/src/services.h @@ -0,0 +1,34 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_CMDLINE_SERVICES_H +#define M_CMDLINE_SERVICES_H + +#include "mimcmd_handlers.h" + +int InitServices(); +int DestroyServices(); + +int StartServer(); + +extern "C" __declspec(dllexport) void ProcessConsoleCommand(PCommand command, TArgument *arguments, int count, PReply reply); +extern "C" __declspec(dllexport) void ListCommands(PCommand * commands, int *count); + +#endif //M_CMDLINE_SERVICES_H diff --git a/plugins/CmdLine/src/utils.cpp b/plugins/CmdLine/src/utils.cpp new file mode 100644 index 0000000000..7d1136602f --- /dev/null +++ b/plugins/CmdLine/src/utils.cpp @@ -0,0 +1,461 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#include "commonheaders.h" + +int LogInit() +{ +#ifdef USE_LOG + //FILE *fout = fopen(LOG_FILE, "wt"); + //fclose(fout); + Log("********************** Miranda started **********************"); +#endif + return 0; +} + +int Log(char *format, ...) +{ +#ifdef USE_LOG + char str[4096]; + va_list vararg; + int tBytes; + FILE *fout = fopen(LOG_FILE, "at"); + if (!fout) + { +// MessageBox(0, "can't open file", NULL, MB_OK); + return -1; + } + time_t tNow = time(NULL); + struct tm *now = localtime(&tNow); + strftime(str, sizeof(str), "%d %b %Y @ %H:%M:%S: ", now); + fputs(str, fout); + va_start(vararg, format); + + tBytes = _vsnprintf(str, sizeof(str), format, vararg); + if (tBytes > 0) + { + str[tBytes] = 0; + } + + va_end(vararg); + if (str[strlen(str) - 1] != '\n') + { + strcat(str, "\n"); + } + fputs(str, fout); + fclose(fout); +#endif + return 0; +} + +int Info(char *title, char *format, ...) +{ + char str[4096]; + va_list vararg; + int tBytes; + va_start(vararg, format); + tBytes = _vsnprintf(str, sizeof(str), format, vararg); + if (tBytes > 0) + { + str[tBytes] = 0; + } + va_end(vararg); + return MessageBoxA(0, str, title, MB_OK | MB_ICONINFORMATION); +} + +int MyPUShowMessage(char *lpzText, BYTE kind) +{ + if (ServiceExists(MS_POPUP_SHOWMESSAGE)) + { + return PUShowMessage(lpzText, kind); + } + else{ + char *title = (kind == SM_NOTIFY) ? Translate("Notify") : Translate("Warning"); + + return MessageBox(NULL, lpzText, title, MB_OK | (kind == SM_NOTIFY) ? MB_ICONINFORMATION : MB_ICONEXCLAMATION); + } +} + +#define HEX_SIZE 8 + +char *BinToHex(int size, PBYTE data) +{ + char *szresult = NULL; + char buffer[32] = {0}; //should be more than enough + int maxSize = size * 2 + HEX_SIZE + 1; + szresult = (char *) new char[ maxSize ]; + memset(szresult, 0, maxSize); + sprintf(buffer, "%0*X", HEX_SIZE, size); + strcpy(szresult, buffer); + int i; + for (i = 0; i < size; i++) + { + sprintf(buffer, "%02X", data[i]); + strcpy(szresult + (HEX_SIZE + i * 2), buffer); + } + return szresult; +} + +void HexToBin(char *inData, ULONG &size, LPBYTE &outData) +{ + char buffer[32] = {0}; + strcpy(buffer, "0x"); + STRNCPY(buffer + 2, inData, HEX_SIZE); + sscanf(buffer, "%x", &size); + outData = (unsigned char*)new char[size*2]; + UINT i; + //size = i; + char *tmp = inData + HEX_SIZE; + buffer[4] = '\0'; //mark the end of the string + for (i = 0; i < size; i++) + { + STRNCPY(buffer + 2, &tmp[i * 2], 2); + sscanf(buffer, "%x", &outData[i]); + } + i = size; +} + +int GetStringFromDatabase(HANDLE hContact, char *szModule, char *szSettingName, char *szError, char *szResult, size_t size) +{ + DBVARIANT dbv = {0}; + int res = 1; + size_t len; + dbv.type = DBVT_ASCIIZ; + if (DBGetContactSetting(hContact, szModule, szSettingName, &dbv) == 0) + { + res = 0; + size_t tmp = strlen(dbv.pszVal); + len = (tmp < size - 1) ? tmp : size - 1; + strncpy(szResult, dbv.pszVal, len); + szResult[len] = '\0'; + mir_free(dbv.pszVal); + } + else{ + res = 1; + if (szError) + { + size_t tmp = strlen(szError); + len = (tmp < size - 1) ? tmp : size - 1; + strncpy(szResult, szError, len); + szResult[len] = '\0'; + } + else{ + szResult[0] = '\0'; + } + } + return res; +} + +int GetStringFromDatabase(HANDLE hContact, char *szModule, char *szSettingName, WCHAR *szError, WCHAR *szResult, size_t count) +{ + DBVARIANT dbv = {0}; + int res = 1; + size_t len; + dbv.type = DBVT_WCHAR; + if (DBGetContactSettingWString(hContact, szModule, szSettingName, &dbv) == 0) + { + res = 0; + if (dbv.type != DBVT_WCHAR) + { + MultiByteToWideChar(CP_ACP, 0, dbv.pszVal, -1, szResult, (int) count); + } + else{ + size_t tmp = wcslen(dbv.pwszVal); + len = (tmp < count - 1) ? tmp : count - 1; + wcsncpy(szResult, dbv.pwszVal, len); + szResult[len] = L'\0'; + } + mir_free(dbv.pwszVal); + } + else{ + res = 1; + if (szError) + { + size_t tmp = wcslen(szError); + len = (tmp < count - 1) ? tmp : count - 1; + wcsncpy(szResult, szError, len); + szResult[len] = L'\0'; + } + else{ + szResult[0] = L'\0'; + } + } + return res; +} + +int GetStringFromDatabase(char *szSettingName, char *szError, char *szResult, size_t size) +{ + return GetStringFromDatabase(NULL, ModuleName, szSettingName, szError, szResult, size); +} + +int GetStringFromDatabase(char *szSettingName, WCHAR *szError, WCHAR *szResult, size_t count) +{ + return GetStringFromDatabase(NULL, ModuleName, szSettingName, szError, szResult, count); +} + +#pragma warning (disable: 4312) +TCHAR *GetContactName(HANDLE hContact, char *szProto) +{ + CONTACTINFO ctInfo; + INT_PTR ret; + char proto[200]; + + ZeroMemory((void *) &ctInfo, sizeof(ctInfo)); + ctInfo.cbSize = sizeof(ctInfo); + if (szProto) + { + ctInfo.szProto = szProto; + } + else{ + GetContactProtocol(hContact, proto, sizeof(proto)); + ctInfo.szProto = proto; + } + ctInfo.dwFlag = CNF_DISPLAY; +#ifdef _UNICODE + ctInfo.dwFlag += CNF_UNICODE; +#endif + ctInfo.hContact = hContact; + //_debug_message("retrieving contact name for %d", hContact); + ret = CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) &ctInfo); + //_debug_message(" contact name %s", ctInfo.pszVal); + TCHAR *buffer; + if (!ret) + { + buffer = _tcsdup(ctInfo.pszVal); + } + mir_free(ctInfo.pszVal); + if (!ret) + { + return buffer; + } + else{ + return NULL; + } + return buffer; +} +#pragma warning (default: 4312) + +#pragma warning (disable: 4312) +void GetContactProtocol(HANDLE hContact, char *szProto, size_t size) +{ + GetStringFromDatabase(hContact, "Protocol", "p", NULL, szProto, size); +} +#pragma warning (default: 4312) + +#pragma warning (disable: 4312) +TCHAR *GetContactID(HANDLE hContact) +{ + char protocol[256]; + GetContactProtocol(hContact, protocol, sizeof(protocol)); + + return GetContactID(hContact, protocol); +} + +TCHAR *GetContactID(HANDLE hContact, char *szProto) +{ + CONTACTINFO ctInfo; + INT_PTR ret; + + ZeroMemory((void *) &ctInfo, sizeof(ctInfo)); + ctInfo.cbSize = sizeof(ctInfo); + ctInfo.szProto = szProto; + ctInfo.dwFlag = CNF_UNIQUEID; +#ifdef _UNICODE + ctInfo.dwFlag |= CNF_UNICODE; +#endif + ctInfo.hContact = hContact; + ret = CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) &ctInfo); + TCHAR *buffer; + if (!ret) + { + TCHAR tmp[16]; + switch (ctInfo.type) + { + case CNFT_BYTE: + { + _stprintf(tmp, _T("%d"), ctInfo.bVal); + buffer = _tcsdup(tmp); + + break; + } + + case CNFT_WORD: + { + _stprintf(tmp, _T("%d"), ctInfo.wVal); + buffer = _tcsdup(tmp); + + break; + } + + case CNFT_DWORD: + { + _stprintf(tmp, _T("%ld"), ctInfo.dVal); + buffer = _tcsdup(tmp); + + break; + } + + case CNFT_ASCIIZ: + default: + { + buffer = _tcsdup(ctInfo.pszVal); + + break; + } + } + + + } + mir_free(ctInfo.pszVal); + if (!ret) + { + return buffer; + } + else{ + return NULL; + } +} +#pragma warning (default: 4312) + +#pragma warning (disable: 4312) +HANDLE GetContactFromID(TCHAR *szID, char *szProto) +{ + HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + TCHAR *szHandle; + TCHAR dispName[1024]; + char cProtocol[256]; + char *tmp; + + int found = 0; + while (hContact) + { + GetContactProtocol(hContact, cProtocol, sizeof(cProtocol)); + szHandle = GetContactID(hContact, cProtocol); + + tmp = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, 0); + STRNCPY(dispName, tmp, sizeof(dispName)); + + if ((szHandle) && ((_tcsicmp(szHandle, szID) == 0) || (_tcsicmp(dispName, szID) == 0)) && ((szProto == NULL) || (_stricmp(szProto, cProtocol) == 0))) + { + found = 1; + } + if (szHandle) { free(szHandle); } + + if (found) { break; } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + return hContact; +} +#pragma warning (default: 4312) + +#pragma warning (disable: 4312) +HANDLE GetContactFromID(TCHAR *szID, wchar_t *szProto) +{ + char protocol[1024]; + WideCharToMultiByte(CP_ACP, 0, szProto, -1, protocol, sizeof(protocol), NULL, NULL); + return GetContactFromID(szID, protocol); +} +#pragma warning (default: 4312) + +void ScreenToClient(HWND hWnd, LPRECT rect) +{ + POINT pt; + int cx = rect->right - rect->left; + int cy = rect->bottom - rect->top; + pt.x = rect->left; + pt.y = rect->top; + ScreenToClient(hWnd, &pt); + rect->left = pt.x; + rect->top = pt.y; + rect->right = pt.x + cx; + rect->bottom = pt.y + cy; +} + +void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors) +{ + RECT rParent; + RECT rChild; + + if (parentPos->flags & SWP_NOSIZE) + { + return; + } + GetWindowRect(parentPos->hwnd, &rParent); + rChild = AnchorCalcPos(window, &rParent, parentPos, anchors); + MoveWindow(window, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, FALSE); +} + +RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors) +{ + RECT rChild; + RECT rTmp; + + GetWindowRect(window, &rChild); + ScreenToClient(parentPos->hwnd, &rChild); + + int cx = rParent->right - rParent->left; + int cy = rParent->bottom - rParent->top; + if ((cx == parentPos->cx) && (cy == parentPos->cy)) + { + return rChild; + } + if (parentPos->flags & SWP_NOSIZE) + { + return rChild; + } + + rTmp.left = parentPos->x - rParent->left; + rTmp.right = (parentPos->x + parentPos->cx) - rParent->right; + rTmp.bottom = (parentPos->y + parentPos->cy) - rParent->bottom; + rTmp.top = parentPos->y - rParent->top; + + cx = (rTmp.left) ? -rTmp.left : rTmp.right; + cy = (rTmp.top) ? -rTmp.top : rTmp.bottom; + + rChild.right += cx; + rChild.bottom += cy; + //expanded the window accordingly, now we need to enforce the anchors + if ((anchors & ANCHOR_LEFT) && (!(anchors & ANCHOR_RIGHT))) + { + rChild.right -= cx; + } + if ((anchors & ANCHOR_TOP) && (!(anchors & ANCHOR_BOTTOM))) + { + rChild.bottom -= cy; + } + if ((anchors & ANCHOR_RIGHT) && (!(anchors & ANCHOR_LEFT))) + { + rChild.left += cx; + } + if ((anchors & ANCHOR_BOTTOM) && (!(anchors & ANCHOR_TOP))) + { + rChild.top += cy; + } + return rChild; +} + +inline char *STRNCPY(char *output, const char *input, size_t size) +{ + char *res = strncpy(output, input, size); + output[size - 1] = 0; + + return res; +} \ No newline at end of file diff --git a/plugins/CmdLine/src/utils.h b/plugins/CmdLine/src/utils.h new file mode 100644 index 0000000000..22b4721cfa --- /dev/null +++ b/plugins/CmdLine/src/utils.h @@ -0,0 +1,62 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007 Cristian Libotean + +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. +*/ + +#ifndef M_CMDLINE_UTILS_H +#define M_CMDLINE_UTILS_H + +#include + +//#define USE_LOG +#define LOG_FILE "cmdline.log" + +#define ANCHOR_LEFT 0x000001 +#define ANCHOR_RIGHT 0x000002 +#define ANCHOR_TOP 0x000004 +#define ANCHOR_BOTTOM 0x000008 +#define ANCHOR_ALL ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM + +int LogInit(); +int Log(char *format, ...); +int Info(char *title, char *format, ...); + +char *BinToHex(int size, PBYTE data); +void HexToBin(char *inData, ULONG &size, PBYTE &outData); + +void ScreenToClient(HWND hWnd, LPRECT rect); +void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors); +RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors); + +int GetStringFromDatabase(HANDLE hContact, char *szModule, char *szSettingName, char *szError, char *szResult, size_t size); +int GetStringFromDatabase(HANDLE hContact, char *szModule, char *szSettingName, WCHAR *szError, WCHAR *szResult, size_t count); +int GetStringFromDatabase(char *szSettingName, char *szError, char *szResult, size_t size); +int GetStringFromDatabase(char *szSettingName, WCHAR *szError, WCHAR *szResult, size_t count); + +TCHAR *GetContactName(HANDLE hContact, char *szProto); +TCHAR *GetContactID(HANDLE hContact); +TCHAR *GetContactID(HANDLE hContact, char *szProto); +HANDLE GetContactFromID(TCHAR *szID, char *szProto); +HANDLE GetContactFromID(TCHAR *szID, wchar_t *szProto); +void GetContactProtocol(HANDLE hContact, char *szProto, size_t size); + +int MyPUShowMessage(char *lpzText, BYTE kind); + +inline char *STRNCPY(char *output, const char *input, size_t size); + +#endif \ No newline at end of file diff --git a/plugins/CmdLine/src/version.h b/plugins/CmdLine/src/version.h new file mode 100644 index 0000000000..03656ae51d --- /dev/null +++ b/plugins/CmdLine/src/version.h @@ -0,0 +1,49 @@ +/* +CmdLine plugin for Miranda IM + +Copyright © 2007-2010 Cristian Libotean + +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. +*/ + +#ifndef M_CMDLINE_VERSION_H +#define M_CMDLINE_VERSION_H + +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 0 +#define __RELEASE_NUM 4 +#define __BUILD_NUM 1 + +#define VERSION PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM) + +#define __PLUGINVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __PLUGINVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM +#define __STRINGIFY_(x) #x +#define __STRINGIFY(x) __STRINGIFY_(x) +#define __VERSION_STRING __STRINGIFY(__PLUGINVERSION_STRING_DOTS) + +#define __DESC "This plugin lets you control Miranda from the command line." +#define __AUTHOR "Cristian Libotean" +#define __AUTHOREMAIL "eblis102@yahoo.com" +#define __COPYRIGHT "© 2007-2011 Cristian Libotean" +#define __AUTHORWEB "http://www.miranda-im.org/" + +#if defined(WIN64) || defined(_WIN64) +#define __PLUGIN_DISPLAY_NAME "Command Line (x64)" +#else +#define __PLUGIN_DISPLAY_NAME "Command Line" +#endif + +#endif //M_CMDLINE_VERSION_H -- cgit v1.2.3