summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-04 22:09:42 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-04 22:09:42 +0000
commit801367d0b94426c1160f05aeb6fea70938085894 (patch)
treec8f60e1988ae7e43d4addb8ba2138d8880dfdf9b
parent65e002b63efdb00571d0ba4ec1a73b14e1d7d3a0 (diff)
CmdLine added, not adopted yet
git-svn-id: http://svn.miranda-ng.org/main/trunk@764 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r--plugins/CmdLine/CmdLine.html12
-rw-r--r--plugins/CmdLine/CmdLine.sln41
-rw-r--r--plugins/CmdLine/CmdLine/CmdLine.cpp94
-rw-r--r--plugins/CmdLine/CmdLine/CmdLine.rc63
-rw-r--r--plugins/CmdLine/CmdLine/CmdLine.vcproj438
-rw-r--r--plugins/CmdLine/CmdLine/commonheaders.h132
-rw-r--r--plugins/CmdLine/CmdLine/hooked_events.cpp139
-rw-r--r--plugins/CmdLine/CmdLine/hooked_events.h45
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_data.cpp43
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_data.h126
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_handlers.cpp2307
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_handlers.h58
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_ipc.cpp105
-rw-r--r--plugins/CmdLine/CmdLine/mimcmd_ipc.h58
-rw-r--r--plugins/CmdLine/CmdLine/mirandaMem.cpp28
-rw-r--r--plugins/CmdLine/CmdLine/mirandaMem.h30
-rw-r--r--plugins/CmdLine/CmdLine/resource.h15
-rw-r--r--plugins/CmdLine/CmdLine/services.cpp107
-rw-r--r--plugins/CmdLine/CmdLine/services.h36
-rw-r--r--plugins/CmdLine/CmdLine/utils.cpp461
-rw-r--r--plugins/CmdLine/CmdLine/utils.h63
-rw-r--r--plugins/CmdLine/CmdLine/version.h49
-rw-r--r--plugins/CmdLine/CmdLine/version.rc100
-rw-r--r--plugins/CmdLine/docs/CmdLine_readme.txt199
-rw-r--r--plugins/CmdLine/executable/MimCmd/MimCmd.cpp105
-rw-r--r--plugins/CmdLine/executable/MimCmd/MimCmd.vcproj404
-rw-r--r--plugins/CmdLine/executable/MimCmd/commands.cpp239
-rw-r--r--plugins/CmdLine/executable/MimCmd/commands.h44
-rw-r--r--plugins/CmdLine/executable/MimCmd/common.h30
-rw-r--r--plugins/CmdLine/executable/MimCmd/langpack.cpp377
-rw-r--r--plugins/CmdLine/executable/MimCmd/langpack.h92
-rw-r--r--plugins/CmdLine/executable/MimCmd/resource.h14
-rw-r--r--plugins/CmdLine/executable/MimCmd/version.rc100
-rw-r--r--plugins/CmdLine/files_release.txt1
-rw-r--r--plugins/CmdLine/files_releasex64.txt1
-rw-r--r--plugins/CmdLine/files_source.txt5
-rw-r--r--plugins/CmdLine/pack source.bat8
-rw-r--r--plugins/CmdLine/pack symbols.bat12
-rw-r--r--plugins/CmdLine/pack x64.bat18
-rw-r--r--plugins/CmdLine/pack.bat18
-rw-r--r--plugins/CmdLine/symbols_exclude.txt1
41 files changed, 6218 insertions, 0 deletions
diff --git a/plugins/CmdLine/CmdLine.html b/plugins/CmdLine/CmdLine.html
new file mode 100644
index 0000000000..31beec9f89
--- /dev/null
+++ b/plugins/CmdLine/CmdLine.html
@@ -0,0 +1,12 @@
+<html>
+ <head></head>
+ <body>
+ <center>
+ <h1>CmdLine Test Page</h1>
+
+ <p>CmdLine version 0.0.4.1
+ </p>
+ <p><a href="CmdLine.zip">CmdLine.zip</a></p>
+ </center>
+ </body>
+</html>
diff --git a/plugins/CmdLine/CmdLine.sln b/plugins/CmdLine/CmdLine.sln
new file mode 100644
index 0000000000..da95391077
--- /dev/null
+++ b/plugins/CmdLine/CmdLine.sln
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdLine", "CmdLine\CmdLine.vcproj", "{73BA9CA5-640D-4F30-A157-A73557A25F98}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "executable", "executable", "{F94BE703-4A5E-4864-B15D-C942212DAD05}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MimCmd", "executable\MimCmd\MimCmd.vcproj", "{1E3BB48A-FFBC-4A03-8C43-9124A484BE51}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Debug|Win32.ActiveCfg = Debug|Win32
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Debug|Win32.Build.0 = Debug|Win32
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Debug|x64.ActiveCfg = Debug|x64
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Debug|x64.Build.0 = Debug|x64
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Release|Win32.ActiveCfg = Release|Win32
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Release|Win32.Build.0 = Release|Win32
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Release|x64.ActiveCfg = Release|x64
+ {73BA9CA5-640D-4F30-A157-A73557A25F98}.Release|x64.Build.0 = Release|x64
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Debug|Win32.Build.0 = Debug|Win32
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Debug|x64.ActiveCfg = Debug|x64
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Debug|x64.Build.0 = Debug|x64
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Release|Win32.ActiveCfg = Release|Win32
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Release|Win32.Build.0 = Release|Win32
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Release|x64.ActiveCfg = Release|x64
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {1E3BB48A-FFBC-4A03-8C43-9124A484BE51} = {F94BE703-4A5E-4864-B15D-C942212DAD05}
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/CmdLine/CmdLine/CmdLine.cpp b/plugins/CmdLine/CmdLine/CmdLine.cpp
new file mode 100644
index 0000000000..9847786a97
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/CmdLine.cpp
@@ -0,0 +1,94 @@
+/*
+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"
+#include "mimcmd_ipc.h"
+
+char ModuleName[] = "CmdLine";
+HINSTANCE hInstance;
+
+PLUGINLINK *pluginLink;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_DISPLAY_NAME,
+ VERSION,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ 0, //unicode aware
+ 0,
+ {0x2f1a117c, 0x3c1b, 0x4c01, {0x89, 0xea, 0x6d, 0x8f, 0xd8, 0x5a, 0x9b, 0x4c}} //{2f1a117c-3c1b-4c01-89ea-6d8fd85a9b4c}
+ }; //not used
+
+OLD_MIRANDAPLUGININFO_SUPPORT;
+
+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(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+// InitServices();
+ if (InitServer())
+ {
+ MessageBox(0, "Could not initialize CmdLine plugin property", "Error", MB_ICONEXCLAMATION | MB_OK);
+ }
+
+ HookEvents();
+
+ InitializeMirandaMemFunctions();
+
+ 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/CmdLine/CmdLine.rc b/plugins/CmdLine/CmdLine/CmdLine.rc
new file mode 100644
index 0000000000..1b7522b7a4
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/CmdLine.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/CmdLine/CmdLine/CmdLine.vcproj b/plugins/CmdLine/CmdLine/CmdLine.vcproj
new file mode 100644
index 0000000000..11c10635c9
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/CmdLine.vcproj
@@ -0,0 +1,438 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="CmdLine"
+ ProjectGUID="{73BA9CA5-640D-4F30-A157-A73557A25F98}"
+ RootNamespace="CmdLine"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\..\..\..\cvs\test miranda\Plugins"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../include/"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CMDLINE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../include/"
+ PreprocessorDefinitions="WIN64;_DEBUG;_WINDOWS;_USRDLL;CMDLINE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../include/"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CMDLINE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ BaseAddress="0x2F0B0000"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../include/"
+ PreprocessorDefinitions="WIN64;NDEBUG;_WINDOWS;_USRDLL;CMDLINE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ BaseAddress="0x2F0B0000"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\CmdLine.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\hooked_events.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_data.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_handlers.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_ipc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mirandaMem.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\services.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\commonheaders.h"
+ >
+ </File>
+ <File
+ RelativePath=".\hooked_events.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_data.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_handlers.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mimcmd_ipc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mirandaMem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\services.h"
+ >
+ </File>
+ <File
+ RelativePath=".\utils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\version.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\CmdLine.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\version.rc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\docs\CmdLine_readme.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/plugins/CmdLine/CmdLine/commonheaders.h b/plugins/CmdLine/CmdLine/commonheaders.h
new file mode 100644
index 0000000000..8a04e27e9a
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/commonheaders.h
@@ -0,0 +1,132 @@
+/*
+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
+
+#ifndef MIRANDA_VER
+#define MIRANDA_VER 0x0800
+#endif
+
+#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 "version.h"
+#include "utils.h"
+#include "mirandaMem.h"
+//#include "services.h"
+//#include "dlg_handlers.h"
+
+#include "resource.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 "sdk/m_versioninfo.h"
+#include "sdk/m_statusplugins.h"
+#include "sdk//m_updater.h"
+
+#include "hooked_events.h"
+
+extern char ModuleName[];
+extern HINSTANCE hInstance;
+
+//extern PLUGINLINK *pluginLink;
+
+extern int bUseANSIStrings;
+
+extern int bWaitForUnload;
+
+#define ID_ICQ_EXIT 40001
+
+#define OLD_MIRANDAPLUGININFO_SUPPORT PLUGININFO oldPluginInfo = { \
+ sizeof(PLUGININFO), \
+ pluginInfo.shortName, \
+ pluginInfo.version, \
+ pluginInfo.description, \
+ pluginInfo.author, \
+ pluginInfo.authorEmail, \
+ pluginInfo.copyright, \
+ pluginInfo.homepage, \
+ pluginInfo.flags, \
+ pluginInfo.replacesDefaultModule \
+}; \
+\
+extern "C" __declspec(dllexport) PLUGININFO *MirandaPluginInfo(DWORD mirandaVersion) \
+{ \
+ return &oldPluginInfo; \
+}
+
+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/CmdLine/hooked_events.cpp b/plugins/CmdLine/CmdLine/hooked_events.cpp
new file mode 100644
index 0000000000..a8a13c6420
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/hooked_events.cpp
@@ -0,0 +1,139 @@
+/*
+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 "hooked_events.h"
+#include "mimcmd_ipc.h"
+#include "services.h"
+
+HANDLE hModulesLoaded;
+HANDLE hOptionsInitialize;
+HANDLE hShutdown;
+HANDLE hProtoAck;
+
+int bShouldProcessAcks = FALSE;
+
+ACKDATA acks[50] = {0};
+int cAcks = sizeof(acks) / sizeof(acks[0]);
+
+#define HOST "http://eblis.tla.ro/projects"
+
+#if defined(WIN64) || defined(_WIN64)
+#define CMDLINE_VERSION_URL HOST "/miranda/CmdLine/updater/x64/CmdLine.html"
+#define CMDLINE_UPDATE_URL HOST "/miranda/CmdLine/updater/x64/CmdLine.zip"
+#else
+#define CMDLINE_VERSION_URL HOST "/miranda/CmdLine/updater/CmdLine.html"
+#define CMDLINE_UPDATE_URL HOST "/miranda/CmdLine/updater/CmdLine.zip"
+#endif
+#define CMDLINE_VERSION_PREFIX "CmdLine version "
+
+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)
+{
+ char buffer[1024];
+ Update update = {0};
+ update.cbSize = sizeof(Update);
+ update.szComponentName = __PLUGIN_DISPLAY_NAME;
+ update.pbVersion = (BYTE *) CreateVersionString(VERSION, buffer);
+ update.cpbVersion = (int) strlen((char *) update.pbVersion);
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+ update.szBetaVersionURL = CMDLINE_VERSION_URL;
+ update.szBetaUpdateURL = CMDLINE_UPDATE_URL;
+ update.pbBetaVersionPrefix = (BYTE *) CMDLINE_VERSION_PREFIX;
+ update.cpbBetaVersionPrefix = (int) strlen(CMDLINE_VERSION_PREFIX);
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM) &update);
+
+ 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/CmdLine/hooked_events.h b/plugins/CmdLine/CmdLine/hooked_events.h
new file mode 100644
index 0000000000..2498638400
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/hooked_events.h
@@ -0,0 +1,45 @@
+/*
+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
+
+#include "commonheaders.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/CmdLine/mimcmd_data.cpp b/plugins/CmdLine/CmdLine/mimcmd_data.cpp
new file mode 100644
index 0000000000..bbf64278d3
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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 "mimcmd_data.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/CmdLine/mimcmd_data.h b/plugins/CmdLine/CmdLine/mimcmd_data.h
new file mode 100644
index 0000000000..d8570548f8
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/mimcmd_data.h
@@ -0,0 +1,126 @@
+/*
+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
+
+#ifndef MIRANDA_VER
+#define MIRANDA_VER 0x0400
+#endif
+
+#include "commonheaders.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/CmdLine/mimcmd_handlers.cpp b/plugins/CmdLine/CmdLine/mimcmd_handlers.cpp
new file mode 100644
index 0000000000..0f828f8e0e
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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 "mimcmd_handlers.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/CmdLine/mimcmd_handlers.h b/plugins/CmdLine/CmdLine/mimcmd_handlers.h
new file mode 100644
index 0000000000..3446445d58
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/mimcmd_handlers.h
@@ -0,0 +1,58 @@
+/*
+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 <stdio.h>
+
+#include "commonheaders.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/CmdLine/mimcmd_ipc.cpp b/plugins/CmdLine/CmdLine/mimcmd_ipc.cpp
new file mode 100644
index 0000000000..bc7c2b4cbe
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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 "mimcmd_ipc.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/CmdLine/mimcmd_ipc.h b/plugins/CmdLine/CmdLine/mimcmd_ipc.h
new file mode 100644
index 0000000000..3b845c030a
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/mimcmd_ipc.h
@@ -0,0 +1,58 @@
+/*
+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 <windows.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/CmdLine/mirandaMem.cpp b/plugins/CmdLine/CmdLine/mirandaMem.cpp
new file mode 100644
index 0000000000..a945c4c1b1
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/mirandaMem.cpp
@@ -0,0 +1,28 @@
+/*
+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 "mirandaMem.h"
+
+struct MM_INTERFACE mmi;
+
+void InitializeMirandaMemFunctions()
+{
+ mir_getMMI(&mmi);
+} \ No newline at end of file
diff --git a/plugins/CmdLine/CmdLine/mirandaMem.h b/plugins/CmdLine/CmdLine/mirandaMem.h
new file mode 100644
index 0000000000..3468fcbc41
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/mirandaMem.h
@@ -0,0 +1,30 @@
+/*
+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_MIRANDA_MEM_H
+#define M_CMDLINE_MIRANDA_MEM_H
+
+#include "commonheaders.h"
+
+extern struct MM_INTERFACE mmi;
+
+void InitializeMirandaMemFunctions();
+
+#endif \ No newline at end of file
diff --git a/plugins/CmdLine/CmdLine/resource.h b/plugins/CmdLine/CmdLine/resource.h
new file mode 100644
index 0000000000..0268ce4765
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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/CmdLine/services.cpp b/plugins/CmdLine/CmdLine/services.cpp
new file mode 100644
index 0000000000..d5dd45fad8
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/services.cpp
@@ -0,0 +1,107 @@
+/*
+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 "services.h"
+#include "mimcmd_ipc.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/CmdLine/services.h b/plugins/CmdLine/CmdLine/services.h
new file mode 100644
index 0000000000..07f6ffaeec
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/services.h
@@ -0,0 +1,36 @@
+/*
+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 "commonheaders.h"
+#include "mimcmd_data.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/CmdLine/utils.cpp b/plugins/CmdLine/CmdLine/utils.cpp
new file mode 100644
index 0000000000..241f6ecfe7
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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 "utils.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/CmdLine/utils.h b/plugins/CmdLine/CmdLine/utils.h
new file mode 100644
index 0000000000..70bdb84fad
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/utils.h
@@ -0,0 +1,63 @@
+/*
+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>
+#include "commonheaders.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/CmdLine/version.h b/plugins/CmdLine/CmdLine/version.h
new file mode 100644
index 0000000000..03656ae51d
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/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
diff --git a/plugins/CmdLine/CmdLine/version.rc b/plugins/CmdLine/CmdLine/version.rc
new file mode 100644
index 0000000000..effbb6fe04
--- /dev/null
+++ b/plugins/CmdLine/CmdLine/version.rc
@@ -0,0 +1,100 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+#include "version.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __PLUGINVERSION_STRING
+ PRODUCTVERSION __PLUGINVERSION_STRING
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", __PLUGIN_DISPLAY_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/CmdLine/docs/CmdLine_readme.txt b/plugins/CmdLine/docs/CmdLine_readme.txt
new file mode 100644
index 0000000000..349aa932e8
--- /dev/null
+++ b/plugins/CmdLine/docs/CmdLine_readme.txt
@@ -0,0 +1,199 @@
+CmdLine plugin v.0.0.4.1
+Copyright © 2007-2011 Cristian Libotean
+
+This plugin lets you control Miranda from the command line.
+It does this using an additional executable file that's used to pass command line arguments to Miranda.
+This plugin will not work correctly when multiple instances of Miranda and the plugin are running at
+the same time. Do not run more than once instance of the plugin at the same time!
+
+The executable file (MimCmd.exe) can be placed anywhere, it doesn't have to be inside Miranda's main folder.
+
+Changes
+=======
++ : new feature
+* : changed
+! : bufgix
+- : feature removed or disabled because of pending bugs
+
+v. 0.0.4.1 - 2011/08/22
+ + made x64 version updater aware
+
+v. 0.0.4.0 - 2011/07/25
+ + Added 'mimcmd contacts open' command which opens all the message windows for contacts which have unread messages
+ + Added 'mimcmd ignore' command which can ignore or remove the ignore flags for specified contacts
+ + Added 'mimcmd setnickname' command which can change the owner's nickname on given protocols
+
+v. 0.0.3.0 - 2010/11/01
+ + Added per account information to status command. The 'mimcmd status' will now list the global status as well as per account status.
+ * Code rewrite to take advantage of accounts instead of protocols - expect problems :)
+ ! The code should now work with account names instead of internal protocol names.
+ ! The code no longer converts the account name (former protocol name) to uppercase.
+
+v. 0.0.2.20 - 2009/11/16
+ + x64 support (not tested !!)
+
+v. 0.0.2.12 - 2009/05/28
+ ! Fixed quit command
+ ! Possible fix for crash in history command
+
+v. 0.0.2.11 - 2009/05/18
+ ! Issuing buffer full events did not work correctly (the buffer was reset before Miranda had a chance to process it)
+ ! Showing history did not work correctly for a big number of entries.
+ ! Crash when encountering a NULL contact id.
+
+v. 0.0.2.10 - 2009/05/18
+ + Added contact id to 'contact list' command.
+ + Added id: search parameter to contact command.
+
+v. 0.0.2.9 - 2008/05/12
+ ! Only set away message for protocols that support it.
+
+v. 0.0.2.8 - 2008/01/24
+ * Increased timeout when sending message from 4 seconds to 15 seconds.
+ * Changed beta versions server.
+
+v. 0.0.2.7 - 2007/11/15
+ + Added quit wait command. If this command is used the command will return only when CmdLine plugin is unloaded by Miranda.
+ Warning: The status will be reported as an error, "Miranda has been closed or an error has occured while waiting for the result, could not process request."
+
+v. 0.0.2.6 - 2007/09/27
+ ! Fix for history unread command truncating messages ( :) )
+ + Added status:<status> parameter to contacts command.
+
+v. 0.0.2.5 - 2007/09/27
+ ! Fix for history command truncating messages.
+ + Added version command - mimcmd -v (works even if miranda is not started).
+
+v. 0.0.2.4 - 2007/08/09
+ + Do not allow more than 1 instance of CmdLine to run at the same time.
+ * Changed the order of the parameters for message command (now the message parameter is the last one).
+ * Increased parameter maximum size from 256 characters to 512.
+
+v. 0.0.2.3 - 2007/08/09
+ ! Forgot to update version number.
+
+v. 0.0.2.2 - 2007/07/31
+ + Added command to open the message window for specified contacts.
+ * Contacts list command will also show the contact handle.
+
+v. 0.0.2.1 - 2007/05/30
+ + Added version command.
+
+v. 0.0.2.0 - 2007/05/28
+ ! Successfully sent messages are now stored in the database.
+ + Added contacts search function (keywords can match either the contact name or the protocol).
+ + Added unread events command.
+ + Added view history command.
+
+v. 0.0.1.3 - 2007/05/13
+ ! Status change now works correctly when KeepStatus is installed.
+
+v. 0.0.1.2 - 2007/04/23
+ ! Allow usage information to be translated.
+
+v. 0.0.1.1 - 2007/04/21
+ * If connection with Miranda could not be established try to read language pack file in current folder too.
+ ! Convert strings to OEM before printing them (fixes translations for non latin based alphabets).
+
+v. 0.0.1.0 - 2007/04/19
+ + Added translation support for command line utility.
+ + Added database command (you can write, read and delete settings).
+ + Added proxy command. Currently it will *not* change proxy servers for all netlib users as there is no way
+ to get that list (yet). It will only change protocol settings (client to client connnections, updater, help and
+ others will not be changed). Requires a Miranda restart before taking effect.
+
+v. 0.0.0.4 - 2007/04/16
+ + Rebased dll (0x2F0B0000)
+
+v. 0.0.0.3 - 2007/04/04
+ ! Status was not set correctly when protocol name was specified.
+
+v. 0.0.0.2 - 2007/04/02
+ + Added yamn command.
+ + Added message command.
+
+v. 0.0.0.1 - 2007/03/30
+ + First release.
+
+
+******Translateable strings****** (updated for version 0.0.2.6)
+[Available commands: ]
+Miranda has been closed or an error has occured while waiting for the result, could not process request.
+%s usage:\n
+%s <command> [<param> [, <param> ..]]\n
+This will will tell Miranda to run the specified command. The commands can have zero, one or more parameters. Use '%s help' to get a list of possible commands.\n
+No command can have more than %d parameters\n
+Could not create connection with Miranda or could not retrieve list of known commands.\n
+Unknown command '%s'.\n
+Change protocol status either globally or per protocol.\nUsage: status <status> [<protocol>].\nPossible values for <status> are: offline, online, away, dnd, na, occupied, freechat, invisible, onthephone, outtolunch.\n<Protocol> is the name of the protocol. If it's not specified then the command will issue a global status change.
+Change away message either globally or per protocol.\nUsage: awaymsg <message> [<protocol>].\n<Message> is the new away message.\n<Protocol> is an optional parameter specifying the protocol to set the away message for. If not specified then the away message will be set globally.
+Change extended status either globally or per protocol.\nUsage xstatus <status> [<protocol>].\n<XStatus> is the new extended status to set. Possible values are:...\n<Protocol> is an optional parameter specifying the protocol for which extended status is set. If not specified then extended status for all protocols will be changed.\nNOTE: Not all protocols support extended status.
+Disables or enables popups display.\nUsage popups (disable | enable | toggle).\nThe command will either enable or disable popups display.
+Disables or enables sounds.\nUsage: sounds (disable | enable | toggle).\nThe command will either disable or enable sounds.
+Hides or shows the contact list window.\nUsage: clist (show | hide | toggle).\nThe command will either show or hide the contact list window.
+Closes Miranda.\nUsage: quit.
+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.
+Notifies Exchange plugin to check for email.\nUsage: exchange check
+Notifies YAMN plugin to check for email.\nUsage: yamn check.
+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.
+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>[:<protocol>]. <Name> is the contact display name or unique ID and <protocol> is an optional parameter representing the protocol of the contact (useful in case there is more than one contact with the same name).\nNOTE:The message string cannot exceed 512 characters.
+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.
+Configures proxy settings either globally or per protocol.\nUsage: proxy (global|<protocol>) <setting> [<params>].\n <setting> is one of the following settings:\n status (disable | enable | toggle).\n server <proxy type> <server> <port>
+Allows you to search/list contacts or open a message windows for specified contacts.\nUsage:\n contacts list [<keyword> [protocol:<protocol>] [status:<status>] [<keyword> [...]]]. The command will search all contacts and display the ones matching the search criteria. To search for a specific protocol use the keyword 'protocol:<protocol>'. To search for contacts that have a certain status use 'status:<status>'.\n contacts open [<keyword> [protocol:<protocol>] [status:<status>] [<keyword> [...]]]. The command will open a message window for all contacts that match the search criteria. To search for a specific protocol use the keyword 'protocol:<protocol>'. To search for contacts that have a certain status use 'status:<status>'.
+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).
+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.
+
+Popups are currently enabled.
+Popups are currently disabled.
+Popups were enabled successfully.
+Popups could not be enabled.
+Popups were disabled successfully.
+Popups could not be disabled.
+Sounds are currently enabled.
+Sounds are currently disabled.
+Sounds were enabled successfully.
+Sounds could not be enabled.
+Sounds were disabled successfully.
+Sounds could not be disabled.
+Contact list is currectly shown.
+Contact list is currently hidden.
+Contact list was shown successfully.
+Contact list could not be shown.
+Contact list was hidden successfully.
+Contact list could not be hidden.
+Command '%s' is not currently supported.
+Wrong number of parameters for command '%s'.
+Unknown parameter '%s' for command '%s'.
+Current status: %s.
+Changed global status to '%s' (previous status was '%s').
+Changed '%s' status to '%s' (previous status was '%s').
+'%s' doesn't seem to be a valid protocol.
+Failed to change status for protocol '%s' to '%s'.
+Successfully set '%s' status message to '%s' (status is '%s').
+Changed '%s' status message to '%s' (status is '%s').
+'%s' doesn't seem to be a valid protocol.
+Failed to change status message for protocol '%s' to '%s' (status is '%s').
+Issued check email command to Exchange plugin.
+Exchange plugin is not running.
+Issued check email command to YAMN plugin.
+YAMN plugin is not running.
+CallService call successful: service '%s' returned %d.
+Invalid parameter '%s' passed to CallService command.
+Service '%s' does not exist.
+Message sent to '%s'.
+Could not send message to '%s'.
+Setting '%s/%s' deleted.
+Wrote '%s:%s' to database entry '%s/%s'.
+'%s/%s' - %s.
+Could not retrieve setting '%s/%s': %s.
+Setting '%s/%s' was not found.
+'%s' proxy was disabled.
+'%s' proxy was enabled.
+%s proxy server: %s %s:%d.
+%s proxy set to %s %s:%d.
+%s The port or the proxy type parameter is invalid.
+'%s' doesn't seem to be a valid protocol.
+Could not find contact handle for contact '%s'.
+No unread messages found.
+%s:%s - %d unread events.
+Contact '%s' has '%d' events in history. \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/MimCmd.cpp b/plugins/CmdLine/executable/MimCmd/MimCmd.cpp
new file mode 100644
index 0000000000..2709d6c034
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/MimCmd.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 "common.h"
+
+//why ??
+//Who's using it ?
+PLUGINLINK *pluginLink;
+
+char *GetProgramName(char *programName, int size)
+{
+ char name[512];
+ GetModuleFileName(GetModuleHandle(NULL), name, sizeof(name));
+ char *p = strrchr(name, '\\');
+ if (p)
+ {
+ STRNCPY(programName, p + 1, size);
+ }
+ else{
+ STRNCPY(programName, name, size);
+ }
+
+ return programName;
+}
+
+void PrintUsage()
+{
+ char name[128];
+ GetProgramName(name, sizeof(name));
+
+ lpprintf(Translate("%s usage:\n"), name);
+ lpprintf(Translate("%s <command> [<param> [, <param> ..]]\n"), name);
+ lpprintf(Translate("This will tell Miranda to run the specified command. The commands can have zero, one or more parameters. Use '%s help' to get a list of possible commands.\n"), name);
+ lpprintf(Translate("No command can have more than %d parameters\n"), MAX_ARGUMENTS - 1);
+}
+
+void ShowVersion()
+{
+ char name[128];
+ char message[1024];
+ GetProgramName(name, sizeof(name));
+ mir_snprintf(message, sizeof(message), Translate("%s version %s"), name, __VERSION_STRING);
+
+ lpprintf("%s\n", message);
+}
+
+int main(int argc, char *argv[])
+{
+ int error = 0;
+ if ((argc == 2) && (strcmp(argv[1], "-v") == 0))
+ {
+ ShowVersion();
+
+ return 0;
+ }
+
+ if ((InitClient()) || (ConnectToMiranda()) || (GetKnownCommands()) || (LoadLangPackModule(sdCmdLine->mimFolder)))
+ {
+ LoadLangPackModule(".");
+ lpprintf(Translate("Could not create connection with Miranda or could not retrieve list of known commands.\n"));
+ error = MIMRES_NOMIRANDA;
+ }
+ else{
+ if ((argc <= 1) || (argc > MAX_ARGUMENTS))
+ {
+ PrintUsage();
+ }
+ else{
+ PReply reply = ParseCommand(argv, argc);
+ if (reply)
+ {
+ error = reply->code;
+ lpprintf("%s\n", reply->message);
+ }
+ else{
+ lpprintf(Translate("Unknown command '%s'.\n"), argv[1]);
+ }
+
+ DestroyKnownCommands();
+ DisconnectFromMiranda();
+ DestroyClient();
+ LangPackShutdown();
+ }
+ }
+
+ return error;
+}
+
diff --git a/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj b/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj
new file mode 100644
index 0000000000..fb04bfb375
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/MimCmd.vcproj
@@ -0,0 +1,404 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MimCmd"
+ ProjectGUID="{1E3BB48A-FFBC-4A03-8C43-9124A484BE51}"
+ RootNamespace="MimCmd"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\..\..\..\..\cvs\test miranda"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN64;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../../../include/"
+ PreprocessorDefinitions="WIN64;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\commands.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\langpack.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MimCmd.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Detect64BitPortabilityProblems="false"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Detect64BitPortabilityProblems="false"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\CmdLine\mimcmd_ipc.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\commands.h"
+ >
+ </File>
+ <File
+ RelativePath=".\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\langpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\version.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/plugins/CmdLine/executable/MimCmd/commands.cpp b/plugins/CmdLine/executable/MimCmd/commands.cpp
new file mode 100644
index 0000000000..b04b9ba7ba
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/commands.cpp
@@ -0,0 +1,239 @@
+/*
+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 "commands.h"
+
+inline char *STRNCPY(char *output, const char *input, size_t size)
+{
+ char *res = strncpy(output, input, size);
+ output[size - 1] = 0;
+
+ return res;
+}
+
+LISTCOMMANDS ListCommands = NULL;
+
+PCommand knownCommands = NULL;
+int cKnownCommands = 0;
+
+HMODULE hCmdLineDLL = NULL;
+
+char *GetMirandaFolder(char *mimFolder, int size)
+{
+ STRNCPY(mimFolder, sdCmdLine->mimFolder, size);
+ mimFolder[size - 1] = 0;
+
+ return mimFolder;
+}
+
+
+int ConnectToMiranda()
+{
+ char pluginPath[1024];
+ GetMirandaFolder(pluginPath, sizeof(pluginPath));
+ strcat(pluginPath, "\\plugins\\cmdline.dll");
+
+ ListCommands = NULL;
+
+ hCmdLineDLL = LoadLibrary(pluginPath);
+
+ int failure = 1;
+ if (hCmdLineDLL)
+ {
+ ListCommands = (LISTCOMMANDS) GetProcAddress(hCmdLineDLL, "ListCommands");
+ }
+
+ if (ListCommands)
+ {
+ failure = 0;
+ }
+
+ return failure;
+}
+
+int DisconnectFromMiranda()
+{
+ return FreeLibrary(hCmdLineDLL);
+}
+
+int GetKnownCommands()
+{
+ ListCommands(&knownCommands, &cKnownCommands);
+
+ return (knownCommands == NULL);
+}
+
+int DestroyKnownCommands()
+{
+
+
+ return 0;
+}
+
+PCommand GetCommand(char *command)
+{
+ int i;
+ char lower[512];
+ STRNCPY(lower, command, sizeof(lower));
+ _strlwr(lower);
+
+ for (i = 0; i < cKnownCommands; i++)
+ {
+ if (strcmp(knownCommands[i].command, lower) == 0)
+ {
+ return &knownCommands[i];
+ }
+ }
+
+ //allow more parameters to trigger the help command - /h -h /? --help
+ if ((strcmp(lower, "/h") == 0) || (strcmp(lower, "-h") == 0) || (strcmp(lower, "/?") == 0) || (strcmp(lower, "--help") == 0))
+ {
+ for (i = 0; i < cKnownCommands; i++)
+ {
+ if (knownCommands[i].ID == MIMCMD_HELP)
+ {
+ return &knownCommands[i];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void HandleHelpCommand(PCommand helpCommand, char *argv[], int argc, PReply reply)
+{
+ const int size = REPLY_SIZE;
+ if (argc >= 3)
+ {
+ PCommand command = GetCommand(argv[2]);
+
+ if (command)
+ {
+ reply->code = MIMRES_SUCCESS;
+ STRNCPY(reply->message, Translate(command->help), size);
+ }
+ else{
+ reply->code = MIMRES_NOTFOUND;
+ _snprintf(reply->message, size, Translate("No help for '%s'."), argv[2]);
+ reply->message[size -1 ] = 0;
+ }
+ }
+ else{
+ reply->code = MIMRES_SUCCESS;
+ STRNCPY(reply->message, Translate("Available commands: "), size);
+
+ int i;
+ for (i = 0; i < cKnownCommands - 1; i++)
+ {
+ strncat(reply->message, knownCommands[i].command, size);
+ strncat(reply->message, ", ", size);
+ }
+ strncat(reply->message, knownCommands[cKnownCommands - 1].command, size);
+ strncat(reply->message, ".", size);
+ }
+}
+
+PReply ParseCommand(char *argv[], int argc)
+{
+ PCommand command = GetCommand(argv[1]);
+ if (command)
+ {
+ PReply reply = &sdCmdLine->reply;
+ if (command->ID == MIMCMD_HELP)
+ {
+ HandleHelpCommand(command, argv, argc, reply);
+ }
+ else{
+ ProcessConsoleCommand(command, argv, argc, reply);
+ }
+
+ return reply;
+ }
+ else{
+ return NULL;
+ }
+}
+
+void FillSharedDataStruct(PCommand command, char *arguments[], int count)
+{
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ STRNCPY(sdCmdLine->arguments[i], arguments[i], ARGUMENT_SIZE);
+ }
+
+ sdCmdLine->cArguments = count;
+ sdCmdLine->command = *command;
+ *sdCmdLine->reply.message = 0;
+ sdCmdLine->reply.code =-1;
+}
+
+void ProcessConsoleCommand(PCommand command, char *arguments[], int count, PReply reply)
+{
+ const HANDLE events[] = {heServerDone, heServerClose, heServerBufferFull};
+ const int cEvents = sizeof(events) / sizeof(events[0]);
+
+ if (WaitForSingleObject(hmClient, INFINITE) == WAIT_OBJECT_0)
+ {//got the mutex, we're the only one who can talk to miranda now
+ FillSharedDataStruct(command, arguments, count);
+ SetEvent(heServerExec); //tell Miranda to process the request
+
+ int done = FALSE;
+ while (!done)
+ {
+ switch (WaitForMultipleObjects(cEvents, events, FALSE, INFINITE)) //wait until server either finished processing or miranda was closed
+ {
+ case WAIT_OBJECT_0: //done event
+ {
+ done = TRUE;
+
+ break; //nothing to do
+ }
+
+ case WAIT_OBJECT_0 + 1: //close event
+ default:
+ {
+ strcpy(sdCmdLine->reply.message, Translate("Miranda has been closed or an error has occured while waiting for the result, could not process request."));
+ done = TRUE;
+
+ break;
+ }
+
+ case WAIT_OBJECT_0 + 2: //buffer full event
+ {
+ lpprintf("%s", reply->message);
+
+ break;
+ }
+ }
+ }
+
+ reply->code = sdCmdLine->reply.code;
+ STRNCPY(reply->message, sdCmdLine->reply.message, REPLY_SIZE);
+
+ ReleaseMutex(hmClient); //let other possible clients talk to the server
+ }
+ else{
+ int err = GetLastError();
+ reply->code = -1;
+ *reply->message = 0;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/commands.h b/plugins/CmdLine/executable/MimCmd/commands.h
new file mode 100644
index 0000000000..04cc640f48
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/commands.h
@@ -0,0 +1,44 @@
+/*
+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_COMMANDS_H
+#define M_MIMCMD_COMMANDS_H
+
+#include "common.h"
+
+extern PCommand knownCommands;
+extern int cKnownCommands;
+
+typedef void (* LISTCOMMANDS)(PCommand *commands, int *count);
+
+extern LISTCOMMANDS ListCommands;
+
+char *GetMirandaFolder();
+
+int ConnectToMiranda();
+int DisconnectFromMiranda();
+int GetKnownCommands();
+int DestroyKnownCommands();
+
+PCommand GetCommand(char *command);
+PReply ParseCommand(char *argv[], int argc);
+void ProcessConsoleCommand(PCommand command, char *arguments[], int count, PReply reply);
+
+#endif \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/common.h b/plugins/CmdLine/executable/MimCmd/common.h
new file mode 100644
index 0000000000..8361cc24d4
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/common.h
@@ -0,0 +1,30 @@
+/*
+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 <stdio.h>
+#include <windows.h>
+#include <string.h>
+
+#define NO_MIMCMD_COMMANDS
+
+#include "../../cmdline/mimcmd_data.h"
+#include "../../cmdline/mimcmd_ipc.h"
+#include "commands.h"
+#include "langpack.h" \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/langpack.cpp b/plugins/CmdLine/executable/MimCmd/langpack.cpp
new file mode 100644
index 0000000000..096431f95b
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/langpack.cpp
@@ -0,0 +1,377 @@
+/*
+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.
+*/
+
+//this code is mostly taken from Miranda's langpack module.
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2007 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "langpack.h"
+
+static __inline int mir_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;
+}
+
+int lpprintf(const char *format, ...)
+{
+ va_list va;
+ va_start(va, format);
+ const int MAX_SIZE = 16192;
+ char buffer[MAX_SIZE] = {0};
+ int len = _vsnprintf(buffer, MAX_SIZE - 1, format, va);
+ buffer[MAX_SIZE - 1] = 0;
+ va_end(va);
+ CharToOemBuff(buffer, buffer, len);
+ printf("%s", buffer);
+
+ return len;
+}
+
+static void TrimString(char *str)
+{
+ int len,start;
+ len=lstrlenA(str);
+ while(str[0] && (unsigned char)str[len-1]<=' ') str[--len]=0;
+ for(start=0;str[start] && (unsigned char)str[start]<=' ';start++);
+ MoveMemory(str,str+start,len-start+1);
+}
+
+static void TrimStringSimple(char *str)
+{
+ if (str[lstrlenA(str)-1] == '\n') str[lstrlenA(str)-1] = '\0';
+ if (str[lstrlenA(str)-1] == '\r') str[lstrlenA(str)-1] = '\0';
+}
+
+static int IsEmpty(char *str)
+{
+ int i = 0;
+
+ while (str[i])
+ {
+ if (str[i]!=' '&&str[i]!='\r'&&str[i]!='\n')
+ return 0;
+ i++;
+ }
+ return 1;
+}
+
+static void ConvertBackslashes(char *str)
+{
+ char *pstr;
+
+ for(pstr=str;*pstr;pstr=CharNextA(pstr)) {
+ if(*pstr=='\\') {
+ switch(pstr[1]) {
+case 'n': *pstr='\n'; break;
+case 't': *pstr='\t'; break;
+case 'r': *pstr='\r'; break;
+default: *pstr=pstr[1]; break;
+ }
+ MoveMemory(pstr+1,pstr+2,lstrlenA(pstr+2)+1);
+ }
+ }
+}
+
+static DWORD LangPackHash(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__
+ __asm { //this is mediocrely optimised, but I'm sure it's good enough
+ xor edx,edx
+ mov esi,szStr
+ xor cl,cl
+lph_top:
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ inc esi
+ test al,al
+ jz lph_end
+ rol eax,cl
+ add cl,5
+ xor edx,eax
+ jmp lph_top
+lph_end:
+ mov eax,edx
+ }
+#else
+ DWORD hash=0;
+ int i;
+ int shift=0;
+ for(i=0;szStr[i];i++) {
+ hash^=szStr[i]<<shift;
+ if(shift>24) hash^=(szStr[i]>>(32-shift))&0x7F;
+ shift=(shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+static DWORD LangPackHashW(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined __GNUC__
+ __asm { //this is mediocrely optimised, but I'm sure it's good enough
+ xor edx,edx
+ mov esi,szStr
+ xor cl,cl
+lph_top:
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ inc esi
+ inc esi
+ test al,al
+ jz lph_end
+ rol eax,cl
+ add cl,5
+ xor edx,eax
+ jmp lph_top
+lph_end:
+ mov eax,edx
+ }
+#else
+ DWORD hash=0;
+ int i;
+ int shift=0;
+ for(i=0;szStr[i];i+=2) {
+ hash^=szStr[i]<<shift;
+ if(shift>24) hash^=(szStr[i]>>(32-shift))&0x7F;
+ shift=(shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+static int SortLangPackHashesProc(struct LangPackEntry *arg1,struct LangPackEntry *arg2)
+{
+ if(arg1->englishHash<arg2->englishHash) return -1;
+ if(arg1->englishHash>arg2->englishHash) return 1;
+ /* both source strings of the same hash (may not be the same string thou) put
+ the one that was written first to be found first */
+ if(arg1->linePos<arg2->linePos) return -1;
+ if(arg1->linePos>arg2->linePos) return 1;
+ return 0;
+}
+
+
+static int SortLangPackHashesProc2(struct LangPackEntry *arg1,struct LangPackEntry *arg2)
+{
+ if(arg1->englishHash<arg2->englishHash) return -1;
+ if(arg1->englishHash>arg2->englishHash) return 1;
+ return 0;
+}
+
+static int LoadLangPack(const TCHAR *szLangPack)
+{
+ FILE *fp;
+ char line[4096];
+ char *pszColon;
+ char *pszLine;
+ int entriesAlloced;
+ int startOfLine=0;
+ unsigned int linePos=1;
+ USHORT langID;
+
+ lstrcpy(langPack.filename,szLangPack);
+ fp = _tfopen(szLangPack,_T("rt"));
+ if(fp==NULL) return 1;
+ fgets(line,SIZEOF(line),fp);
+ TrimString(line);
+ if(lstrcmpA(line,"Miranda Language Pack Version 1")) {fclose(fp); return 2;}
+ //headers
+ while(!feof(fp)) {
+ startOfLine=ftell(fp);
+ if(fgets(line,SIZEOF(line),fp)==NULL) break;
+ TrimString(line);
+ if(IsEmpty(line) || line[0]==';' || line[0]==0) continue;
+ if(line[0]=='[') break;
+ pszColon=strchr(line,':');
+ if(pszColon==NULL) {fclose(fp); return 3;}
+ *pszColon=0;
+ if(!lstrcmpA(line,"Language")) {mir_snprintf(langPack.language,sizeof(langPack.language),"%s",pszColon+1); TrimString(langPack.language);}
+ else if(!lstrcmpA(line,"Last-Modified-Using")) {mir_snprintf(langPack.lastModifiedUsing,sizeof(langPack.lastModifiedUsing),"%s",pszColon+1); TrimString(langPack.lastModifiedUsing);}
+ else if(!lstrcmpA(line,"Authors")) {mir_snprintf(langPack.authors,sizeof(langPack.authors),"%s",pszColon+1); TrimString(langPack.authors);}
+ else if(!lstrcmpA(line,"Author-email")) {mir_snprintf(langPack.authorEmail,sizeof(langPack.authorEmail),"%s",pszColon+1); TrimString(langPack.authorEmail);}
+ else if(!lstrcmpA(line, "Locale")) {
+ char szBuf[20], *stopped;
+
+ TrimString(pszColon + 1);
+ langID = (USHORT)strtol(pszColon + 1, &stopped, 16);
+ langPack.localeID = MAKELCID(langID, 0);
+ GetLocaleInfoA(langPack.localeID, LOCALE_IDEFAULTANSICODEPAGE, szBuf, 10);
+ szBuf[5] = 0; // codepages have max. 5 digits
+ langPack.defaultANSICp = atoi(szBuf);
+ }
+ }
+ //body
+ fseek(fp,startOfLine,SEEK_SET);
+ entriesAlloced=0;
+ while(!feof(fp)) {
+ if(fgets(line,SIZEOF(line),fp)==NULL) break;
+ if(IsEmpty(line) || line[0]==';' || line[0]==0) continue;
+ TrimStringSimple(line);
+ ConvertBackslashes(line);
+ if(line[0]=='[' && line[lstrlenA(line)-1]==']') {
+ if(langPack.entryCount && langPack.entry[langPack.entryCount-1].local==NULL) {
+ if(langPack.entry[langPack.entryCount-1].english!=NULL) free(langPack.entry[langPack.entryCount-1].english);
+ langPack.entryCount--;
+ }
+ pszLine = line+1;
+ line[lstrlenA(line)-1]='\0';
+ //TrimStringSimple(line);
+ if(++langPack.entryCount>entriesAlloced) {
+ entriesAlloced+=128;
+ langPack.entry=(struct LangPackEntry*)realloc(langPack.entry,sizeof(struct LangPackEntry)*entriesAlloced);
+ }
+ langPack.entry[langPack.entryCount-1].english=NULL;
+ langPack.entry[langPack.entryCount-1].englishHash=LangPackHash(pszLine);
+ langPack.entry[langPack.entryCount-1].local=NULL;
+ langPack.entry[langPack.entryCount-1].wlocal = NULL;
+ langPack.entry[langPack.entryCount-1].linePos=linePos++;
+ }
+ else if(langPack.entryCount) {
+ struct LangPackEntry* E = &langPack.entry[langPack.entryCount-1];
+
+ if(E->local==NULL) {
+ E->local=_strdup(line);
+ {
+ size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0);
+ E->wlocal = (wchar_t *)malloc((int) ((iNeeded+1) * sizeof(wchar_t)));
+ MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, E->wlocal, (int) iNeeded);
+ }
+ }
+ else {
+ E->local=(char*)realloc(E->local,lstrlenA(E->local)+lstrlenA(line)+2);
+ lstrcatA(E->local,"\n");
+ lstrcatA(E->local,line);
+ {
+ size_t iNeeded = MultiByteToWideChar(langPack.defaultANSICp, 0, line, -1, 0, 0);
+ size_t iOldLen = wcslen(E->wlocal);
+ E->wlocal = (wchar_t*)realloc(E->wlocal, ( sizeof(wchar_t) * ( iOldLen + iNeeded + 2)));
+ wcscat(E->wlocal, L"\n");
+ MultiByteToWideChar( langPack.defaultANSICp, 0, line, -1, E->wlocal + iOldLen+1, (int) iNeeded);
+ }
+ }
+ }
+ }
+ qsort(langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc);
+ fclose(fp);
+ return 0;
+}
+
+char *LangPackTranslateString(const char *szEnglish, const int W)
+{
+ struct LangPackEntry key,*entry;
+
+ if ( langPack.entryCount == 0 || szEnglish == NULL ) return (char*)szEnglish;
+
+
+ key.englishHash = W ? LangPackHashW(szEnglish) : LangPackHash(szEnglish);
+ entry=(struct LangPackEntry*)bsearch(&key,langPack.entry,langPack.entryCount,sizeof(struct LangPackEntry),(int(*)(const void*,const void*))SortLangPackHashesProc2);
+ if(entry==NULL) return (char*)szEnglish;
+ while(entry>langPack.entry)
+ {
+ entry--;
+ if(entry->englishHash!=key.englishHash) {
+ entry++;
+ return W ? (char *)entry->wlocal : entry->local;
+ }
+ }
+ return W ? (char *)entry->wlocal : entry->local;
+}
+
+int LangPackGetDefaultCodePage()
+{
+ return (langPack.defaultANSICp == 0) ? CP_ACP : langPack.defaultANSICp;
+}
+
+int LangPackGetDefaultLocale()
+{
+ return (langPack.localeID == 0) ? LOCALE_USER_DEFAULT : langPack.localeID;
+}
+
+int LangPackShutdown()
+{
+ int i;
+ for(i=0;i<langPack.entryCount;i++) {
+ if(langPack.entry[i].english!=NULL) free(langPack.entry[i].english);
+ if(langPack.entry[i].local!=NULL) { free(langPack.entry[i].local); }
+ if(langPack.entry[i].wlocal!=NULL) { free(langPack.entry[i].wlocal); }
+ }
+ if(langPack.entryCount) {
+ free(langPack.entry);
+ langPack.entry=0;
+ langPack.entryCount=0;
+ }
+
+ return 0;
+}
+
+int LoadLangPackModule(char *mirandaPath)
+{
+ HANDLE hFind;
+ TCHAR szSearch[MAX_PATH],*str2,szLangPack[MAX_PATH];
+ WIN32_FIND_DATA fd;
+
+ ZeroMemory(&langPack,sizeof(langPack));
+
+ strncpy(szSearch, mirandaPath, SIZEOF(szSearch));
+ szSearch[SIZEOF(szSearch) - 1] = 0;
+ strcat(szSearch, "\\");
+
+ str2=_tcsrchr(szSearch,'\\');
+ if(str2!=NULL) *str2=0;
+ else str2=szSearch;
+ lstrcat( szSearch, _T("\\langpack_*.txt"));
+ hFind = FindFirstFile( szSearch, &fd );
+ if( hFind != INVALID_HANDLE_VALUE ) {
+ lstrcpy(str2+1,fd.cFileName);
+ lstrcpy(szLangPack,szSearch);
+ FindClose(hFind);
+ LoadLangPack(szLangPack);
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/langpack.h b/plugins/CmdLine/executable/MimCmd/langpack.h
new file mode 100644
index 0000000000..15d6b301b5
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/langpack.h
@@ -0,0 +1,92 @@
+/*
+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.
+*/
+
+//this code is mostly taken from Miranda's langpack module.
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2007 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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_LANGPACK_H
+#define M_MIMCMD_LANGPACK_H
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <tchar.h>
+#include <locale.h>
+
+
+#define SIZEOF(X) (sizeof(X)/sizeof(X[0]))
+
+struct LangPackEntry {
+ unsigned linePos;
+ DWORD englishHash;
+ char *english; //not currently used, the hash does everything
+ char *local;
+ wchar_t *wlocal;
+};
+
+struct LangPackStruct {
+ TCHAR filename[MAX_PATH];
+ char language[64];
+ char lastModifiedUsing[64];
+ char authors[256];
+ char authorEmail[128];
+ struct LangPackEntry *entry;
+ int entryCount;
+ LCID localeID;
+ DWORD defaultANSICp;
+} static langPack = {0};
+
+#ifdef Translate
+#undef Translate
+#define Translate(s) LangPackTranslateString(s, 0)
+#endif
+
+char *LangPackTranslateString(const char *szEnglish, const int W);
+int LangPackGetDefaultCodePage();
+int LangPackGetDefaultLocale();
+
+int LangPackShutdown();
+int LoadLangPackModule(char *mirandaPath);
+
+int lpprintf(const char *format, ...);
+
+#endif \ No newline at end of file
diff --git a/plugins/CmdLine/executable/MimCmd/resource.h b/plugins/CmdLine/executable/MimCmd/resource.h
new file mode 100644
index 0000000000..c3bc570152
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by version.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/executable/MimCmd/version.rc b/plugins/CmdLine/executable/MimCmd/version.rc
new file mode 100644
index 0000000000..67a109eebf
--- /dev/null
+++ b/plugins/CmdLine/executable/MimCmd/version.rc
@@ -0,0 +1,100 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+#include "..\..\CmdLine\version.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __PLUGINVERSION_STRING
+ PRODUCTVERSION __PLUGINVERSION_STRING
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "FileVersion", __VERSION_STRING
+ VALUE "InternalName", __PLUGIN_DISPLAY_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/CmdLine/files_release.txt b/plugins/CmdLine/files_release.txt
new file mode 100644
index 0000000000..173a6a177d
--- /dev/null
+++ b/plugins/CmdLine/files_release.txt
@@ -0,0 +1 @@
+executable\MimCmd\win32\Release\*.exe
diff --git a/plugins/CmdLine/files_releasex64.txt b/plugins/CmdLine/files_releasex64.txt
new file mode 100644
index 0000000000..19ce16953c
--- /dev/null
+++ b/plugins/CmdLine/files_releasex64.txt
@@ -0,0 +1 @@
+executable\MimCmd\x64\Release\*.exe
diff --git a/plugins/CmdLine/files_source.txt b/plugins/CmdLine/files_source.txt
new file mode 100644
index 0000000000..cfc893cd2a
--- /dev/null
+++ b/plugins/CmdLine/files_source.txt
@@ -0,0 +1,5 @@
+CmdLine\*.*
+executable\*.*
+executable\MimCmd\*.*
+docs\*.*
+*.*
diff --git a/plugins/CmdLine/pack source.bat b/plugins/CmdLine/pack source.bat
new file mode 100644
index 0000000000..555522e5e6
--- /dev/null
+++ b/plugins/CmdLine/pack source.bat
@@ -0,0 +1,8 @@
+for /F "tokens=4-8* delims=. " %%i in (docs\CmdLine_readme.txt) do (call :Pack %%i %%j %%k %%l; exit)
+
+:Pack
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -c2 "CmdLine src %1.%2.%3.%4.zip" @files_source.txt -x*.zip -x*.ncb -x*.user
+exit
+
+error:
+echo "Error packing Bonsai"
diff --git a/plugins/CmdLine/pack symbols.bat b/plugins/CmdLine/pack symbols.bat
new file mode 100644
index 0000000000..c765d34756
--- /dev/null
+++ b/plugins/CmdLine/pack symbols.bat
@@ -0,0 +1,12 @@
+@echo off
+if NOT EXIST "symbols\%1 - %3" (
+ mkdir "symbols\%1 - %3"
+)
+xcopy "%1\win32\Release\*.pdb" "symbols\%1 - %3\win32\*" /EXCLUDE:symbols_exclude.txt /Y
+xcopy "%2\win32\Release\*.pdb" "symbols\%1 - %3\win32\*" /EXCLUDE:symbols_exclude.txt /Y
+
+xcopy "%1\x64\Release\*.pdb" "symbols\%1 - %3\x64\*" /EXCLUDE:symbols_exclude.txt /Y
+xcopy "%2\x64\Release\*.pdb" "symbols\%1 - %3\x64\*" /EXCLUDE:symbols_exclude.txt /Y
+
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -r -c2 "symbols - %1.zip" "symbols\*.*"
+rmdir "symbols\" /Q /S \ No newline at end of file
diff --git a/plugins/CmdLine/pack x64.bat b/plugins/CmdLine/pack x64.bat
new file mode 100644
index 0000000000..e6a5812727
--- /dev/null
+++ b/plugins/CmdLine/pack x64.bat
@@ -0,0 +1,18 @@
+if NOT EXIST "plugins" (
+ mkdir "plugins"
+)
+
+xcopy "CmdLine\x64\Release\*.dll" "plugins\*"
+
+for /F "tokens=4-8* delims=. " %%i in (docs\CmdLine_readme.txt) do (call :Pack %%i %%j %%k %%l; exit)
+
+:Pack
+d:\usr\PowerArchiver\pacl\pacomp.exe -a -c2 "CmdLine %1.%2.%3.%4 x64.zip" @files_releasex64.txt
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -c2 "CmdLine %1.%2.%3.%4 x64.zip" docs\*.* *.caca
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -c2 "CmdLine %1.%2.%3.%4 x64.zip" plugins\*.* *.caca
+rmdir "plugins\" /Q /S
+call "pack symbols.bat" CmdLine executable\MimCmd %1.%2.%3.%4
+exit
+
+error:
+echo "Error packing CmdLine"
diff --git a/plugins/CmdLine/pack.bat b/plugins/CmdLine/pack.bat
new file mode 100644
index 0000000000..38411bd994
--- /dev/null
+++ b/plugins/CmdLine/pack.bat
@@ -0,0 +1,18 @@
+if NOT EXIST "plugins" (
+ mkdir "plugins"
+)
+
+xcopy "CmdLine\win32\Release\*.dll" "plugins\*"
+
+for /F "tokens=4-8* delims=. " %%i in (docs\CmdLine_readme.txt) do (call :Pack %%i %%j %%k %%l; exit)
+
+:Pack
+d:\usr\PowerArchiver\pacl\pacomp.exe -a -c2 "CmdLine %1.%2.%3.%4 x32.zip" @files_release.txt
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -c2 "CmdLine %1.%2.%3.%4 x32.zip" docs\*.* *.caca
+d:\usr\PowerArchiver\pacl\pacomp.exe -p -a -c2 "CmdLine %1.%2.%3.%4 x32.zip" plugins\*.* *.caca
+rmdir "plugins\" /Q /S
+call "pack symbols.bat" CmdLine executable\MimCmd %1.%2.%3.%4
+exit
+
+error:
+echo "Error packing CmdLine"
diff --git a/plugins/CmdLine/symbols_exclude.txt b/plugins/CmdLine/symbols_exclude.txt
new file mode 100644
index 0000000000..361cf2448b
--- /dev/null
+++ b/plugins/CmdLine/symbols_exclude.txt
@@ -0,0 +1 @@
+vc80.pdb \ No newline at end of file