summaryrefslogtreecommitdiff
path: root/plugins/CmdLine/src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-16 16:31:53 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-16 16:31:53 +0000
commit5b0a53a6d3f1b8d70b34631d96d3815d0a334dd3 (patch)
tree9b38676d8ae565bac52063f5398dde110082a26f /plugins/CmdLine/src
parent1cf47d1eaff4d7d7242d0ab87dd540ae5b400833 (diff)
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
Diffstat (limited to 'plugins/CmdLine/src')
-rw-r--r--plugins/CmdLine/src/CmdLine.cpp87
-rw-r--r--plugins/CmdLine/src/commonheaders.h112
-rw-r--r--plugins/CmdLine/src/hooked_events.cpp113
-rw-r--r--plugins/CmdLine/src/hooked_events.h43
-rw-r--r--plugins/CmdLine/src/mimcmd_data.cpp43
-rw-r--r--plugins/CmdLine/src/mimcmd_data.h120
-rw-r--r--plugins/CmdLine/src/mimcmd_handlers.cpp2307
-rw-r--r--plugins/CmdLine/src/mimcmd_handlers.h55
-rw-r--r--plugins/CmdLine/src/mimcmd_ipc.cpp105
-rw-r--r--plugins/CmdLine/src/mimcmd_ipc.h56
-rw-r--r--plugins/CmdLine/src/resource.h15
-rw-r--r--plugins/CmdLine/src/services.cpp106
-rw-r--r--plugins/CmdLine/src/services.h34
-rw-r--r--plugins/CmdLine/src/utils.cpp461
-rw-r--r--plugins/CmdLine/src/utils.h62
-rw-r--r--plugins/CmdLine/src/version.h49
16 files changed, 3768 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <time.h>
+
+#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 <status> [<account>].\nPossible values for <status> are: offline, online, away, dnd, na, occupied, freechat, invisible, onthephone, outtolunch.\n<Account> 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 <message> [<account>].\n<Message> is the new away message.\n<Account> 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 <status> [<account>].\n<XStatus> is the new extended status to set. Possible values are:...\n<Account> 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 [<command>].\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 <service> (d|s)<wParam> (d|s)<lParam>. The command will call Miranda <service> 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 <contact> [<contact> [<contact> [...]]] <message>. The command will send <message> to the specified contact(s) - at least one contact must be specified - all parameters except the last one are considered recipients.\n<Contact> has the following format:<name>[:<account>]. <Name> is the contact display name or unique ID and <account> 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 <module> <name> (b|i|d|s|w)<value>\n db delete <module> <name>\n db get <module> <name>.\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. <Module> is the name of the module where the key should be located, <name> is the name of the key and <value> is the value to be written. A character must be placed before <value> 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|<account>) <setting> [<params>].\n <setting> is one of the following settings:\n status (disable | enable | toggle).\n server <proxy type> <server> <port>"
+#define MIMCMD_HELP_CONTACTS "Allows you to search/list contacts or open a message windows for specified contacts.\nUsage:\n contacts list [<keyword> [account:<account>] [id:<id>] [status:<status>] [<keyword> [...]]]. The command will search all contacts and display the ones matching the search criteria. To search for a specific account use the keyword 'account:<account>'. To search for contacts that have a certain id use the keyword 'id:<id>'. To search for contacts that have a certain status use 'status:<status>'.\n contacts open [<keyword> [account:<account>] [id:<id>] [status:<status>] [<keyword> [...]]]. 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:<account>'. To search for contacts that have a certain id use the keyword 'id:<id>'. To search for contacts that have a certain status use 'status:<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 <command> <contact>.\n <command> is one of the following commands:\n unread - show unread messages for that contact.\n show <contact> <start> <finish> - show history from event number <start> to <finish>. 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 <protocol> new_nickname"
+#define MIMCMD_HELP_IGNORE "Ignores or removes ignore flags for specific contacts.\nUsage:\n ignore (block | unblock) <contact> [<contact> [<contact> [..]]]. 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", "<unknown>", 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 <stdarg.h>
+
+//#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