summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2014-04-15 08:46:04 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2014-04-15 08:46:04 +0000
commitc015ec458520935c407aa1b2ce1d004c5c5c8a61 (patch)
tree9c77a0b9d3368731d08468105f52dcb2726c6d3f /protocols
parentbd7e07aa0bfb4fecdd09d0a48eabcb6899dd0601 (diff)
ICQCorp adopted - needs Unicode fixes
git-svn-id: http://svn.miranda-ng.org/main/trunk@8980 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols')
-rw-r--r--protocols/ICQCorp/ICQCorp_10.vcxproj219
-rw-r--r--protocols/ICQCorp/ICQCorp_10.vcxproj.filters97
-rw-r--r--protocols/ICQCorp/ICQCorp_12.vcxproj221
-rw-r--r--protocols/ICQCorp/ICQCorp_12.vcxproj.filters97
-rw-r--r--protocols/ICQCorp/res/corp.icobin0 -> 318 bytes
-rw-r--r--protocols/ICQCorp/res/resource.rc147
-rw-r--r--protocols/ICQCorp/res/version.rc38
-rw-r--r--protocols/ICQCorp/src/corp.cpp118
-rw-r--r--protocols/ICQCorp/src/corp.h71
-rw-r--r--protocols/ICQCorp/src/event.cpp111
-rw-r--r--protocols/ICQCorp/src/event.h52
-rw-r--r--protocols/ICQCorp/src/options.cpp90
-rw-r--r--protocols/ICQCorp/src/options.h29
-rw-r--r--protocols/ICQCorp/src/packet.cpp217
-rw-r--r--protocols/ICQCorp/src/packet.h62
-rw-r--r--protocols/ICQCorp/src/protocol.cpp2339
-rw-r--r--protocols/ICQCorp/src/protocol.h223
-rw-r--r--protocols/ICQCorp/src/resource.h46
-rw-r--r--protocols/ICQCorp/src/services.cpp589
-rw-r--r--protocols/ICQCorp/src/socket.cpp399
-rw-r--r--protocols/ICQCorp/src/socket.h85
-rw-r--r--protocols/ICQCorp/src/stdafx.cpp18
-rw-r--r--protocols/ICQCorp/src/transfer.cpp505
-rw-r--r--protocols/ICQCorp/src/transfer.h75
-rw-r--r--protocols/ICQCorp/src/user.cpp160
-rw-r--r--protocols/ICQCorp/src/user.h52
-rw-r--r--protocols/ICQCorp/src/version.h14
27 files changed, 6074 insertions, 0 deletions
diff --git a/protocols/ICQCorp/ICQCorp_10.vcxproj b/protocols/ICQCorp/ICQCorp_10.vcxproj
new file mode 100644
index 0000000000..ecc9ef71cb
--- /dev/null
+++ b/protocols/ICQCorp/ICQCorp_10.vcxproj
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AD0D0500-CE7D-417D-9C36-3620D56CA6D4}</ProjectGuid>
+ <ProjectName>ICQCorp</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>11.0.60610.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalOptions>/PDBALTPATH:%_PDB% %(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <AdditionalOptions>/PDBALTPATH:%_PDB% %(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\corp.h" />
+ <ClInclude Include="src\event.h" />
+ <ClInclude Include="src\options.h" />
+ <ClInclude Include="src\packet.h" />
+ <ClInclude Include="src\protocol.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\socket.h" />
+ <ClInclude Include="src\transfer.h" />
+ <ClInclude Include="src\user.h" />
+ <ClInclude Include="src\version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ <ResourceCompile Include="res\version.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="res\corp.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\corp.cpp" />
+ <ClCompile Include="src\event.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\packet.cpp" />
+ <ClCompile Include="src\protocol.cpp" />
+ <ClCompile Include="src\services.cpp" />
+ <ClCompile Include="src\socket.cpp" />
+ <ClCompile Include="src\stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\transfer.cpp" />
+ <ClCompile Include="src\user.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/ICQCorp/ICQCorp_10.vcxproj.filters b/protocols/ICQCorp/ICQCorp_10.vcxproj.filters
new file mode 100644
index 0000000000..a0f5be6393
--- /dev/null
+++ b/protocols/ICQCorp/ICQCorp_10.vcxproj.filters
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{69c79660-1836-402a-9ec2-3b75f4396bc2}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{c2873240-bfbb-49ad-b400-228addec6702}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{41cb7826-be3c-4d3a-9f8d-1ba6b379207b}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;r</Extensions>
+ </Filter>
+ <Filter Include="Resource Files\Icons">
+ <UniqueIdentifier>{3e399225-12c1-4207-95d1-b5adc3407673}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\corp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\event.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\packet.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\protocol.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\socket.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\transfer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\user.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="res\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="res\corp.ico">
+ <Filter>Resource Files\Icons</Filter>
+ </Image>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\corp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\event.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\packet.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\protocol.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\services.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\socket.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\transfer.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\user.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/ICQCorp/ICQCorp_12.vcxproj b/protocols/ICQCorp/ICQCorp_12.vcxproj
new file mode 100644
index 0000000000..ce09d216c3
--- /dev/null
+++ b/protocols/ICQCorp/ICQCorp_12.vcxproj
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AD0D0500-CE7D-417D-9C36-3620D56CA6D4}</ProjectGuid>
+ <ProjectName>ICQCorp</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>11.0.60610.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MinimalRebuild>false</MinimalRebuild>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeaderFile>corp.h</PrecompiledHeaderFile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin12\lib</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\..\include;..\..\include\msapi</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="src\corp.h" />
+ <ClInclude Include="src\event.h" />
+ <ClInclude Include="src\options.h" />
+ <ClInclude Include="src\packet.h" />
+ <ClInclude Include="src\protocol.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\socket.h" />
+ <ClInclude Include="src\transfer.h" />
+ <ClInclude Include="src\user.h" />
+ <ClInclude Include="src\version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc" />
+ <ResourceCompile Include="res\version.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="res\corp.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\corp.cpp" />
+ <ClCompile Include="src\event.cpp" />
+ <ClCompile Include="src\options.cpp" />
+ <ClCompile Include="src\packet.cpp" />
+ <ClCompile Include="src\protocol.cpp" />
+ <ClCompile Include="src\services.cpp" />
+ <ClCompile Include="src\socket.cpp" />
+ <ClCompile Include="src\stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\transfer.cpp" />
+ <ClCompile Include="src\user.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/ICQCorp/ICQCorp_12.vcxproj.filters b/protocols/ICQCorp/ICQCorp_12.vcxproj.filters
new file mode 100644
index 0000000000..a0f5be6393
--- /dev/null
+++ b/protocols/ICQCorp/ICQCorp_12.vcxproj.filters
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{69c79660-1836-402a-9ec2-3b75f4396bc2}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{c2873240-bfbb-49ad-b400-228addec6702}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{41cb7826-be3c-4d3a-9f8d-1ba6b379207b}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;r</Extensions>
+ </Filter>
+ <Filter Include="Resource Files\Icons">
+ <UniqueIdentifier>{3e399225-12c1-4207-95d1-b5adc3407673}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\corp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\event.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\packet.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\protocol.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\socket.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\transfer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\user.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="res\resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="res\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="res\corp.ico">
+ <Filter>Resource Files\Icons</Filter>
+ </Image>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\corp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\event.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\packet.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\protocol.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\services.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\socket.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\transfer.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\user.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/protocols/ICQCorp/res/corp.ico b/protocols/ICQCorp/res/corp.ico
new file mode 100644
index 0000000000..5421e31fdf
--- /dev/null
+++ b/protocols/ICQCorp/res/corp.ico
Binary files differ
diff --git a/protocols/ICQCorp/res/resource.rc b/protocols/ICQCorp/res/resource.rc
new file mode 100644
index 0000000000..f68b019090
--- /dev/null
+++ b/protocols/ICQCorp/res/resource.rc
@@ -0,0 +1,147 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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.
+*/
+
+// Microsoft Visual C++ generated resource script.
+//
+#include "..\src\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian (Russia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Icon's
+//
+///////////////////////////////////////////////////////////////////////////////
+
+IDI_ICQCORP ICON "corp.ico"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Dialog's
+//
+///////////////////////////////////////////////////////////////////////////////
+
+IDD_INFO_ICQCORP DIALOGEX 0, 0, 222, 132
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "UIN:",IDC_STATIC,5,5,56,8
+ EDITTEXT IDC_INFO_UIN,61,5,156,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "External IP:",IDC_STATIC,5,18,56,8
+ EDITTEXT IDC_INFO_IP,61,18,83,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Internal IP:",IDC_STATIC,5,31,56,8
+ EDITTEXT IDC_INFO_REALIP,61,31,156,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Port:",IDC_STATIC,5,44,56,8
+ EDITTEXT IDC_INFO_PORT,61,44,156,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "ICQ Version:",IDC_STATIC,5,57,56,8
+ EDITTEXT IDC_INFO_VERSION,61,57,156,8,ES_AUTOHSCROLL |
+ ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Miranda Version:",IDC_STATIC,5,70,56,8
+ EDITTEXT IDC_INFO_MIRVER,61,70,156,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+ LTEXT "Ping:",IDC_STATIC,147,18,34,8
+ EDITTEXT IDC_INFO_PING,182,18,35,8,ES_AUTOHSCROLL | ES_READONLY |
+ NOT WS_BORDER | NOT WS_TABSTOP
+END
+
+///////////////////////////////////////////////////////////////////////////////
+
+IDD_OPT_ICQCORP DIALOGEX 0, 0, 261, 160
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "ICQ Corp",IDC_STATIC,4,4,253,147
+ RTEXT "Login Server:",IDC_STATIC,12,34,44,8
+ EDITTEXT IDC_OPT_SERVER,64,32,100,12,ES_AUTOHSCROLL
+ RTEXT "Port:",IDC_STATIC,173,34,21,11
+ EDITTEXT IDC_OPT_PORT,204,32,40,12,ES_AUTOHSCROLL
+ RTEXT "ICQ#:",IDC_STATIC,15,65,42,8
+ EDITTEXT IDC_OPT_UIN,64,63,100,12,ES_AUTOHSCROLL | ES_NUMBER
+ RTEXT "Password:",IDC_STATIC,15,79,42,8
+ EDITTEXT IDC_OPT_PASSWORD,64,78,100,12,ES_PASSWORD |
+ ES_AUTOHSCROLL
+ LTEXT "You will need to reconnect to the ICQ network for the changes you have made on this page to take effect.",
+ IDC_OPT_RECONNECT,14,119,237,16,NOT WS_VISIBLE
+END
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\\src\\resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+#endif // Russian (Russia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/protocols/ICQCorp/res/version.rc b/protocols/ICQCorp/res/version.rc
new file mode 100644
index 0000000000..5bfbab4754
--- /dev/null
+++ b/protocols/ICQCorp/res/version.rc
@@ -0,0 +1,38 @@
+// Microsoft Visual C++ generated resource script.
+//
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+#include "afxres.h"
+#include "..\src\version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION __FILEVERSION_STRING
+ PRODUCTVERSION __FILEVERSION_STRING
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x0L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "FileDescription", __DESCRIPTION
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ VALUE "ProductName", __PLUGIN_NAME
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/protocols/ICQCorp/src/corp.cpp b/protocols/ICQCorp/src/corp.cpp
new file mode 100644
index 0000000000..ef8bff0dd8
--- /dev/null
+++ b/protocols/ICQCorp/src/corp.cpp
@@ -0,0 +1,118 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+HINSTANCE hInstance;
+char protoName[64];
+int hLangpack;
+
+PLUGININFOEX pluginInfo =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved)
+{
+ hInstance = hModule;
+ if (reason == DLL_PROCESS_ATTACH) DisableThreadLibraryCalls(hModule);
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" __declspec(dllexport) int Unload()
+{
+ UnloadServices();
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" __declspec(dllexport) int Load()
+{
+ mir_getLP(&pluginInfo);
+
+ PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE };
+ pd.szName = protoName;
+ pd.type = PROTOTYPE_PROTOCOL;
+
+ char fileName[MAX_PATH];
+ WIN32_FIND_DATA findData;
+
+ GetModuleFileName(hInstance, fileName, MAX_PATH);
+ FindClose(FindFirstFile(fileName, &findData));
+ findData.cFileName[strlen(findData.cFileName) - 4] = 0;
+ strcpy(protoName, findData.cFileName);
+
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ LoadServices();
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD Version)
+{
+ return &pluginInfo;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef _DEBUG
+void T(char *format, ...)
+{
+ char buffer[8196], bufferTime[64];
+ va_list list;
+ SYSTEMTIME t;
+
+ va_start(list, format);
+ vsprintf(buffer, format, list);
+ va_end(list);
+
+ GetLocalTime(&t);
+ sprintf(bufferTime, "%.2d:%.2d:%.2d.%.3d ", t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
+
+ static HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD result;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ hFile = CreateFile("ICQ Corp.log", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
+ SetFilePointer(hFile, 0, 0, FILE_END);
+ }
+ WriteFile(hFile, bufferTime, (DWORD)strlen(bufferTime), &result, NULL);
+ WriteFile(hFile, buffer, (DWORD)strlen(buffer), &result, NULL);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/corp.h b/protocols/ICQCorp/src/corp.h
new file mode 100644
index 0000000000..444f40382b
--- /dev/null
+++ b/protocols/ICQCorp/src/corp.h
@@ -0,0 +1,71 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 corp_h
+#define corp_h
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <string.h>
+#include <process.h>
+#include <vector>
+#include <time.h>
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <statusmodes.h>
+#include <m_clist.h>
+#include <m_userinfo.h>
+
+#include "user.h"
+#include "transfer.h"
+#include "packet.h"
+#include "socket.h"
+#include "event.h"
+#include "protocol.h"
+#include "options.h"
+#include "resource.h"
+#include "version.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern HINSTANCE hInstance;
+extern char protoName[64];
+
+extern int LoadServices();
+extern int UnloadServices();
+
+#ifdef _DEBUG
+extern void T(char *format, ...);
+#else
+inline void T(char *format, ...) {};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif \ No newline at end of file
diff --git a/protocols/ICQCorp/src/event.cpp b/protocols/ICQCorp/src/event.cpp
new file mode 100644
index 0000000000..69f2ac85db
--- /dev/null
+++ b/protocols/ICQCorp/src/event.cpp
@@ -0,0 +1,111 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+std::vector <ICQEvent *> icqEvents;
+
+///////////////////////////////////////////////////////////////////////////////
+
+void WINAPI eventTimerProc(HWND hWnd, UINT Msg, UINT_PTR hTimer, DWORD Time)
+{
+ unsigned int i;
+
+ KillTimer(NULL, hTimer);
+ for (i=0; i<icqEvents.size(); i++) if (hTimer == icqEvents[i]->hTimer) icqEvents[i]->noAck();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *getEvent(SOCKET hSocket, unsigned int sequence)
+{
+ unsigned int i;
+
+ for (i=0; i<icqEvents.size(); i++) if (icqEvents[i]->isEvent(hSocket, sequence)) return icqEvents[i];
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent::ICQEvent(unsigned short theCmd, unsigned short theSubCmd, unsigned int theSequence,
+ unsigned int theUin, Socket *theSocket, Packet *thePacket, int theReply)
+{
+ cmd = theCmd;
+ subCmd = theSubCmd;
+ sequence = theSequence;
+ uin = theUin;
+ socket = theSocket;
+ packet = new Packet(thePacket);
+ reply = theReply;
+
+ hTimer = NULL;
+ retries = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent::~ICQEvent()
+{
+ stop();
+ delete packet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQEvent::start()
+{
+ // send the packet
+ if (!socket->sendPacket(*packet)) return false;
+
+ if (cmd != ICQ_CMDxTCP_START) hTimer = SetTimer(NULL, 0, MAX_WAIT_ACK, (TIMERPROC)eventTimerProc);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQEvent::stop()
+{
+ if (hTimer)
+ {
+ KillTimer(NULL, hTimer);
+ hTimer = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQEvent::isEvent(SOCKET hSocket, unsigned long theSequence)
+{
+ return socket->handleVal == hSocket && sequence == theSequence;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQEvent::noAck()
+{
+ hTimer = NULL;
+ if (socket->connected() && retries < MAX_SERVER_RETRIES && cmd != ICQ_CMDxTCP_START)
+ {
+ retries++;
+ start();
+ }
+ else icq.doneEvent(false, socket->handleVal, sequence);
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/event.h b/protocols/ICQCorp/src/event.h
new file mode 100644
index 0000000000..ee204927e2
--- /dev/null
+++ b/protocols/ICQCorp/src/event.h
@@ -0,0 +1,52 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 event_h
+#define event_h
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ICQEvent
+{
+public:
+ ICQEvent(unsigned short theCmd, unsigned short theSubCmd, unsigned int theSequence, unsigned int theUin, Socket *theSocket, Packet *thePacket, int theReply);
+ ~ICQEvent();
+ bool start();
+ void stop();
+ bool isEvent(SOCKET hSocket, unsigned long theSequence);
+ void noAck();
+ unsigned short cmd, subCmd;
+ unsigned int uin, sequence;
+ int reply;
+ unsigned int hTimer;
+ Packet *packet;
+protected:
+ unsigned short retries;
+ Socket *socket;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern std::vector <ICQEvent *> icqEvents;
+
+extern ICQEvent *getEvent(SOCKET hSocket, unsigned int sequence);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/protocols/ICQCorp/src/options.cpp b/protocols/ICQCorp/src/options.cpp
new file mode 100644
index 0000000000..aab67117c7
--- /dev/null
+++ b/protocols/ICQCorp/src/options.cpp
@@ -0,0 +1,90 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK icqOptionsDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char str[128];
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hWnd);
+ SetDlgItemInt(hWnd, IDC_OPT_UIN, db_get_dw(NULL, protoName, "UIN", 0), FALSE);
+ if (!db_get(NULL, protoName, "Password", &dbv))
+ {
+ SetDlgItemText(hWnd, IDC_OPT_PASSWORD, dbv.pszVal);
+ db_free(&dbv);
+ }
+ if(!db_get(NULL, protoName, "Server", &dbv))
+ {
+ SetDlgItemText(hWnd, IDC_OPT_SERVER, dbv.pszVal);
+ db_free(&dbv);
+ }
+ SetDlgItemInt(hWnd, IDC_OPT_PORT, db_get_w(NULL, protoName, "Port", 4000), FALSE);
+ ShowWindow(GetDlgItem(hWnd, IDC_OPT_RECONNECT), SW_HIDE);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ db_set_dw(NULL, protoName, "UIN", (DWORD)GetDlgItemInt(hWnd, IDC_OPT_UIN, NULL, FALSE));
+ GetDlgItemText(hWnd, IDC_OPT_PASSWORD, str, sizeof(str));
+ db_set_s(NULL, protoName, "Password", str);
+ GetDlgItemText(hWnd, IDC_OPT_SERVER, str, sizeof(str));
+ db_set_s(NULL, protoName, "Server", str);
+ db_set_w(NULL, protoName, "Port", (WORD)GetDlgItemInt(hWnd, IDC_OPT_PORT, NULL, FALSE));
+ return TRUE;
+ }
+ break;
+
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_OPT_UIN || LOWORD(wParam) == IDC_OPT_PASSWORD || LOWORD(wParam) == IDC_OPT_SERVER || LOWORD(wParam) == IDC_OPT_PORT) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+ break;
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int icqOptionsInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ odp.cbSize = sizeof(odp);
+ odp.position = -800000000;
+ odp.pszTitle = Translate(protoName);
+ odp.pfnDlgProc = (DLGPROC)icqOptionsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_OPT_ICQCORP);
+ odp.hInstance = hInstance;
+ odp.pszGroup = Translate("Network");
+ odp.flags = ODPF_BOLDGROUPS;
+// odp.nIDBottomSimpleControl = IDC_STICQGROUP;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/options.h b/protocols/ICQCorp/src/options.h
new file mode 100644
index 0000000000..a0254cd3b9
--- /dev/null
+++ b/protocols/ICQCorp/src/options.h
@@ -0,0 +1,29 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 options_h
+#define options_h
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern int icqOptionsInitialise(WPARAM wParam, LPARAM lParam);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif \ No newline at end of file
diff --git a/protocols/ICQCorp/src/packet.cpp b/protocols/ICQCorp/src/packet.cpp
new file mode 100644
index 0000000000..0baebee9a7
--- /dev/null
+++ b/protocols/ICQCorp/src/packet.cpp
@@ -0,0 +1,217 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet::Packet()
+{
+ maxSize = MAX_PACKET_SIZE;
+ buff = new char[maxSize];
+ nextData = buff;
+ sizeVal = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet::Packet(Packet *packet)
+{
+ maxSize = packet->maxSize;
+ buff = new char[maxSize];
+ nextData = buff + (packet->nextData - packet->buff);
+ sizeVal = packet->sizeVal;
+ memcpy(buff, packet->buff, sizeVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+Packet::Packet(char *newBuff, unsigned long buffSize)
+{
+ maxSize = MAX_PACKET_SIZE;
+ if (buffSize > maxSize) buffSize = maxSize;
+ buff = new char[maxSize];
+ memcpy(buff, newBuff, buffSize);
+ nextData = buff;
+ sizeVal = buffSize;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+*/
+Packet::~Packet()
+{
+ delete [] buff;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Packet::clearPacket()
+{
+ nextData = buff;
+ sizeVal = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Packet::add(unsigned int s)
+{
+ nextData += s;
+ sizeVal += s;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator << (unsigned int data)
+{
+ *(unsigned int*)nextData = data;
+ sizeVal += sizeof(unsigned int);
+ nextData += sizeof(unsigned int);
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator << (unsigned short data)
+{
+ *(unsigned short*)nextData = data;
+ sizeVal += sizeof(unsigned short);
+ nextData += sizeof(unsigned short);
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator << (unsigned char data)
+{
+ *(unsigned char*)nextData = data;
+ sizeVal += sizeof(unsigned char);
+ nextData += sizeof(unsigned char);
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator << (char *data)
+{
+ unsigned int s = (unsigned int)strlen(data) + 1;
+ operator << ((unsigned short)s);
+ memcpy(nextData, data, s);
+ sizeVal += s;
+ nextData += s;
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator << (Packet *packet)
+{
+ unsigned int s = packet->dataSize();
+ memcpy(nextData, packet->nextData, s);
+ sizeVal += s;
+ nextData += s;
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator >> (unsigned int &in)
+{
+ if (nextData+sizeof(unsigned int) > buff+sizeVal) in = 0;
+ else
+ {
+ in = *(unsigned int*)nextData;
+ nextData += sizeof(unsigned int);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator >> (unsigned short &in)
+{
+ if (nextData+sizeof(unsigned short) > buff+sizeVal) in = 0;
+ else
+ {
+ in = *(unsigned short*)nextData;
+ nextData += sizeof(unsigned short);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator >> (unsigned char &in)
+{
+ if (nextData+sizeof(unsigned char) > buff+sizeVal) in = 0;
+ else
+ {
+ in = *(unsigned char*)nextData;
+ nextData += sizeof(unsigned char);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Packet &Packet::operator >> (char *&in)
+{
+ unsigned short s;
+
+ operator >> (s);
+ if (nextData+s > buff+sizeVal) in = 0;
+ else
+ {
+ if (in == NULL) in = new char[s];
+ memcpy(in, nextData, s);
+ nextData += s;
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+char *Packet::print()
+{
+ unsigned int i;
+ static char p[8196];
+ char *pPos = p;
+
+ for (i=0; i<sizeVal; i++)
+ {
+ if (i % 16 == 0)
+ {
+ sprintf(pPos, " 0x%04X: %65c\n\0", i, ' ');
+ pPos += 11;
+ }
+
+ sprintf(pPos, "%02X ", (unsigned char)buff[i]);
+ if ((unsigned char)buff[i] > ' ') pPos[48 - (i % 16)*2 + 1] = buff[i];
+
+ pPos += 3;
+ if ((i+1) % 16 == 0)
+ {
+ pPos[0] = ' ';
+ pPos += 18;
+ }
+ }
+ if (sizeVal % 16 != 0) pPos[0] = ' ';
+ return p;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/packet.h b/protocols/ICQCorp/src/packet.h
new file mode 100644
index 0000000000..7ed15f24a5
--- /dev/null
+++ b/protocols/ICQCorp/src/packet.h
@@ -0,0 +1,62 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 packet_h
+#define packet_h
+
+const int MAX_PACKET_SIZE = 8192;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Packet
+{
+public:
+ Packet();
+ Packet(Packet *packet);
+// Packet(char *newBuff, unsigned long buffSize);
+ ~Packet();
+ void clearPacket();
+ void reset() { nextData = buff; };
+ void add(unsigned int s);
+ char *data() { return nextData; };
+ unsigned int size() { return sizeVal; };
+ unsigned int dataSize() { return buff + sizeVal - nextData; };
+ Packet &operator << (unsigned int data);
+ Packet &operator << (unsigned short data);
+ Packet &operator << (unsigned char data);
+ Packet &operator << (char *data);
+ Packet &operator << (Packet *packet);
+ Packet &operator >> (unsigned int &in);
+ Packet &operator >> (unsigned short &in);
+ Packet &operator >> (unsigned char &in);
+ Packet &operator >> (char *&in);
+ char *print();
+protected:
+ char *buff;
+ char *nextData;
+ unsigned int maxSize;
+ unsigned int sizeVal;
+
+ friend class UDPSocket;
+ friend class TCPSocket;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/protocols/ICQCorp/src/protocol.cpp b/protocols/ICQCorp/src/protocol.cpp
new file mode 100644
index 0000000000..25967327d5
--- /dev/null
+++ b/protocols/ICQCorp/src/protocol.cpp
@@ -0,0 +1,2339 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+ICQ icq;
+
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned short toIcqStatus(unsigned short status)
+{
+/*
+ unsigned short icqStatus[] = { ICQ_STATUS_OFFLINE, ICQ_STATUS_ONLINE, ICQ_STATUS_AWAY, ICQ_STATUS_DND,
+ ICQ_STATUS_NA, ICQ_STATUS_OCCUPIED, ICQ_STATUS_FREEFORCHAT, ICQ_STATUS_PRIVATE };
+
+ return icqStatus[status - ID_STATUS_OFFLINE];
+*/
+ switch (status)
+ {
+ case ID_STATUS_OFFLINE: return ICQ_STATUS_OFFLINE;
+ case ID_STATUS_ONLINE: return ICQ_STATUS_ONLINE;
+ case ID_STATUS_AWAY: return ICQ_STATUS_AWAY;
+ case ID_STATUS_DND: return ICQ_STATUS_DND;
+ case ID_STATUS_NA: return ICQ_STATUS_NA;
+ case ID_STATUS_OCCUPIED: return ICQ_STATUS_OCCUPIED;
+ case ID_STATUS_FREECHAT: return ICQ_STATUS_FREECHAT;
+ case ID_STATUS_INVISIBLE: return ICQ_STATUS_PRIVATE;
+ }
+ return ICQ_STATUS_ONLINE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned short toIdStatus(unsigned short status)
+{
+ switch (status)
+ {
+ case ICQ_STATUS_OFFLINE: return ID_STATUS_OFFLINE;
+ case ICQ_STATUS_ONLINE: return ID_STATUS_ONLINE;
+ case ICQ_STATUS_AWAY: return ID_STATUS_AWAY;
+ case ICQ_STATUS_DND: return ID_STATUS_DND;
+ case ICQ_STATUS_NA: return ID_STATUS_NA;
+ case ICQ_STATUS_OCCUPIED: return ID_STATUS_OCCUPIED;
+ case ICQ_STATUS_FREECHAT: return ID_STATUS_FREECHAT;
+ case ICQ_STATUS_PRIVATE: return ID_STATUS_INVISIBLE;
+ }
+ return ID_STATUS_ONLINE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+LRESULT WINAPI messageWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SOCKET hSocket = (SOCKET)wParam;
+ unsigned short netEvents = LOWORD(lParam);
+ unsigned long result;
+
+ switch (msg)
+ {
+ case WM_NETEVENT_SERVER:
+ if (hSocket == icq.udpSocket.handleVal)
+ {
+ if (netEvents & FD_READ) icq.recvUDP(0);
+ break;
+ }
+ break;
+
+ case WM_NETEVENT_CONNECTION:
+ if (hSocket == icq.tcpSocket.handleVal)
+ {
+ if (netEvents & FD_ACCEPT) icq.recvNewTCP(0);
+ break;
+ }
+ break;
+
+ case WM_NETEVENT_USER:
+ if (netEvents & FD_READ)
+ {
+ ioctlsocket(hSocket, FIONREAD, &result);
+ if (result > 0) icq.recvTCP(hSocket);
+ }
+ if (netEvents & FD_CLOSE)
+ {
+ unsigned int i;
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ if (hSocket == icqUsers[i]->socket.handleVal)
+ {
+ T("[tcp] user %d is aborted connection\n", icqUsers[i]->uin);
+ icqUsers[i]->socket.closeConnection();
+ break;
+ }
+ }
+ }
+ break;
+
+ case WM_NETEVENT_TRANSFER:
+ if (netEvents & FD_READ)
+ {
+ ioctlsocket(hSocket, FIONREAD, &result);
+ if (result > 0) icq.recvTransferTCP(hSocket);
+ }
+ if (netEvents & FD_CLOSE)
+ {
+ unsigned int i;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ if (hSocket == icqTransfers[i]->socket.handleVal)
+ {
+ T("[tcp] user %d is aborted file connection\n", icqTransfers[i]->uin);
+ ProtoBroadcastAck(protoName, icqTransfers[i]->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, icqTransfers[i], 0);
+ delete icqTransfers[i];
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void WINAPI pingTimerProc(HWND hWnd, UINT Msg, UINT_PTR hTimer, DWORD Time)
+{
+ icq.ping();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ICQ
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ICQ::ICQ() :
+ tcpSocket(WM_NETEVENT_CONNECTION),
+ udpSocket(WM_NETEVENT_SERVER)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQ::load()
+{
+ WSADATA data;
+
+ if (WSAStartup(MAKEWORD(2,2), &data))
+ {
+ MessageBox(NULL, Translate("ICQ Corporate plugin used only WinSock v2.2 or later."), protoName, MB_ICONWARNING|MB_OK);
+ return false;
+ }
+
+ statusVal = ID_STATUS_OFFLINE;
+ searchSequenceVal = 0;
+ tcpSequenceVal = 0xFFFFFFFE;
+
+ awayMessage = new char[1];
+ awayMessage[0] = 0;
+
+ WNDCLASS wc = { 0, messageWndProc, 0, 0, hInstance, NULL, NULL, NULL, NULL, protoName };
+ if (!RegisterClass(&wc)) return false;
+
+ hWnd = CreateWindowEx(0, protoName, NULL, 0, 0, 0, 0, 0, (unsigned short)GetVersion() >= 5 ? HWND_MESSAGE : 0, NULL, hInstance, NULL);
+ if (hWnd == NULL) return false;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::unload()
+{
+ if (statusVal != ID_STATUS_OFFLINE) logoff(false);
+
+ KillTimer(NULL, pingTimer);
+ pingTimer = NULL;
+
+ delete [] awayMessage;
+
+ WSACleanup();
+
+ DestroyWindow(hWnd);
+ UnregisterClass(protoName, hInstance);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQ::logon(unsigned short logonStatus)
+{
+ DBVARIANT dbv;
+ char str[128];
+
+ if(!db_get(NULL, protoName, "Server", &dbv))
+ {
+ lstrcpy(str, dbv.pszVal);
+ db_free(&dbv);
+ }
+ else
+ {
+ MessageBox(NULL, Translate("You need specify ICQ Corporate login server."), protoName, MB_ICONWARNING|MB_OK);
+ return false;
+ }
+
+ if (!tcpSocket.connected() && !tcpSocket.startServer()) return false;
+ if (!udpSocket.connected())
+ {
+ if (!udpSocket.setDestination(str, db_get_w(NULL, protoName, "Port", 4000))) return false;
+ udpSocket.openConnection();
+ }
+
+ if (pingTimer == NULL) pingTimer = SetTimer(NULL, 0, PING_FREQUENCY, (TIMERPROC)pingTimerProc);
+
+ updateContactList();
+
+ uin = db_get_dw(NULL, protoName, "UIN", 0);
+ if (!db_get(NULL, protoName, "Password", &dbv))
+ {
+ lstrcpy(str, dbv.pszVal);
+ db_free(&dbv);
+ }
+
+
+ timeStampLastMessage = 0;
+ sequenceVal = 1;
+
+ Packet loginPacket;
+ loginPacket << ICQ_VERSION
+ << ICQ_CMDxSND_LOGON
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << tcpSocket.localPortVal
+ << str
+ << (unsigned short)0x7A
+ << (unsigned short)0x02
+// << LOCALHOST
+ << udpSocket.localIPVal
+ << (unsigned char)0x04
+ << (unsigned int)toIcqStatus(logonStatus)
+ << (unsigned int)0x02
+ << (unsigned int)0x00
+ << (unsigned short)0x13
+ << (unsigned short)0x7A;
+
+ T("[udp] requesting logon (%d)...\n", sequenceVal);
+ sendICQ(udpSocket, loginPacket, ICQ_CMDxSND_LOGON, sequenceVal);
+
+ desiredStatus = logonStatus;
+ statusVal = ID_STATUS_CONNECTING;
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_OFFLINE, statusVal);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::logoff(bool reconnect)
+{
+ unsigned int i;
+
+ // if not connected then don't both logging off
+ if (udpSocket.connected())
+ {
+ Packet logoffPacket;
+ logoffPacket << ICQ_VERSION
+ << ICQ_CMDxSND_LOGOFF
+ << (unsigned int)0x00
+ << uin
+ << (unsigned int)0x00
+ << "B_USER_DISCONNECTED"
+ << (unsigned short)0x0005;
+
+ T("[udp] logging off.\n");
+ udpSocket.sendPacket(logoffPacket);
+// udpSocket.closeConnection();
+
+ // close all open events
+ for (i=0; i<icqEvents.size(); i++) delete icqEvents[i];
+ icqEvents.clear();
+ }
+
+ statusVal = ID_STATUS_OFFLINE;
+
+ if (reconnect) logon(desiredStatus);
+ else
+ {
+ udpSocket.closeConnection();
+ tcpSocket.closeConnection();
+
+ updateContactList();
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_ONLINE, statusVal);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::ping()
+{
+ if (statusVal > ID_STATUS_OFFLINE)
+ {
+ Packet pingPacket;
+ pingPacket << ICQ_VERSION
+ << ICQ_CMDxSND_PING
+ << sequenceVal
+ << (unsigned short)0x00
+ << uin
+ << (unsigned int)0x00;
+
+ T("[udp] keep alive (%d)\n", sequenceVal);
+ sendICQ(udpSocket, pingPacket, ICQ_CMDxSND_PING, sequenceVal);
+ }
+
+ if (statusVal == ID_STATUS_OFFLINE && desiredStatus != ID_STATUS_OFFLINE) logoff(true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendICQ(Socket &socket, Packet &packet, unsigned short cmd, unsigned long sequence,
+ unsigned long uin, unsigned short subCmd, int reply)
+{
+ ICQEvent *result;
+
+ if (!socket.connected()) return NULL;
+
+ if (cmd != ICQ_CMDxTCP_START) sequenceVal++;
+
+ icqEvents.push_back(result = new ICQEvent(cmd, subCmd, sequence, uin, &socket, &packet, reply));
+ if (!result->start())
+ {
+ cancelEvent(result);
+ return NULL;
+ }
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::doneEvent(bool gotAck, int hSocket, int sequence)
+{
+ unsigned int i;
+ ICQEvent *e;
+
+ for (i=0; i<icqEvents.size(); i++)
+ {
+ e = icqEvents[i];
+ if (e->isEvent(hSocket, sequence)) break;
+ }
+ if (i == icqEvents.size()) return;
+
+ e->stop();
+ if (!gotAck || e->reply == 0)
+ {
+ icqEvents[i] = icqEvents[icqEvents.size() - 1];
+ icqEvents.pop_back();
+ }
+
+ if (!gotAck) T("[ ] sending failed (%d)\n", sequence);
+
+ switch (e->cmd)
+ {
+ case ICQ_CMDxTCP_START:
+ doneUserFcn(gotAck, e);
+ break;
+ case ICQ_CMDxSND_THRUxSERVER:
+ doneUserFcn(gotAck, e);
+ break;
+ case ICQ_CMDxSND_USERxGETxINFO:
+ //emit doneUserInfo(true, e->uin);
+ break;
+ case ICQ_CMDxSND_SETxSTATUS:
+ if (gotAck)
+ {
+ int oldStatus = statusVal;
+ statusVal = desiredStatus;
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, statusVal);
+ }
+ break;
+ case ICQ_CMDxSND_PING:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ case ICQ_CMDxSND_USERxADD:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ case ICQ_CMDxSND_AUTHORIZE:
+ //emit doneOwnerFcn(gotAck, cmd);
+ break;
+ case ICQ_CMDxSND_LOGON:
+ if (!gotAck)
+ {
+ logoff(false);
+ //emit doneOwnerFcn(false, cmd);
+ }
+ break;
+ case ICQ_CMDxSND_USERxLIST:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ case ICQ_CMDxSND_VISxLIST:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ case ICQ_CMDxSND_SYSxMSGxREQ:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ case ICQ_CMDxSND_SYSxMSGxDONExACK:
+ //if (!gotAck) emit doneOwnerFcn(false, cmd);
+ break;
+ }
+
+ if (!gotAck && e->cmd != ICQ_CMDxTCP_START && e->cmd != ICQ_CMDxSND_LOGON) logoff(true);
+
+
+ if (!gotAck || e->reply == 0) delete e;
+
+ else e->reply--;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::cancelEvent(ICQEvent *&e)
+{
+ unsigned int i;
+
+ for (i=0; i<icqEvents.size(); i++) if (icqEvents[i] == e) break;
+ if (i == icqEvents.size()) return;
+
+ e->stop();
+
+ icqEvents[i] = icqEvents[icqEvents.size() - 1];
+ icqEvents.pop_back();
+
+ delete e;
+ e = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned short ICQ::processUdpPacket(Packet &packet)
+{
+ unsigned short version, command, newCommand, theSequence, theSequence1, searchSequence, junkShort;
+ unsigned int checkUin, userIP, realIP, junkl, newStatus, userPort, timedataStamp;
+ unsigned char junkChar;
+ char *message = NULL;
+ ICQUser *u;
+ ICQEvent *e;
+
+ // read in the standard UDP header info
+ packet >> version
+ >> command
+ >> theSequence
+ >> theSequence1
+ >> checkUin
+ >> junkl;
+
+ if (version != ICQ_VERSION)
+ {
+ T("[udp] bad version number %d\n", version);
+ return 0xFFFF;
+ }
+/* on offline multi packet field checkUin not equal uin :(
+
+ if (checkUin != uin)
+ {
+ T("[udp] bad uin number %d\n", checkUin);
+ return 0xFFFF;
+ }
+*/
+ switch (command)
+ {
+ case ICQ_CMDxRCV_LOGIN_ERR:
+ T("[udp] error loging to server.\n");
+ ackUDP(theSequence);
+
+ packet >> message;
+
+ T("%s\n", message);
+ MessageBox(NULL, message, protoName, MB_ICONERROR|MB_OK);
+ delete [] message;
+ break;
+
+ case ICQ_CMDxRCV_USERxONLINE: // initial user status packet
+ packet >> checkUin;
+
+ T("[udp] user %d is online\n", checkUin);
+ ackUDP(theSequence);
+
+ if ((u = getUserByUIN(checkUin, false)) == NULL) break;
+
+ packet >> userIP
+ >> userPort
+ >> realIP
+ >> junkChar
+ >> newStatus;
+
+ u->socket.closeConnection();
+ u->socket.setDestination(userIP, userPort);
+ u->setStatus(toIdStatus(newStatus));
+ u->setInfo("IP", (unsigned int)ntohl(userIP));
+ u->setInfo("Port", (unsigned short)userPort);
+ u->setInfo("RealIP", (unsigned int)ntohl(realIP));
+ break;
+
+ case ICQ_CMDxRCV_USERxOFFLINE: // user just went offline packet
+ packet >> checkUin;
+
+ T("[udp] user %d is offline\n", checkUin);
+ ackUDP(theSequence);
+
+ if ((u = getUserByUIN(checkUin, false)) == NULL) break;
+
+ u->setStatus(ID_STATUS_OFFLINE);
+ u->socket.closeConnection();
+ break;
+
+ case ICQ_CMDxRCV_USERxBASICxINFO:
+ case ICQ_CMDxRCV_USERxINFO:
+ case ICQ_CMDxRCV_USERxWORKxINFO:
+ case ICQ_CMDxRCV_USERxWORKxPAGE:
+ case ICQ_CMDxRCV_USERxHOMExINFO:
+ case ICQ_CMDxRCV_USERxHOMExPAGE:
+ T("[udp] user information packet (%d)\n", theSequence);
+ ackUDP(theSequence);
+
+ if ((e = getEvent(udpSocket.handleVal, theSequence1)) == NULL) break;
+ checkUin = e->uin;
+ if ((u = getUserByUIN(checkUin, false)) == NULL) break;
+
+ char *buffer;
+ buffer = new char[1024];
+
+ switch (command)
+ {
+ case ICQ_CMDxRCV_USERxBASICxINFO:
+ case ICQ_CMDxRCV_USERxINFO:
+ packet >> buffer;
+ u->setInfo("Nick", buffer);
+ packet >> buffer;
+ u->setInfo("FirstName", buffer);
+ packet >> buffer;
+ u->setInfo("LastName", buffer);
+ packet >> buffer;
+ u->setInfo("e-mail", buffer);
+ break;
+
+ case ICQ_CMDxRCV_USERxWORKxINFO:
+ packet >> buffer;
+ u->setInfo("CompanyStreet", buffer);
+ packet >> buffer;
+ u->setInfo("CompanyCity", buffer);
+ packet >> buffer;
+ u->setInfo("CompanyState", buffer);
+ packet >> junkShort;
+ u->setInfo("CompanyCountry", junkShort);
+ packet >> buffer;
+ u->setInfo("Company", buffer);
+ packet >> buffer;
+ u->setInfo("CompanyPosition", buffer);
+ packet >> junkl;
+ packet >> buffer;
+ u->setInfo("CompanyPhone", buffer);
+ packet >> buffer;
+ u->setInfo("CompanyFax", buffer);
+ packet >> buffer;
+ packet >> junkl;
+ if (junkl && junkl != 0xFFFFFFFF) _itoa(junkl, buffer, 10);
+ else buffer[0] = 0;
+ u->setInfo("CompanyZIP", buffer);
+ break;
+
+ case ICQ_CMDxRCV_USERxWORKxPAGE:
+ packet >> buffer;
+ u->setInfo("CompanyHomepage", buffer);
+ break;
+
+ case ICQ_CMDxRCV_USERxHOMExINFO:
+ packet >> buffer;
+ u->setInfo("Street", buffer);
+ packet >> buffer;
+ u->setInfo("City", buffer);
+ packet >> buffer;
+ u->setInfo("State", buffer);
+ packet >> junkShort;
+ u->setInfo("Country", junkShort);
+ packet >> buffer;
+ u->setInfo("Phone", buffer);
+ packet >> buffer;
+ u->setInfo("Fax", buffer);
+ packet >> buffer;
+ u->setInfo("Cellular", buffer);
+ packet >> junkl;
+ if (junkl && junkl != 0xFFFFFFFF) _itoa(junkl, buffer, 10);
+ else buffer[0] = 0;
+ u->setInfo("ZIP", buffer);
+ packet >> junkChar;
+ if (junkChar == 1) junkChar = 'F';
+ if (junkChar == 2) junkChar = 'M';
+ u->setInfo("Gender", junkChar);
+ packet >> junkShort;
+ u->setInfo("Age", (unsigned char)junkShort);
+ packet >> junkChar;
+ u->setInfo("BirthDay", junkChar);
+ packet >> junkChar;
+ u->setInfo("BirthMonth", junkChar);
+ packet >> junkShort;
+ u->setInfo("BirthYear", junkShort);
+ break;
+
+ case ICQ_CMDxRCV_USERxHOMExPAGE:
+ packet >> buffer;
+ u->setInfo("Homepage", buffer);
+ break;
+ }
+
+ if (e->reply == 0) ProtoBroadcastAck(protoName, u->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, 0, 0);
+ doneEvent(true, udpSocket.handleVal, theSequence1);
+ delete [] buffer;
+ break;
+
+ case ICQ_CMDxRCV_USERxINVALIDxUIN: // not a good uin
+ T("[udp] invalid uin\n");
+ ackUDP(theSequence);
+
+ if ((e = getEvent(udpSocket.handleVal, theSequence1)) == NULL) break;
+
+ checkUin = e->uin;
+ T("invalid uin: %d\n", checkUin);
+/*
+ delete icqEvents[i2];
+ icqEvents[i2] = icqEvents[icqEvents.size() - 1];
+ icqEvents.pop_back();
+*/
+ break;
+
+ case ICQ_CMDxRCV_USERxSTATUS: // user changed status packet
+ packet >> checkUin;
+
+ T("[udp] user %d changed status\n", checkUin);
+ ackUDP(theSequence);
+
+ packet >> newStatus;
+
+ if ((u = getUserByUIN(checkUin, false)) == NULL) break;
+ u->setStatus(toIdStatus(newStatus));
+ break;
+
+ case ICQ_CMDxRCV_USERxLISTxDONE: // end of user list
+ T("[udp] end of user list.\n");
+ ackUDP(theSequence);
+ break;
+
+ case ICQ_CMDxRCV_SEARCHxFOUND: // user found in search
+ T("[udp] search found user\n");
+ ackUDP(theSequence);
+
+ char *alias, *firstName, *lastName, *email;
+ unsigned char auth;
+
+ alias = NULL;
+ firstName = NULL;
+ lastName = NULL;
+ email = NULL;
+
+ packet >> checkUin
+ >> alias
+ >> firstName
+ >> lastName
+ >> email
+ >> auth;
+
+ ICQSEARCHRESULT isr;
+
+ isr.hdr.cbSize = sizeof(isr);
+ isr.hdr.nick = alias;
+ isr.hdr.firstName = firstName;
+ isr.hdr.lastName = lastName;
+ isr.hdr.email = email;
+ isr.uin = checkUin;
+ isr.auth = auth;
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, (LPARAM)&isr);
+
+ delete [] alias;
+ delete [] firstName;
+ delete [] lastName;
+ delete [] email;
+ break;
+
+ case ICQ_CMDxRCV_SEARCHxDONE:
+ T("[udp] search finished.\n");
+ ackUDP(theSequence);
+
+ packet >> searchSequence;
+ searchSequence = theSequence1;
+
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
+ break;
+
+ case ICQ_CMDxRCV_SYSxMSGxOFFLINE: // offline system message, now have to check the sub-command
+ T("[udp] offline system message\n");
+ ackUDP(theSequence);
+
+ packet >> checkUin
+ >> timedataStamp
+ >> newCommand;
+
+ timeStampLastMessage = timedataStamp;
+ timedataStamp = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, timedataStamp, 0);
+
+ processSystemMessage(packet, checkUin, newCommand, timedataStamp);
+ break;
+
+ case ICQ_CMDxRCV_SYSxMSGxONLINE: // online system message, now have to check the sub-command
+ T("[udp] online system message\n");
+ ackUDP(theSequence);
+
+ packet >> checkUin
+ >> newCommand;
+
+ processSystemMessage(packet, checkUin, newCommand, time(NULL));
+ break;
+
+ case ICQ_CMDxRCV_SYSxMSGxDONE: // end of system messages
+ T("[udp] end of system messages.\n");
+ ackUDP(theSequence);
+
+ if (timeStampLastMessage)
+ {
+ ackSYS(timeStampLastMessage);
+ timeStampLastMessage = 0;
+ }
+ break;
+
+ case ICQ_CMDxRCV_BROADCASTxMULTI:
+ T("[udp] broadcast multi-packet (%d)\n", theSequence);
+ ackUDP(theSequence);
+
+ unsigned int i;
+ unsigned char j, frameNo, frameSize;
+ bool found;
+
+ packet >> frameNo
+ >> frameSize;
+
+ icqEvents.push_back(new ICQEvent(ICQ_CMDxRCV_BROADCASTxMULTI, (unsigned short)frameNo, theSequence1, 0, &udpSocket, &packet, 0));
+
+ {
+ Packet multiPacket;
+
+ for (j=0; j<frameSize; j++)
+ {
+ found = false;
+ for (i=0; i<icqEvents.size(); i++)
+ {
+ e = icqEvents[i];
+ if (e->cmd == ICQ_CMDxRCV_BROADCASTxMULTI && e->subCmd == j && e->isEvent(udpSocket.handleVal, theSequence1))
+ {
+ multiPacket << e->packet;
+ found = true;
+ break;
+ }
+ }
+ if (!found) break;
+ }
+
+ if (j == frameSize)
+ {
+ for (i=0; i<icqEvents.size(); i++)
+ {
+ e = icqEvents[i];
+ if (e->cmd == ICQ_CMDxRCV_BROADCASTxMULTI && e->isEvent(udpSocket.handleVal, theSequence1))
+ {
+ icqEvents[i] = icqEvents[icqEvents.size() - 1];
+ icqEvents.pop_back();
+
+ delete e;
+ }
+ }
+
+ multiPacket.reset();
+ processUdpPacket(multiPacket);
+ }
+ }
+ break;
+
+ case ICQ_CMDxRCV_BROADCASTxOFFLINE:
+ T("[udp] offline broadcast message (%d)\n", theSequence);
+ ackUDP(theSequence);
+
+ packet >> checkUin
+ >> timedataStamp
+ >> newCommand;
+
+ db_set_dw(NULL, protoName, "LastBroadcastTime", timedataStamp);
+ timedataStamp = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, timedataStamp, 0);
+
+ processSystemMessage(packet, checkUin, newCommand, timedataStamp);
+ break;
+
+ case ICQ_CMDxRCV_BROADCASTxONLINE:
+ T("[udp] online broadcast message (%d)\n", theSequence);
+ ackUDP(theSequence);
+
+ packet >> checkUin
+ >> newCommand;
+
+ processSystemMessage(packet, checkUin, newCommand, time(NULL));
+ break;
+
+ case ICQ_CMDxRCV_BROADCASTxDONE:
+ T("[udp] end of broadcast messages.\n");
+ ackUDP(theSequence);
+ break;
+
+ case ICQ_CMDxRCV_SETxOFFLINE: // we got put offline by mirabilis for some reason
+ T("[udp] kicked offline.\n");
+ logoff(true);
+ break;
+
+ case ICQ_CMDxRCV_ACK: // icq acknowledgement
+ T("[udp] received ack (%d)\n", theSequence);
+ doneEvent(true, udpSocket.handleVal, theSequence);
+ break;
+
+ case ICQ_CMDxRCV_ERROR: // icq says go away
+ T("[udp] server says bugger off.\n");
+ logoff(true);
+ break;
+
+ case ICQ_CMDxRCV_HELLO: // hello packet from mirabilis received on logon
+ T("[udp] received hello.\n");
+ ackUDP(theSequence);
+
+ int oldStatus;
+
+ requestSystemMsg();
+ requestBroadcastMsg();
+
+// pingTimer.start(PING_FREQUENCY * 1000);
+ oldStatus = statusVal;
+ statusVal = desiredStatus;
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, statusVal);
+
+ updateContactList();
+// sendVisibleList();
+// sendInvisibleList();
+ break;
+
+ case ICQ_CMDxRCV_WRONGxPASSWD: // incorrect password sent in logon
+ T("[udp] incorrect password.\n");
+ ProtoBroadcastAck(protoName, NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
+ MessageBox(NULL, Translate("Your ICQ Corp number and password combination was rejected by the ICQ Corporate server. Please go to M->Options->ICQCorp and try again."), protoName, MB_ICONERROR|MB_OK);
+ break;
+
+ case ICQ_CMDxRCV_BUSY: // server too busy to respond
+ T("[udp] server busy, try again in a few minutes.\n");
+ break;
+
+ default: // what the heck is this packet?
+ T("[udp] unknown packet:\n%s", packet.print());
+ ackUDP(theSequence);
+ break;
+ }
+
+ return command;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::processSystemMessage(Packet &packet, unsigned long checkUin, unsigned short newCommand, time_t timeSent)
+{
+ char *message/*, *sysMsg*/;
+ ICQUser *u;
+ unsigned int i, /*j,*/ messageLen;
+
+ u = getUserByUIN(checkUin);
+
+ message = NULL;
+ packet >> message;
+
+ switch (newCommand)
+ {
+ case ICQ_CMDxRCV_SYSxMSG:
+ T("message through server from %d\n", checkUin);
+ addMessage(u, message, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxTCP_MSG, 0, timeSent);
+ break;
+
+ case ICQ_CMDxRCV_SYSxURL:
+ T("url through server from %d\n", checkUin);
+ addUrl(u, message, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxTCP_URL, 0, timeSent);
+ break;
+
+ case ICQ_CMDxRCV_SYSxBROADCAST:
+ T("broadcast message from %d\n", checkUin);
+
+ messageLen = (unsigned int)strlen(message);
+ for (i=0; i<messageLen; i++) if (message[i] == (char)0xFE) message[i] = '\n';
+
+ addMessage(u, message, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxTCP_MSG, 0, timeSent);
+ break;
+/*
+ case ICQ_CMDxRCV_SYSxAUTHxREQ: // system message: authorisation request
+ // 02 00 04 01 08 00 8F 76 20 00 06 00 41 00 41 70 6F 74 68 65 6F 73 69 73
+ // FE 47 72 61 68 61 6D FE 52 6F 66 66 FE 67 72 6F 66 66 40 75 77 61 74 65
+ // 72 6C 6F 6F 2E 63 61 FE 31 FE 50 6C 65 61 73 65 20 61 75 74 68 6F 72 69
+ // 7A 65 20 6D 65 2E 00
+ T("authorization request from %ld.\n", checkUin);
+ packet >> messageLen;
+ message = new char[messageLen + 1];
+ for (i=0; i<=messageLen; i++)
+ {
+ packet >> message[i];
+ if (message[i] == (char)0xFE) message[i] = '\n';
+ }
+
+ sysMsg = new char[messageLen + 128];
+ sprintf(sysMsg, "(%s) Authorization request from %ld:\n%s", sm.timeRec(), checkUin, message);
+ icqOwner.addMessage(sysMsg, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxRCV_SMxREQxAUTH, 0, timeSent);
+ sprintf(sysMsg, "Authorization request from %ld:\n%s", checkUin, message);
+ addToSystemMessageHistory(sysMsg);
+ playSound(soundSysMsg);
+ delete sysMsg;
+ delete message;
+ break;
+
+ case ICQ_CMDxRCV_SYSxAUTHxGRANTED: // system message: authorization granted
+
+ outputWindow->wprintf(" (%s) Authorization granted from %ld.", sm.timeRec(), checkUin);
+ packet >> messageLen;
+ message = new char[messageLen + 1];
+ for (i = 0; i <= messageLen; i++)
+ {
+ packet >> message[i];
+ if (message[i] == (char)0xFE) message[i] = '\n';
+ }
+
+ sysMsg = new char[messageLen + 128];
+ sprintf(sysMsg, "(%s) Authorization granted from %ld:\n%s", sm.timeRec(), checkUin, message);
+ icqOwner.addMessage(sysMsg, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxRCV_SMxREQxAUTH, 0, timeSent);
+ sprintf(sysMsg, "Authorization granted from %ld:\n%s", checkUin, message);
+ addToSystemMessageHistory(sysMsg);
+ playSound(soundSysMsg);
+
+ delete sysMsg;
+ delete message;
+ break;
+*/
+/*
+ case ICQ_CMDxRCV_SYSxADDED: // system message: added to a contact list
+ outputWindow->wprintf(" %C(%s) user %C%ld%C added you to their contact list.", COLOR_RECEIVE, sm.timeRec(), COLOR_DATA, checkUin, COLOR_RECEIVE);
+ sysMsg = new char[128];
+ sprintf(sysMsg, "(%s) User %ld added you to their contact list.", sm.timeRec(), checkUin);
+ icqOwner.addMessage(sysMsg, ICQ_CMDxRCV_SYSxMSGxONLINE, ICQ_CMDxRCV_SMxADDED, 0, timeSent);
+ sprintf(sysMsg, "User %ld added you to their contact list.", checkUin);
+ addToSystemMessageHistory(sysMsg);
+ delete sysMsg;
+ playSound(soundSysMsg);
+*/
+ /* there is a bunch of info about the given user in the packet but the read routine to get
+ at it is totally broken right now
+ int infoLen, j;
+ packet >> infoLen;
+
+ // declare all the strings we will need for reading in the user data
+ char *userInfo, *aliasField, *firstNameField, *lastNameField, *emailField;
+ userInfo = new char[infoLen];
+ aliasField = new char[infoLen];
+ firstNameField = new char[infoLen];
+ lastNameField = new char[infoLen];
+ emailField = new char[infoLen];
+
+ // read in the user data from the packet
+ for (i = 0; i < infoLen; i++) packet >> userInfo[i];
+
+ // parse the user info string for the four fields
+ i = j = 0;
+ do { aliasField[j] = userInfo[i]; i++; j++;} while (userInfo[i] != (char)0xFE);
+ aliasField[j] = '\0'; j = 0;
+ do { firstNameField[j] = userInfo[i]; i++; j++;} while (userInfo[i] != (char)0xFE);
+ firstNameField[j] = '\0'; j = 0;
+ do { lastNameField[j] = userInfo[i]; i++; j++;} while (userInfo[i] != (char)0xFE);
+ lastNameField[j] = '\0'; j = 0;
+ do { emailField[j] = userInfo[i]; i++; j++;} while (i < infoLen);
+ emailField[j] = '\0';
+
+ *outputWindow << " " << aliasField << " (" << firstNameField << " " << lastNameField << "), " << emailField << ".";
+
+ delete userInfo; delete aliasField; delete firstNameField; delete lastNameField; delete emailField;
+ break;
+ */
+
+ default:
+ T("[udp] unknown system packet:\n%s", packet.print());
+ break;
+ }
+
+ delete [] message;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::ackUDP(unsigned short theSequence)
+{
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_ACK
+ << theSequence
+ << (unsigned short)0x00
+ << uin
+ << (unsigned int)0x00;
+
+ T("[udp] sending ack (%d)\n", theSequence);
+ udpSocket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::ackSYS(unsigned int timeStamp)
+{
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_SYSxMSGxDONExACK
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << timeStamp;
+
+ T("[udp] sending system message ack (%d)\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_SYSxMSGxDONExACK, sequenceVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQUser *ICQ::getUserByUIN(unsigned long uin, bool allowAdd)
+{
+ unsigned long i;
+ ICQUser *u;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->uin == uin) return u;
+ }
+
+ if (allowAdd)
+ {
+ T("unknown user %d, adding them to your list\n", uin);
+ return addUser(uin, false);
+ }
+
+ T("ICQ sent unknown user %d\n", uin);
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQUser *ICQ::getUserByContact(MCONTACT hContact)
+{
+ unsigned long i;
+ ICQUser *u;
+
+// uin = db_get_dw(ccs->hContact, protoName, "UIN", 0);
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->hContact == hContact) return u;
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::requestSystemMsg()
+{
+ // request offline system messages
+ // 02 00 4C 04 02 00 50 A5 82 00
+
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_SYSxMSGxREQ
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00;
+
+ T("[udp] sending offline system messages request (%d)...\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_SYSxMSGxREQ, sequenceVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::requestBroadcastMsg()
+{
+ unsigned int timeStamp = db_get_dw(NULL, protoName, "LastBroadcastTime", 0);
+
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_BROADCASTxREQ
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << timeStamp
+ << (unsigned int)0x00;
+
+ T("[udp] sending offline broadcast messages request (%d)...\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_SYSxMSGxREQ, sequenceVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQ::setStatus(unsigned short newStatus)
+{
+ if (!udpSocket.connected()) return false;
+
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_SETxSTATUS
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << toIcqStatus(newStatus);
+
+ T("[udp] sending set status packet (%d)\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_SETxSTATUS, sequenceVal);
+
+ desiredStatus = newStatus;
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::updateContactList()
+{
+ char *proto;
+ unsigned int i;
+ int userCount;
+ //HANDLE hContact;
+ ICQUser *u;
+
+ for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
+ proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if (proto && !strcmp(proto, protoName))
+ {
+ if ((u = getUserByContact(hContact)) == NULL)
+ {
+ u = new ICQUser();
+ u->hContact = hContact;
+ u->uin = db_get_dw(hContact, protoName, "UIN", 0);
+ icqUsers.push_back(u);
+ }
+ if (statusVal <= ID_STATUS_OFFLINE) u->setStatus(ID_STATUS_OFFLINE);
+ else u->statusVal = db_get_w(hContact, protoName, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+
+ if (statusVal <= ID_STATUS_OFFLINE) return;
+
+
+ // create user info packet
+ Packet userPacket;
+ for (i=0; i<icqUsers.size(); )
+ {
+ userCount = (unsigned int)icqUsers.size() - i;
+ if (userCount > 100) userCount = 100;
+
+ userPacket.clearPacket();
+ userPacket << ICQ_VERSION
+ << ICQ_CMDxSND_USERxLIST
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << (unsigned char)userCount;
+
+ for (; userCount>0; userCount--) userPacket << icqUsers[i++]->uin;
+
+ // send user info packet
+ T("[udp] sending contact list (%d)...\n", sequenceVal);
+ sendICQ(udpSocket, userPacket, ICQ_CMDxSND_USERxLIST, sequenceVal);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::sendVisibleList()
+{
+/*
+ unsigned int i, numUsers = 0;
+ ICQUser *u;
+
+ if (statusVal != ID_STATUS_INVISIBLE) return;
+
+ Packet userPacket;
+ userPacket << ICQ_VERSION
+ << ICQ_CMDxSND_VISxLIST
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->statusVal != ID_STATUS_OFFLINE && db_get_w(u->hContact, protoName, "ApparentMode", 0) == ID_STATUS_ONLINE)
+ numUsers++;
+ }
+
+ if (numUsers == 0) return;
+ userPacket << (char)numUsers;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->statusVal != ID_STATUS_OFFLINE && db_get_w(u->hContact, protoName, "ApparentMode", 0) == ID_STATUS_ONLINE)
+ userPacket << icqUsers[i]->uin;
+ }
+
+ T("[udp] sending visible list (%d)\n", sequenceVal);
+ sendICQ(udpSocket, userPacket, ICQ_CMDxSND_VISxLIST, sequenceVal);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::sendInvisibleList()
+{
+/*
+ unsigned int i, numUsers = 0;
+
+ Packet userPacket;
+ userPacket << ICQ_VERSION
+ << ICQ_CMDxSND_INVISxLIST
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ if (db_get_w(icqUsers[i]->hContact, protoName, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ numUsers++;
+ }
+
+ if (numUsers == 0) return;
+ userPacket << (char)numUsers;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ if (db_get_w(icqUsers[i]->hContact, protoName, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ userPacket << icqUsers[i]->uin;
+ }
+
+ T("[udp] sending invisible list (%d)\n", sequenceVal);
+ sendICQ(udpSocket, userPacket, ICQ_CMDxSND_INVISxLIST, sequenceVal);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::updateUserList(ICQUser *u, char list, char add)
+{
+/*
+ Packet userPacket;
+ userPacket << ICQ_VERSION
+ << ICQ_CMDxSND_UPDATExLIST
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << u->uin
+ << list
+ << add;
+
+ T("[udp] update user list (%d)\n", sequenceVal);
+ sendICQ(udpSocket, userPacket, ICQ_CMDxSND_UPDATExLIST, sequenceVal);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQUser *ICQ::addUser(unsigned int uin, bool persistent)
+{
+ unsigned int i;
+ ICQUser *u;
+
+ for (i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->uin == uin)
+ {
+ if (persistent)
+ {
+ db_unset(u->hContact, "CList", "NotOnList");
+ db_unset(u->hContact, "CList", "Hidden");
+ }
+ return u;
+ }
+ }
+
+ u = new ICQUser();
+ u->uin = uin;
+ u->hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ icqUsers.push_back(u);
+
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)u->hContact, (LPARAM)protoName);
+ u->setInfo("UIN", uin);
+
+ if (persistent) getUserInfo(u, true);
+ else
+ {
+ db_set_b(u->hContact, "CList", "NotOnList", 1);
+ db_set_b(u->hContact, "CList", "Hidden", 1);
+ }
+
+ updateContactList();
+ return u;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::addNewUser(ICQUser *u)
+{
+/*
+ // update the users info from the server
+ if (statusVal != ICQ_STATUS_OFFLINE)
+ {
+ Packet packet; // alert server to new user
+
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_USERxADD
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << u->uin;
+
+ T("[udp] alerting server to new user (%d)...\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_USERxADD, sequenceVal);
+
+// getUserInfo(u);
+ }
+*/
+ updateContactList();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::removeUser(ICQUser *u)
+{
+ unsigned int i;
+
+ for (i=0; i<icqUsers.size(); i++) if (icqUsers[i] == u) break;
+ if (i == icqUsers.size()) return;
+
+ icqUsers[i] = icqUsers[icqUsers.size() - 1];
+ icqUsers.pop_back();
+
+ delete u;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::startSearch(unsigned char skrit, unsigned char smode, char *sstring, unsigned int s)
+{
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_SEARCHxSTART
+ << sequenceVal
+ << (unsigned short)s
+// << (unsigned short)(icqOwner.sequence1())
+ << uin
+ << (unsigned int)0x00
+ << (unsigned char)0xFF
+ << skrit
+ << (unsigned char)0x00
+ << smode
+ << sstring;
+
+ T("[udp] starting search for user (%d)...\n", s);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_SEARCHxSTART, sequenceVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::send(ICQUser *u, unsigned short cmd, char *cmdStr, char *m)
+{
+ ICQEvent *result;
+
+ if (u->statusVal > ID_STATUS_OFFLINE && (result = sendTCP(u, cmd, cmdStr, m)) != NULL) return result;
+ else return sendUDP(u, cmd, cmdStr, m);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQ::openConnection(TCPSocket &socket)
+{
+ T("[tcp] connecting to %s on port %d...\n", inet_ntoa(*(in_addr*)&socket.remoteIPVal), socket.remotePortVal);
+ socket.openConnection();
+
+ if (!socket.connected())
+ {
+ T("[tcp] connect failed\n");
+ return false;
+ }
+
+ T("[tcp] connection successful\n");
+
+ Packet packet;
+// packet << ICQ_CMDxTCP_HANDSHAKE3
+ packet << (unsigned char)0xFF
+ << (unsigned int)0x02
+ << (unsigned int)0x00
+// << (unsigned long)tcpSocket.localPortVal
+ << uin
+ << socket.localIPVal
+ << socket.localIPVal
+ << (unsigned char)0x04
+ << (unsigned int)0x00;
+// << (unsigned long)tcpSocket.localPortVal;
+
+ T("[tcp] sending handshake\n");
+ if (!socket.sendPacket(packet))
+ {
+ T("[tcp] send failed\n");
+ return false;
+ }
+
+ T("[tcp] setup completed\n");
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendTCP(ICQUser *u, unsigned short cmd, char *cmdStr, char *m)
+{
+ if (!u->socket.connected() && !openConnection(u->socket)) return NULL;
+
+ unsigned int status;
+ if (accept)
+ {
+ switch (statusVal)
+ {
+ case ID_STATUS_ONLINE: status = 0x00100000; break;
+ case ID_STATUS_FREECHAT: status = 0x00000000; break; // ??
+ case ID_STATUS_AWAY: status = 0x01100000; break;
+ case ID_STATUS_NA: status = 0x00100000; break;
+ case ID_STATUS_DND: status = 0x00100000; break;
+ case ID_STATUS_OCCUPIED: status = 0x02100000; break;
+ case ID_STATUS_INVISIBLE: status = 0x00900000; break; // ??
+ default: status = 0x00100000; break;
+ }
+ }
+ else status = 0x00000001;
+
+ Packet packet;
+ packet << uin
+ << (unsigned short)0x02 // ICQ_VERSION
+ << ICQ_CMDxTCP_START // ICQ_CMDxTCP_ACK, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CANCEL
+ << (unsigned short)0x00
+ << uin
+ << cmd
+ << m
+ << udpSocket.localIPVal
+ << udpSocket.localIPVal
+ << tcpSocket.localPortVal
+ << (unsigned char)0x04
+ << status
+ << tcpSequenceVal--;
+
+ T("[tcp] sending %s (%d)\n", cmdStr, tcpSequenceVal + 1);
+ return sendICQ(u->socket, packet, ICQ_CMDxTCP_START, tcpSequenceVal + 1, u->uin, cmd);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendUDP(ICQUser *u, unsigned short cmd, char *cmdStr, char *m)
+{
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_THRUxSERVER
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << u->uin
+ << cmd
+ << m;
+
+/* write for offline multi packet, but not work - little architecturial trouble:
+ one big packet must divided on several little packets and Miranda use returned ONE event for control process sending,
+ but not several events
+
+ if (packet.size() > 450)
+ {
+ unsigned int i, j = 0;
+ unsigned char c, frameNo, frameSize;
+
+ packet.reset();
+
+ frameSize = (packet.size()+449) / 450;
+ for (frameNo=0; frameNo<frameSize; frameNo++)
+ {
+ Packet frame;
+ frame << ICQ_VERSION
+ << ICQ_CMDxSND_MULTI
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << frameSize
+ << frameNo;
+
+ for (i=0; i<450 && j<packet.size(); i++, j++)
+ {
+ packet >> c;
+ frame << c;
+ }
+
+ T("[udp] sending %s through server, part %d of %d (%d)\n", cmdStr, frameNo, frameSize, sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_THRUxSERVER, sequenceVal, u->uin, cmd);
+ }
+ }
+ else
+*/
+ {
+ T("[udp] sending %s through server (%d)\n", cmdStr, sequenceVal);
+ return sendICQ(udpSocket, packet, ICQ_CMDxSND_THRUxSERVER, sequenceVal, u->uin, cmd);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendMessage(ICQUser *u, char *m)
+{
+ return send(u, ICQ_CMDxTCP_MSG, "message", m);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendUrl(ICQUser *u, char *url)
+{
+ unsigned int nameLen, descriptionLen;
+ char *m, *description;
+ ICQEvent *result;
+
+ nameLen = (unsigned int)strlen(url);
+ description = (char*)url + nameLen + 1;
+ descriptionLen = (unsigned int)strlen(description);
+
+ m = new char[nameLen + descriptionLen + 2];
+ strcpy(m, description);
+ strcpy(m + descriptionLen + 1, url);
+ m[descriptionLen] = (char)0xFE;
+
+ result = send(u, ICQ_CMDxTCP_URL, "url", m);
+ delete [] m;
+
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQEvent *ICQ::sendReadAwayMsg(ICQUser *u)
+{
+ unsigned short cmd;
+
+ switch (u->statusVal)
+ {
+ case ID_STATUS_AWAY: cmd = ICQ_CMDxTCP_READxAWAYxMSG; break;
+ case ID_STATUS_DND: cmd = ICQ_CMDxTCP_READxDNDxMSG; break;
+ case ID_STATUS_NA: cmd = ICQ_CMDxTCP_READxNAxMSG; break;
+ case ID_STATUS_OCCUPIED: cmd = ICQ_CMDxTCP_READxOCCUPIEDxMSG; break;
+ case ID_STATUS_FREECHAT: cmd = ICQ_CMDxTCP_READxFREECHATxMSG; break;
+ default: return NULL;
+ }
+
+ return sendTCP(u, cmd, "away message request", "");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQTransfer *ICQ::sendFile(ICQUser *u, char *description, char *filename, unsigned int size, char **files)
+{
+ if (!u->socket.connected() && !openConnection(u->socket)) return NULL;
+
+ unsigned int i;
+
+ ICQTransfer *transfer = new ICQTransfer(u, tcpSequenceVal);
+
+ for (i=0; files[i]; i++);
+ transfer->files = new char*[i + 1];
+ for (i=0; files[i]; i++) transfer->files[i] = _strdup(files[i]);
+ transfer->files[i] = 0;
+
+ transfer->description = _strdup(description);
+ transfer->count = i;
+ transfer->totalSize = size;
+
+ transfer->path = _strdup(files[0]);
+ *strrchr(transfer->path, '\\') = 0;
+
+ icqTransfers.push_back(transfer);
+ transfer->ack(ACKRESULT_SENTREQUEST);
+
+
+ unsigned short cmd = ICQ_CMDxTCP_FILE;
+ char *m = description;
+
+ unsigned int status;
+ if (accept)
+ {
+ switch (statusVal)
+ {
+ case ID_STATUS_ONLINE: status = 0x00100000; break;
+ case ID_STATUS_FREECHAT: status = 0x00000000; break; // ??
+ case ID_STATUS_AWAY: status = 0x01100000; break;
+ case ID_STATUS_NA: status = 0x00100000; break;
+ case ID_STATUS_DND: status = 0x00100000; break;
+ case ID_STATUS_OCCUPIED: status = 0x02100000; break;
+ case ID_STATUS_INVISIBLE: status = 0x00900000; break; // ??
+ default: status = 0x00100000; break;
+ }
+ }
+ else status = 0x00000001;
+
+ Packet packet;
+ packet << uin
+ << (unsigned short)0x02 // ICQ_VERSION
+ << ICQ_CMDxTCP_START // ICQ_CMDxTCP_ACK, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CANCEL
+ << (unsigned short)0x00
+ << uin
+ << cmd
+ << m
+ << udpSocket.localIPVal
+ << udpSocket.localIPVal
+ << tcpSocket.localPortVal
+ << (unsigned char)0x04
+ << status;
+
+
+ packet << (unsigned int)0x00
+ << filename
+ << size
+ << (unsigned int)0x00;
+
+ packet << tcpSequenceVal--;
+
+ T("[tcp] sending file request (%d)\n", tcpSequenceVal + 1);
+ sendICQ(u->socket, packet, ICQ_CMDxTCP_START, tcpSequenceVal + 1, u->uin, cmd);
+ return transfer;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::acceptFile(ICQUser *u, unsigned long hTransfer, char *path)
+{
+ unsigned int theSequence = hTransfer;
+ unsigned short cmd = ICQ_CMDxTCP_FILE;
+ char m[1] = { 0 };
+
+ unsigned long status;
+ if (accept)
+ {
+ switch (statusVal)
+ {
+ case ID_STATUS_ONLINE: status = 0x00100000; break;
+ case ID_STATUS_FREECHAT: status = 0x00000000; break; // ??
+ case ID_STATUS_AWAY: status = 0x01100000; break;
+ case ID_STATUS_NA: status = 0x00100000; break;
+ case ID_STATUS_DND: status = 0x00100000; break;
+ case ID_STATUS_OCCUPIED: status = 0x02100000; break;
+ case ID_STATUS_INVISIBLE: status = 0x00900000; break; // ??
+ default: status = 0x00100000; break;
+ }
+ }
+ else status = 0x00000001;
+
+ Packet packet;
+ packet << uin
+ << (unsigned short)0x02 // ICQ_VERSION
+ << ICQ_CMDxTCP_ACK // ICQ_CMDxTCP_ACK, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CANCEL
+ << (unsigned short)0x00
+ << uin
+ << cmd
+ << m
+ << udpSocket.localIPVal
+ << udpSocket.localIPVal
+ << tcpSocket.localPortVal
+ << (unsigned char)0x04
+// << status;
+ << (unsigned int)0x00;
+
+ packet << (unsigned int)htons(tcpSocket.localPortVal)
+ << m
+ << (unsigned int)0x00
+ << tcpSocket.localPortVal;
+
+ packet << theSequence;
+
+ T("[tcp] sending accept file ack (%d)\n", theSequence);
+ u->socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::refuseFile(ICQUser *u, unsigned long hTransfer, char *reason)
+{
+ unsigned int theSequence = hTransfer;
+ unsigned short cmd = ICQ_CMDxTCP_FILE;
+ char m[1] = { 0 };
+
+ unsigned int status;
+ if (accept)
+ {
+ switch (statusVal)
+ {
+ case ID_STATUS_ONLINE: status = 0x00100000; break;
+ case ID_STATUS_FREECHAT: status = 0x00000000; break; // ??
+ case ID_STATUS_AWAY: status = 0x01100000; break;
+ case ID_STATUS_NA: status = 0x00100000; break;
+ case ID_STATUS_DND: status = 0x00100000; break;
+ case ID_STATUS_OCCUPIED: status = 0x02100000; break;
+ case ID_STATUS_INVISIBLE: status = 0x00900000; break; // ??
+ default: status = 0x00100000; break;
+ }
+ }
+ else status = 0x00000001;
+
+ Packet packet;
+ packet << uin
+ << (unsigned short)0x02 // ICQ_VERSION
+ << ICQ_CMDxTCP_ACK // ICQ_CMDxTCP_ACK, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CANCEL
+ << (unsigned short)0x00
+ << uin
+ << cmd
+ << reason
+ << udpSocket.localIPVal
+ << udpSocket.localIPVal
+ << tcpSocket.localPortVal
+ << (unsigned char)0x04
+// << status;
+ << (unsigned int)0x00000001;
+
+ packet << (unsigned int)0x00
+ << m
+ << (unsigned int)0x00
+ << (unsigned int)0x00;
+
+ packet << theSequence;
+
+ T("[tcp] sending refuse file ack (%d)\n", theSequence);
+ u->socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ICQ::getUserInfo(ICQUser *u, bool basicInfo)
+{
+ unsigned short cmd = basicInfo ? ICQ_CMDxSND_USERxGETxBASICxINFO : ICQ_CMDxSND_USERxGETxINFO;
+
+ Packet request;
+ request << ICQ_VERSION
+ << cmd
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << u->uin;
+
+ T("[udp] sending user %s info request (%d)...\n", basicInfo ? "basic" : "details", sequenceVal);
+ sendICQ(udpSocket, request, cmd, sequenceVal, u->uin, 0, basicInfo ? 1 : 5);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::authorize(unsigned int uinToAuthorize)
+{
+ Packet packet;
+ packet << ICQ_VERSION
+ << ICQ_CMDxSND_AUTHORIZE
+ << sequenceVal
+ << sequenceVal
+ << uin
+ << (unsigned int)0x00
+ << uinToAuthorize
+ << (unsigned int)0x00010008 // who knows, seems to be constant
+ << (unsigned char)0x00;
+
+ T("[udp] sending authorization (%d)\n", sequenceVal);
+ sendICQ(udpSocket, packet, ICQ_CMDxSND_AUTHORIZE, sequenceVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::processTcpPacket(Packet &packet, unsigned int hSocket)
+{
+ unsigned int i, checkUin, senderIp, localIp, userStatus, senderPort, junkLong, thePort, theTCPSequence;
+ unsigned short version, command, junkShort, newCommand, /*messageLen,*/ cicqVersion;
+ unsigned char cicqChar, junkChar;
+ char *message = NULL;
+ ICQUser *u;
+ static unsigned int chatUin, chatSequence;
+
+ packet >> checkUin
+ >> version
+ >> command // so far either message stuff or message ack
+ >> junkShort // 00 00 to fill in the MSB of the command long int which is read in as a short
+ >> checkUin
+ >> newCommand // if a message then what type, message/chat/read away message/...
+ >> message
+ >> senderIp
+ >> localIp
+ >> senderPort
+ >> junkChar
+ >> userStatus;
+
+ u = getUserByUIN(checkUin);
+ switch(command)
+ {
+ case ICQ_CMDxTCP_START: // incoming tcp packet containing one of many possible things
+ switch(newCommand) // do a switch on what it could be
+ {
+ case ICQ_CMDxTCP_MSG: // straight message from a user
+ T("[tcp] message from %d.\n", checkUin);
+
+ packet >> theTCPSequence;
+
+ ackTCP(packet, u, newCommand, theTCPSequence);
+ addMessage(u, message, ICQ_CMDxTCP_START, ICQ_CMDxTCP_MSG, theTCPSequence, time(NULL));
+ break;
+
+ case ICQ_CMDxTCP_CHAT:
+ T("[tcp] chat request from %d.\n", checkUin);
+
+ packet >> junkLong
+ >> junkLong
+ >> junkShort
+ >> junkChar
+ >> theTCPSequence
+ >> cicqChar
+ >> cicqVersion;
+/*
+ char *chatReq;
+ chatReq = new char[messageLen + 32];
+ sprintf(chatReq, "Chat request:\n %s", message);
+// u->addMessage(chatReq, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CHAT, theTCPSequence, 0, (cicqChar == 'C'), cicqVersion);
+ delete chatReq;
+*/
+ break;
+
+ case ICQ_CMDxTCP_URL: // url sent
+ T("[tcp] url from %d.\n", checkUin);
+
+ packet >> theTCPSequence;
+
+ ackTCP(packet, u, newCommand, theTCPSequence);
+ addUrl(u, message, ICQ_CMDxTCP_START, ICQ_CMDxTCP_URL, theTCPSequence, time(NULL));
+ break;
+
+ case ICQ_CMDxTCP_FILE:
+ unsigned int size;
+ char *fileName;
+
+ fileName = NULL;
+ packet >> junkLong
+ >> fileName
+ >> size
+ >> junkLong
+ >> theTCPSequence;
+
+ T("[tcp] file transfer request from %d (%d)\n", checkUin, theTCPSequence);
+
+ addFileReq(u, message, fileName, size, ICQ_CMDxTCP_START, ICQ_CMDxTCP_FILE, theTCPSequence, time(NULL));
+ delete [] fileName;
+ break;
+
+ case ICQ_CMDxTCP_READxAWAYxMSG: // read away message
+ case ICQ_CMDxTCP_READxOCCUPIEDxMSG:
+ case ICQ_CMDxTCP_READxNAxMSG:
+ case ICQ_CMDxTCP_READxDNDxMSG:
+ case ICQ_CMDxTCP_READxFREECHATxMSG:
+ T("[tcp] %d requested read of away message.\n", checkUin);
+
+ packet >> theTCPSequence;
+ ackTCP(packet, u, newCommand, theTCPSequence);
+ break;
+ }
+ break;
+
+ case ICQ_CMDxTCP_ACK: // message received packet
+ switch (newCommand)
+ {
+ case ICQ_CMDxTCP_MSG:
+ packet >> theTCPSequence;
+ break;
+
+ case ICQ_CMDxTCP_CHAT:
+ packet >> junkShort
+ >> junkChar
+ >> junkLong // port backwards
+ >> thePort // port to connect to for chat
+ >> theTCPSequence;
+
+ if (chatSequence != theTCPSequence || chatUin != checkUin) // only if this is the first chat ack packet
+ { // do we do anything
+ chatSequence = theTCPSequence;
+ chatUin = checkUin;
+// emit eventResult(u, ICQ_CMDxTCP_CHAT, userStatus == 0x0000 ? true : false, thePort);
+ }
+ break;
+
+ case ICQ_CMDxTCP_URL:
+ packet >> theTCPSequence;
+ break;
+
+ case ICQ_CMDxTCP_FILE:
+ packet >> junkLong
+ >> junkShort
+ >> junkChar
+ >> junkLong
+ >> thePort
+ >> theTCPSequence;
+
+ T("[tcp] file transfer ack from %d (%d)\n", u->uin, theTCPSequence);
+
+ ICQTransfer *t;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ t = icqTransfers[i];
+ if (t->uin == checkUin && !t->socket.connected())
+ {
+ if (userStatus != 0)
+ {
+ T("[tcp] file transfer denied by %d\n", checkUin);
+ ProtoBroadcastAck(protoName, t->hContact, ACKTYPE_FILE, ACKRESULT_DENIED, t, 0);
+ delete t;
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+
+ if (!t->socket.setDestination(u->socket.remoteIPVal, thePort))
+ {
+ T("[tcp] can't set destination\n");
+ break;
+ }
+ t->ack(ACKRESULT_CONNECTING);
+ if (openConnection(t->socket))
+ {
+ t->ack(ACKRESULT_CONNECTED);
+ t->sendPacket0x00();
+ }
+ break;
+ }
+ }
+ break;
+
+ case ICQ_CMDxTCP_READxAWAYxMSG:
+ case ICQ_CMDxTCP_READxOCCUPIEDxMSG:
+ case ICQ_CMDxTCP_READxNAxMSG:
+ case ICQ_CMDxTCP_READxDNDxMSG:
+ case ICQ_CMDxTCP_READxFREECHATxMSG:
+ packet >> theTCPSequence;
+ addAwayMsg(u, message, ICQ_CMDxTCP_START, ICQ_CMDxTCP_READxAWAYxMSG, theTCPSequence, time(NULL));
+ break;
+ }
+
+ // output the away message if there is one (ie if user status is not online)
+ if (userStatus == 0x0000) T("[tcp] ack from %d (%d).\n", u->uin, theTCPSequence);
+ else if (userStatus == 0x0001)
+ {
+ T("[tcp] refusal from %d (%d): %s\n", u->uin, theTCPSequence, message);
+ }
+ else
+ {
+// u->setAwayMessage(message);
+ T("[tcp] ack from %d (%d).\n", u->uin, theTCPSequence);
+// T("[tcp] ack from %d (%ld): %s\n", u->uin, theTCPSequence, message);
+ }
+
+ doneEvent(true, hSocket, theTCPSequence);
+ break;
+
+ case ICQ_CMDxTCP_CANCEL:
+ switch (newCommand)
+ {
+ case ICQ_CMDxTCP_CHAT:
+ T("[tcp] chat request from %d (%d) cancelled.\n", checkUin, theTCPSequence);
+// u->addMessage(chatReq, ICQ_CMDxTCP_CANCEL, ICQ_CMDxTCP_CHAT, 0);
+ break;
+
+ case ICQ_CMDxTCP_FILE:
+ T("[tcp] file transfer request from %d (%d) cancelled.\n", u->uin, theTCPSequence);
+// u->addMessage(fileReq, ICQ_CMDxTCP_CANCEL, ICQ_CMDxTCP_FILE, 0);
+ break;
+ }
+ break;
+
+ default:
+ T("[tcp] unknown packet:\n%s", packet.print());
+ packet.reset();
+ }
+ delete [] message;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::ackTCP(Packet &packet, ICQUser *u, unsigned short newCommand, unsigned int theSequence)
+{
+ unsigned int status;
+
+ switch (statusVal)
+ {
+ case ID_STATUS_ONLINE: status = 0x00100000; break;
+ case ID_STATUS_FREECHAT: status = 0x00000000; break; // ??
+ case ID_STATUS_AWAY: status = 0x01100000; break;
+ case ID_STATUS_NA: status = 0x00100000; break;
+ case ID_STATUS_DND: status = 0x00100000; break;
+ case ID_STATUS_OCCUPIED: status = 0x02100000; break;
+ case ID_STATUS_INVISIBLE: status = 0x00900000; break; // ??
+ default: status = 0x00100000; break;
+ }
+
+ packet.clearPacket();
+ packet << uin
+ << (unsigned short)0x02
+ << (unsigned short)ICQ_CMDxTCP_ACK // ICQ_CMDxTCP_ACK, ICQ_CMDxTCP_START, ICQ_CMDxTCP_CANCEL
+ << (unsigned short)0x00
+ << uin
+ << newCommand
+ << awayMessage
+ << u->socket.localIPVal
+ << u->socket.localIPVal
+ << u->socket.localPortVal
+ << (unsigned char)0x04
+ << status
+ << theSequence;
+
+ T("[tcp] sending ack (%d)\n", theSequence);
+ u->socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::recvUDP(int)
+{
+ Packet packet;
+
+ // mirabilis contacts us using udp on this server
+ if (udpSocket.receivePacket(packet)) processUdpPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::recvNewTCP(int)
+{
+ ICQUser *u;
+ Packet handshake;
+
+ // our tcp incoming server
+ TCPSocket newSocket(0);
+ tcpSocket.receiveConnection(newSocket);
+ newSocket.receivePacket(handshake);
+
+ unsigned int ulJunk, newUin, localHost;
+ unsigned short command, usJunk;
+ unsigned char ucJunk;
+
+ handshake >> command;
+
+ if (command != ICQ_CMDxTCP_HANDSHAKE && command != ICQ_CMDxTCP_HANDSHAKE2 && command != ICQ_CMDxTCP_HANDSHAKE3)
+ {
+ T("[tcp] garbage packet:\n%s", handshake.print());
+ handshake.reset();
+ }
+ else
+ {
+ handshake >> ulJunk
+ >> usJunk
+ >> ucJunk
+ >> newUin
+ >> localHost
+ >> localHost
+ >> ulJunk
+ >> ucJunk;
+
+ u = getUserByUIN(newUin);
+ if (!u->socket.connected())
+ {
+ T("[tcp] connection from uin %d.\n", newUin);
+ u->socket.transferConnectionFrom(newSocket);
+ }
+ else
+ {
+ unsigned int i;
+ ICQTransfer *t;
+
+ T("[tcp] file direct connection from uin %d.\n", newUin);
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ t = icqTransfers[i];
+ if (t->uin == newUin && !t->socket.connected()) t->socket.transferConnectionFrom(newSocket);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::recvTCP(SOCKET hSocket)
+{
+ unsigned int i;
+ Packet packet;
+ ICQUser *u;
+
+ for(i=0; i<icqUsers.size(); i++)
+ {
+ u = icqUsers[i];
+ if (u->socket.handleVal == hSocket)
+ {
+ if (!u->socket.receivePacket(packet))
+ {
+ T("[tcp] connection to %d lost.\n", u->uin);
+ return;
+ }
+ processTcpPacket(packet, hSocket);
+ return;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::recvTransferTCP(SOCKET hSocket)
+{
+ unsigned int i;
+ Packet packet;
+ ICQTransfer *transfer;
+
+ for(i=0; i<icqTransfers.size(); i++)
+ {
+ transfer = icqTransfers[i];
+ if (transfer->socket.handleVal == hSocket)
+ {
+ if (!transfer->socket.receivePacket(packet))
+ {
+// T("[tcp] connection to %d lost.\n", s->uin);
+ return;
+ }
+ transfer->processTcpPacket(packet);
+ return;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::addMessage(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ T("message: %s\n", m);
+
+ ccs.hContact = u->hContact;
+ ccs.szProtoService = PSR_MESSAGE;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.flags = 0;
+ pre.timestamp = t;
+ pre.szMessage = (char*)m;
+ pre.lParam = 0;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::addUrl(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t)
+{
+ unsigned int i, messageLen;
+ char *url;
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ messageLen = lstrlen(m);
+ for (i=0; i<messageLen; i++) if (m[i] == (char)0xFE) m[i] = 0;
+
+ url = new char[messageLen + 1];
+ lstrcpy(url, m + lstrlen(m) + 1);
+ lstrcpy(url + lstrlen(url) + 1, m);
+
+ ccs.hContact = u->hContact;
+ ccs.szProtoService = PSR_URL;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.flags = 0;
+ pre.timestamp = t;
+ pre.szMessage = url;
+ pre.lParam = 0;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ delete [] url;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::addAwayMsg(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+
+ T("away msg: %s\n", m);
+
+ ccs.hContact = u->hContact;
+ ccs.szProtoService = PSR_AWAYMSG;
+ ccs.wParam = u->statusVal;
+ ccs.lParam = (LPARAM)&pre;
+ pre.flags = 0;
+ pre.timestamp = t;
+ pre.szMessage = (char*)m;
+ pre.lParam = theSequence;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/*
+void ICQ::addAdded(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t)
+{
+ DBEVENTINFO dbei;
+ PBYTE pCurBlob;
+
+ //blob is: uin(DWORD), nick(ASCIIZ), first(ASCIIZ), last(ASCIIZ), email(ASCIIZ)
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize=sizeof(dbei);
+ dbei.szModule="ICQ";
+ dbei.timestamp=TimestampLocalToGMT(YMDHMSToTime(year,month,day,hour,minute,0));
+ dbei.flags=0;
+ dbei.eventType=EVENTTYPE_ADDED;
+ dbei.cbBlob=sizeof(DWORD)+strlen(nick)+strlen(first)+strlen(last)+strlen(email)+4;
+ pCurBlob=dbei.pBlob=(PBYTE)malloc(dbei.cbBlob);
+ CopyMemory(pCurBlob,&uin,sizeof(DWORD)); pCurBlob+=sizeof(DWORD);
+ CopyMemory(pCurBlob,nick,strlen(nick)+1); pCurBlob+=strlen(nick)+1;
+ CopyMemory(pCurBlob,first,strlen(first)+1); pCurBlob+=strlen(first)+1;
+ CopyMemory(pCurBlob,last,strlen(last)+1); pCurBlob+=strlen(last)+1;
+ CopyMemory(pCurBlob,email,strlen(email)+1); pCurBlob+=strlen(email)+1;
+ CallService(MS_DB_EVENT_ADD,(WPARAM)(HANDLE)NULL,(LPARAM)&dbei);
+}
+*/
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::addFileReq(ICQUser *u, char *m, char *filename, unsigned long size, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t)
+{
+ CCSDATA ccs;
+ PROTORECVEVENT pre;
+ char *szBlob;
+/*
+ filetransfer *ft;
+
+ // Initialize a filetransfer struct
+ ft = new filetransfer;
+ memset(ft, 0, sizeof(filetransfer));
+ ft->status = 0;
+ ft->wCookie = wCookie;
+ ft->szFilename = _strdup(fileName);
+ ft->szDescription = _strdup(m);
+ ft->dwUin = u->uin;
+ ft->fileId = -1;
+ ft->dwTotalSize = size;
+ ft->nVersion = nVersion;
+ ft->TS1 = dwID1;
+ ft->TS2 = dwID2;
+*/
+ ICQTransfer *transfer = new ICQTransfer(u, theSequence);
+ transfer->description = _strdup(m);
+ transfer->totalSize = size;
+
+ icqTransfers.push_back(transfer);
+
+
+
+ // Send chain event
+ szBlob = new char[sizeof(DWORD) + strlen(filename) + strlen(m) + 2];
+
+ *(PDWORD)szBlob = (DWORD)transfer;
+ strcpy(szBlob + sizeof(DWORD), filename);
+ strcpy(szBlob + sizeof(DWORD) + strlen(filename) + 1, m);
+
+ ccs.hContact = u->hContact;
+ ccs.szProtoService = PSR_FILE;
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)&pre;
+ pre.flags = 0;
+ pre.timestamp = t;
+ pre.szMessage = szBlob;
+ pre.lParam = theSequence;
+ CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
+
+ delete [] szBlob;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQ::doneUserFcn(bool ack, ICQEvent *icqEvent)
+{
+ unsigned int type = 0;
+
+ if (icqEvent->subCmd == ICQ_CMDxTCP_MSG) type = ACKTYPE_MESSAGE;
+ if (icqEvent->subCmd == ICQ_CMDxTCP_URL) type = ACKTYPE_URL;
+
+ ProtoBroadcastAck(protoName, getUserByUIN(icqEvent->uin)->hContact, type, ack ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)icqEvent->sequence, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/protocol.h b/protocols/ICQCorp/src/protocol.h
new file mode 100644
index 0000000000..60294d834c
--- /dev/null
+++ b/protocols/ICQCorp/src/protocol.h
@@ -0,0 +1,223 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 protocol_h
+#define protocol_h
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define ICQ_TCP_VER 0x0002
+#define ICQ_UDP_VER 0x0003
+
+// UDP commands
+const unsigned short ICQ_CMDxRCV_SETxOFFLINE = 0x0028;
+const unsigned short ICQ_CMDxRCV_LOGIN_ERR = 0x0370;
+const unsigned short ICQ_CMDxRCV_ACK = 0x000A;
+const unsigned short ICQ_CMDxRCV_HELLO = 0x005A;
+const unsigned short ICQ_CMDxRCV_WRONGxPASSWD = 0x0064;
+const unsigned short ICQ_CMDxRCV_USERxONLINE = 0x006E;
+const unsigned short ICQ_CMDxRCV_USERxOFFLINE = 0x0078;
+const unsigned short ICQ_CMDxRCV_SEARCHxFOUND = 0x008C;
+const unsigned short ICQ_CMDxRCV_SEARCHxDONE = 0x00A0;
+const unsigned short ICQ_CMDxRCV_SYSxMSGxOFFLINE = 0x00DC;
+const unsigned short ICQ_CMDxRCV_SYSxMSGxONLINE = 0x0104;
+const unsigned short ICQ_CMDxRCV_SYSxMSGxDONE = 0x00E6;
+const unsigned short ICQ_CMDxRCV_BROADCASTxMULTI = 0x0366;
+const unsigned short ICQ_CMDxRCV_BROADCASTxOFFLINE = 0x038E;
+const unsigned short ICQ_CMDxRCV_BROADCASTxONLINE = 0x03A2;
+const unsigned short ICQ_CMDxRCV_BROADCASTxDONE = 0x0398;
+const unsigned short ICQ_CMDxRCV_ERROR = 0x00F0;
+const unsigned short ICQ_CMDxRCV_BUSY = 0x00FA;
+const unsigned short ICQ_CMDxRCV_USERxBASICxINFO = 0x0118;
+const unsigned short ICQ_CMDxRCV_USERxINFO = 0x02e4;
+const unsigned short ICQ_CMDxRCV_USERxWORKxINFO = 0x02F8;
+const unsigned short ICQ_CMDxRCV_USERxWORKxPAGE = 0x030C;
+const unsigned short ICQ_CMDxRCV_USERxHOMExINFO = 0x0320;
+const unsigned short ICQ_CMDxRCV_USERxHOMExPAGE = 0x0334;
+
+const unsigned short ICQ_CMDxRCV_USERxSTATUS = 0x01A4;
+const unsigned short ICQ_CMDxRCV_USERxINVALIDxUIN = 0x02EE;
+const unsigned short ICQ_CMDxRCV_USERxLISTxDONE = 0x021C;
+
+const unsigned short ICQ_CMDxRCV_SYSxMSG = 0x0001;
+const unsigned short ICQ_CMDxRCV_SYSxURL = 0x0004;
+const unsigned short ICQ_CMDxRCV_SYSxAUTHxREQ = 0x0006;
+const unsigned short ICQ_CMDxRCV_SYSxAUTHxGRANTED = 0x0008;
+const unsigned short ICQ_CMDxRCV_SYSxADDED = 0x000C;
+const unsigned short ICQ_CMDxRCV_SYSxBROADCAST = 0x0014;
+
+const unsigned short ICQ_CMDxSND_ACK = 0x000A;
+const unsigned short ICQ_CMDxSND_SEARCHxSTART = 0x05c8;
+const unsigned short ICQ_CMDxSND_THRUxSERVER = 0x010E;
+const unsigned short ICQ_CMDxSND_PING = 0x042E;
+const unsigned short ICQ_CMDxSND_LOGON = 0x03E8;
+const unsigned short ICQ_CMDxSND_LOGOFF = 0x0438;
+const unsigned short ICQ_CMDxSND_SYSxMSGxDONExACK = 0x0442;
+const unsigned short ICQ_CMDxSND_SYSxMSGxREQ = 0x044C;
+const unsigned short ICQ_CMDxSND_BROADCASTxREQ = 0x0604;
+const unsigned short ICQ_CMDxSND_MULTI = 0x05D2;
+const unsigned short ICQ_CMDxSND_USERxGETxINFO = 0x05FA;
+const unsigned short ICQ_CMDxSND_USERxGETxBASICxINFO = 0x0460;
+const unsigned short ICQ_CMDxSND_USERxADD = 0x053C;
+const unsigned short ICQ_CMDxSND_SETxSTATUS = 0x04D8;
+const unsigned short ICQ_CMDxSND_USERxLIST = 0x0406;
+const unsigned short ICQ_CMDxSND_INVISxLIST = 0x06A4;
+const unsigned short ICQ_CMDxSND_VISxLIST = 0x06AE;
+const unsigned short ICQ_CMDxSND_UPDATExLIST = 0x06B8;
+const unsigned short ICQ_CMDxSND_AUTHORIZE = 0x0456;
+
+const unsigned short int ICQ_CMDxSND_PING2 = 0x051E;
+
+// TCP commands
+const unsigned short ICQ_CMDxTCP_START = 0x07EE;
+const unsigned short ICQ_CMDxTCP_CANCEL = 0x07D0;
+const unsigned short ICQ_CMDxTCP_ACK = 0x07DA;
+
+const unsigned short ICQ_CMDxTCP_MSG = 0x0001;
+const unsigned short ICQ_CMDxTCP_CHAT = 0x0002;
+const unsigned short ICQ_CMDxTCP_FILE = 0x0003;
+const unsigned short ICQ_CMDxTCP_URL = 0x0004;
+const unsigned short ICQ_CMDxTCP_READxAWAYxMSG = 0x03E8;
+const unsigned short ICQ_CMDxTCP_READxOCCUPIEDxMSG = 0x03E9;
+const unsigned short ICQ_CMDxTCP_READxNAxMSG = 0x03EA;
+const unsigned short ICQ_CMDxTCP_READxDNDxMSG = 0x03EB;
+const unsigned short ICQ_CMDxTCP_READxFREECHATxMSG = 0x03EC;
+const unsigned short ICQ_CMDxTCP_HANDSHAKE = 0x03FF;
+const unsigned short ICQ_CMDxTCP_HANDSHAKE2 = 0x04FF;
+const unsigned short ICQ_CMDxTCP_HANDSHAKE3 = 0x02FF;
+
+// status constants
+const unsigned short int ICQ_STATUS_OFFLINE = 0xFFFF;
+const unsigned short int ICQ_STATUS_ONLINE = 0x0000;
+const unsigned short int ICQ_STATUS_AWAY = 0x0001;
+const unsigned short int ICQ_STATUS_NA = 0x0005;
+const unsigned short int ICQ_STATUS_OCCUPIED = 0x0011;
+const unsigned short int ICQ_STATUS_DND = 0x0013;
+const unsigned short int ICQ_STATUS_FREECHAT = 0x0020;
+const unsigned short int ICQ_STATUS_PRIVATE = 0x0100;
+
+// miscellaneous constants
+const unsigned short int ICQ_VERSION = 0x0003;
+const unsigned short MAX_MESSAGE_SIZE = 450;
+const unsigned short INT_VERSION = 40;
+const unsigned short PING_FREQUENCY = 45000;
+const unsigned short DEFAULT_SERVER_PORT = 4000;
+const unsigned short MAX_SERVER_RETRIES = 3;
+const unsigned short MAX_WAIT_ACK = 10000;
+const unsigned long LOCALHOST = 0x0100007F;
+
+
+const unsigned int WM_NETEVENT_SERVER = WM_USER + 1;
+const unsigned int WM_NETEVENT_CONNECTION = WM_USER + 2;
+const unsigned int WM_NETEVENT_USER = WM_USER + 3;
+const unsigned int WM_NETEVENT_TRANSFER = WM_USER + 4;
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef struct { //extended search result structure, used for all searches
+ PROTOSEARCHRESULT hdr;
+ DWORD uin;
+ BYTE auth;
+} ICQSEARCHRESULT;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ICQ
+{
+public:
+ ICQ();
+ bool load();
+ void unload();
+
+ bool setStatus(unsigned short newStatus);
+ ICQEvent *sendMessage(ICQUser *u, char *m);
+ ICQEvent *sendUrl(ICQUser *u, char *url);
+ ICQEvent *sendReadAwayMsg(ICQUser *u);
+ ICQTransfer *sendFile(ICQUser *u, char *description, char *filename, unsigned int size, char **files);
+
+ bool logon(unsigned short logonStatus);
+ void logoff(bool reconnect);
+ void ping();
+ unsigned short processUdpPacket(Packet &packet);
+ void doneEvent(bool gotAck, int hSocket, int sequence);
+ void cancelEvent(ICQEvent *&);
+ void ackUDP(unsigned short theSequence);
+ ICQEvent *sendICQ(Socket &socket, Packet &packet, unsigned short cmd, unsigned long sequence, unsigned long uin = 0, unsigned short subCmd = 0, int reply = 0);
+ ICQUser *getUserByUIN(unsigned long uin, bool allowAdd = true);
+ ICQUser *getUserByContact(MCONTACT hContact);
+ void requestSystemMsg();
+ void requestBroadcastMsg();
+ void updateContactList();
+ void sendVisibleList();
+ void sendInvisibleList();
+ void updateUserList(ICQUser *u, char list, char add);
+ void processSystemMessage(Packet &packet, unsigned long checkUin, unsigned short newCommand, time_t timeSent);
+ void ackSYS(unsigned int timeStamp);
+ ICQUser *addUser(unsigned int uin, bool peristent = true);
+ void addNewUser(ICQUser *u);
+ void removeUser(ICQUser *u);
+ void startSearch(unsigned char skrit, unsigned char smode, char *sstring, unsigned int s);
+
+
+ bool getUserInfo(ICQUser *u, bool basicInfo);
+ void authorize(unsigned int uinToAuthorize);
+ void processTcpPacket(Packet &packet, unsigned int hSocket);
+ void ackTCP(Packet &packet, ICQUser *u, unsigned short newCommand, unsigned int theSequence);
+ void recvUDP(int);
+ void recvNewTCP(int);
+ void recvTCP(SOCKET hSocket);
+ void recvTransferTCP(SOCKET hSocket);
+
+ void addMessage(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t = 0);
+ void addUrl(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t = 0);
+ void addAwayMsg(ICQUser *u, char *m, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t = 0);
+ void addFileReq(ICQUser *u, char *m, char *filename, unsigned long size, unsigned short theCmd, unsigned short theSubCmd, unsigned long theSequence, time_t t = 0);
+ void doneUserFcn(bool ack, ICQEvent *icqEvent);
+
+ void acceptFile(ICQUser *u, unsigned long hTransfer, char *path);
+ void refuseFile(ICQUser *u, unsigned long hTransfer, char *reason);
+
+ TCPSocket tcpSocket;
+ UDPSocket udpSocket;
+ unsigned short sequenceVal, searchSequenceVal;
+ unsigned int uin, tcpSequenceVal;
+ unsigned short desiredStatus;
+ unsigned short statusVal;
+ unsigned int pingTimer;
+// int eventThread;
+ HWND hWnd;
+ char *awayMessage;
+ unsigned int timeStampLastMessage;
+private:
+ ICQEvent *send(ICQUser *u, unsigned short cmd, char *cmdStr, char *m);
+
+ bool openConnection(TCPSocket &socket);
+
+ ICQEvent *sendTCP(ICQUser *u, unsigned short cmd, char *cmdStr, char *m);
+
+ ICQEvent *sendUDP(ICQUser *u, unsigned short cmd, char *cmdStr, char *m);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern ICQ icq;
+
+#endif
diff --git a/protocols/ICQCorp/src/resource.h b/protocols/ICQCorp/src/resource.h
new file mode 100644
index 0000000000..7d590bb97b
--- /dev/null
+++ b/protocols/ICQCorp/src/resource.h
@@ -0,0 +1,46 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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.
+*/
+
+#define IDI_ICQCORP 1
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define IDD_INFO_ICQCORP 101
+
+#define IDC_INFO_UIN 1001
+#define IDC_INFO_IP 1002
+#define IDC_INFO_REALIP 1003
+#define IDC_INFO_PORT 1004
+#define IDC_INFO_VERSION 1005
+#define IDC_INFO_MIRVER 1006
+#define IDC_INFO_PING 1007
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define IDD_OPT_ICQCORP 102
+
+#define IDC_OPT_UIN 1001
+#define IDC_OPT_PASSWORD 1002
+#define IDC_OPT_SERVER 1003
+#define IDC_OPT_PORT 1004
+#define IDC_OPT_RECONNECT 1005
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define IDC_STATIC -1
diff --git a/protocols/ICQCorp/src/services.cpp b/protocols/ICQCorp/src/services.cpp
new file mode 100644
index 0000000000..a94fa5450c
--- /dev/null
+++ b/protocols/ICQCorp/src/services.cpp
@@ -0,0 +1,589 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqGetCaps(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam)
+ {
+ case PFLAGNUM_1:
+ return PF1_IM|PF1_URL|PF1_FILE|PF1_MODEMSG|PF1_AUTHREQ|PF1_ADDED|PF1_PEER2PEER|PF1_BASICSEARCH|PF1_EXTSEARCH|PF1_CANRENAMEFILE|PF1_FILERESUME|PF1_ADDSEARCHRES|PF1_SEARCHBYEMAIL|PF1_SEARCHBYNAME|PF1_NUMERICUSERID;
+
+ case PFLAGNUM_2:
+ return PF2_ONLINE|PF2_INVISIBLE|PF2_SHORTAWAY|PF2_LONGAWAY|PF2_LIGHTDND|PF2_HEAVYDND|PF2_FREECHAT;
+
+ case PFLAGNUM_3:
+ return PF2_SHORTAWAY|PF2_LONGAWAY|PF2_LIGHTDND|PF2_HEAVYDND|PF2_FREECHAT;
+
+ case PFLAG_UNIQUEIDTEXT:
+ return (int)Translate("ICQ number:");
+
+ case PFLAG_UNIQUEIDSETTING:
+ return (int)"UIN";
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqGetName(WPARAM wParam, LPARAM lParam)
+{
+ strncpy((char*)lParam, Translate(protoName), wParam);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqLoadIcon(WPARAM wParam, LPARAM lParam)
+{
+ unsigned int id;
+
+ switch (wParam & 0xFFFF)
+ {
+ case PLI_PROTOCOL: id = IDI_ICQCORP; break;
+ default: return (int)(HICON)NULL;
+ }
+ return (int)LoadImage(hInstance, MAKEINTRESOURCE(id), IMAGE_ICON, GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON), GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSetStatus(WPARAM wParam, LPARAM lParam)
+{
+ unsigned short desiredStatus = (unsigned short)wParam;
+
+ T("[ ] set status\n");
+
+ // on change status to online set away msg not calling
+ if (desiredStatus == ID_STATUS_ONLINE) icq.awayMessage[0] = 0;
+
+ if (icq.desiredStatus == desiredStatus) return 0;
+ if (desiredStatus == ID_STATUS_OFFLINE)
+ {
+ icq.desiredStatus = desiredStatus;
+ icq.logoff(false);
+ }
+ else
+ {
+ if (icq.statusVal == ID_STATUS_OFFLINE) icq.logon(desiredStatus);
+ else icq.setStatus(desiredStatus);
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqGetStatus(WPARAM wParam, LPARAM lParam)
+{
+ return icq.statusVal;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqAuthAllow(WPARAM wParam, LPARAM lParam)
+{
+// DBEVENTINFO dbei;
+ //DWORD uin;
+/*
+ if (!icqOnline) return 1;
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof(DWORD);
+ dbei.pBlob = (PBYTE)&uin;
+ if (CallService(MS_DB_EVENT_GET, wParam, (LPARAM)&dbei)) return 1;
+ if (dbei.eventType != EVENTTYPE_AUTHREQUEST) return 1;
+ if (strcmp(dbei.szModule, ICQOSCPROTONAME)) return 1;
+ if (uin <= 1) return 1;
+ icq_sendAuthGrantedServ(uin);
+*/
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqAuthDeny(WPARAM wParam, LPARAM lParam)
+{
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqBasicSearch(WPARAM wParam, LPARAM lParam)
+{
+ T("[ ] basic search\n");
+ icq.startSearch(0, 0, (char*)lParam, 0);
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSearchByEmail(WPARAM wParam, LPARAM lParam)
+{
+ T("[ ] search by e-mail\n");
+ icq.startSearch(4, 0, (char*)lParam, 0);
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSearchByName(WPARAM wParam, LPARAM lParam)
+{
+ PROTOSEARCHBYNAME *psbn = (PROTOSEARCHBYNAME*)lParam;
+
+ T("[ ] search by name\n");
+ icq.startSearch(1, 0, psbn->pszNick, 0);
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqAddToList(WPARAM wParam, LPARAM lParam)
+{
+ ICQSEARCHRESULT *isr = (ICQSEARCHRESULT *)lParam;
+ bool persistent = (wParam & PALF_TEMPORARY) == 0;
+
+ T("[ ] add user to list\n");
+ if (isr->hdr.cbSize != sizeof(ICQSEARCHRESULT) || isr->uin == icq.uin) return NULL;
+ return (int)icq.addUser(isr->uin, persistent)->hContact;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqGetInfo(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQUser *u;
+
+ T("[ ] get user info\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || icq.statusVal <= ID_STATUS_OFFLINE) return 1;
+
+ icq.getUserInfo(u, ccs->wParam & SGIF_MINIMAL);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSendMessage(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQUser *u;
+ ICQEvent *icqEvent;
+
+ T("[ ] send message\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+// uin = db_get_dw(ccs->hContact, ICQCORP_PROTONAME, "UIN", 0);
+ if (u == NULL || icq.statusVal <= ID_STATUS_OFFLINE) return 0;
+
+ icqEvent = icq.sendMessage(u, (char*)ccs->lParam);
+ return icqEvent ? icqEvent->sequence : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqRecvMessage(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT*)ccs->lParam;
+
+ T("[ ] recieve message\n");
+
+ db_unset(ccs->hContact, "CList", "Hidden");
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = protoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.cbBlob = lstrlen(pre->szMessage) + 1;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+ db_event_add(ccs->hContact, &dbei);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSendUrl(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQUser *u;
+ ICQEvent *icqEvent;
+
+ T("[ ] send url\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+// uin = db_get_dw(ccs->hContact, ICQCORP_PROTONAME, "UIN", 0);
+ if (u == NULL || icq.statusVal <= ID_STATUS_OFFLINE) return 0;
+
+ icqEvent = icq.sendUrl(u, (char*)ccs->lParam);
+ return icqEvent ? icqEvent->sequence : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqRecvUrl(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA*)lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT*)ccs->lParam;
+ char *pszDescr;
+
+ T("[ ] recieve url\n");
+
+ db_unset(ccs->hContact, "CList", "Hidden");
+ pszDescr = pre->szMessage + lstrlen(pre->szMessage) + 1;
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = protoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0);
+ dbei.eventType = EVENTTYPE_URL;
+ dbei.cbBlob = lstrlen(pre->szMessage) + lstrlen(pszDescr) + 2;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+ db_event_add(ccs->hContact, &dbei);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSetAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ T("[ ] set away msg\n");
+
+ if (lParam == NULL) return 0;
+
+ if (icq.awayMessage) delete [] icq.awayMessage;
+ icq.awayMessage = new char[strlen((char*)lParam) + 1];
+ strcpy(icq.awayMessage, (char*)lParam);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqGetAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQUser *u;
+ ICQEvent *icqEvent;
+
+ T("[ ] send get away msg\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || u->statusVal <= ID_STATUS_ONLINE) return 0;
+
+ icqEvent = icq.sendReadAwayMsg(u);
+ return icqEvent ? icqEvent->sequence : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqRecvAwayMsg(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *)ccs->lParam;
+
+ T("[ ] recieve away message\n");
+
+ ProtoBroadcastAck(protoName, ccs->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)pre->lParam, (LPARAM)pre->szMessage);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSendFile(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ char **files = (char **)ccs->lParam;
+ //HANDLE hFile;
+ ICQUser *u;
+
+ T("[ ] send file\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || u->statusVal == ID_STATUS_OFFLINE || icq.statusVal <= ID_STATUS_OFFLINE) return 0;
+
+ unsigned long filesCount, directoriesCount, filesSize = 0;
+ char filename[MAX_PATH], format[32];
+ WIN32_FIND_DATA findData;
+
+ for (filesCount=0,directoriesCount=0; files[filesCount]; filesCount++)
+ {
+ FindClose(FindFirstFile(files[filesCount], &findData));
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) directoriesCount++;
+ else filesSize += findData.nFileSizeLow;
+ }
+ filesCount -= directoriesCount;
+
+ if (directoriesCount)
+ {
+ sprintf(format, "%s, %s", filesCount == 1 ? Translate("%d file") : Translate("%d files"), directoriesCount == 1 ? Translate("%d directory") : Translate("%d directories"));
+ sprintf(filename, format, filesCount, directoriesCount);
+ }
+ else
+ {
+ if (filesCount == 1)
+ {
+ char *p = strrchr(files[0], '\\');
+ strcpy(filename, p ? p+1 : files[0]);
+ }
+ else sprintf(filename, filesCount == 1 ? Translate("%d file") : Translate("%d files"), filesCount);
+ }
+
+ return (int)icq.sendFile(u, (char*)ccs->wParam, filename, filesSize, files);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqFileAllow(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQTransfer *t = (ICQTransfer *)ccs->wParam;
+ ICQUser *u;
+
+ T("[ ] send accept file request\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || u->statusVal == ID_STATUS_OFFLINE) return 0;
+
+ t->path = _strdup((char*)ccs->lParam);
+
+ icq.acceptFile(u, t->sequence, (char*)ccs->lParam);
+ return (int)t;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqFileDeny(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQTransfer *t = (ICQTransfer *)ccs->wParam;
+ ICQUser *u;
+
+ T("[ ] send refuse file request\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || u->statusVal == ID_STATUS_OFFLINE) return 0;
+
+ icq.refuseFile(u, t->sequence, (char*)ccs->lParam);
+
+ unsigned int i;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ if (icqTransfers[i] == t)
+ {
+ delete icqTransfers[i];
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqFileCancel(WPARAM wParam, LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ ICQTransfer *t = (ICQTransfer *)ccs->wParam;
+ ICQUser *u;
+
+ T("[ ] file cancel\n");
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL || u->statusVal == ID_STATUS_OFFLINE) return 0;
+
+// icq.refuseFile(u, t->sequence, (char*)ccs->lParam);
+
+ unsigned int i;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ if (icqTransfers[i] == t)
+ {
+ delete icqTransfers[i];
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqRecvFile(WPARAM wParam, LPARAM lParam)
+{
+ DBEVENTINFO dbei;
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ PROTORECVEVENT *pre = (PROTORECVEVENT *)ccs->lParam;
+ char *szDesc, *szFile;
+
+ T("[ ] recieve file\n");
+
+ db_unset(ccs->hContact, "CList", "Hidden");
+
+ szFile = pre->szMessage + sizeof(DWORD);
+ szDesc = szFile + strlen(szFile) + 1;
+
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.szModule = protoName;
+ dbei.timestamp = pre->timestamp;
+ dbei.flags = pre->flags & (PREF_CREATEREAD ? DBEF_READ : 0);
+ dbei.eventType = EVENTTYPE_FILE;
+ dbei.cbBlob = sizeof(DWORD)+(DWORD)strlen(szFile) + (DWORD)strlen(szDesc) + 2;
+ dbei.pBlob = (PBYTE)pre->szMessage;
+ db_event_add(ccs->hContact, &dbei);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqFileResume(WPARAM wParam, LPARAM lParam)
+{
+ PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam;
+ ICQTransfer *t = (ICQTransfer *)wParam;
+
+ T("[ ] send file resume\n");
+ t->resume(pfr->action, pfr->szFilename);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static INT_PTR icqSetApparentMode(WPARAM wParam, LPARAM lParam)
+{
+/*
+ CCSDATA *ccs = (CCSDATA *)lParam;
+ int oldMode, newMode = ccs->wParam;
+ ICQUser *u;
+
+ u = icq.getUserByContact(ccs->hContact);
+ if (u == NULL) return 1;
+
+ oldMode = db_get_w(u->hContact, ICQCORP_PROTONAME, "ApparentMode", 0);
+ if (newMode == oldMode) return 1;
+
+ T("[ ] set apparent mode\n");
+
+ if (newMode == ID_STATUS_ONLINE || newMode == ID_STATUS_OFFLINE) db_set_w(u->hContact, ICQCORP_PROTONAME, "ApparentMode", (WORD)newMode);
+ else db_unset(u->hContact, ICQCORP_PROTONAME, "ApparentMode");
+
+ if (icq.statusVal <= ID_STATUS_OFFLINE) return 0;
+
+ if (oldMode != 0) icq.updateUserList(u, oldMode == ID_STATUS_OFFLINE ? 1 : 2, 0);
+ if (newMode != 0) icq.updateUserList(u, newMode == ID_STATUS_OFFLINE ? 1 : 2, 1);
+*/
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int icqContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ ICQUser *u;
+
+ T("[ ] contact deleted\n");
+
+ if ((u = icq.getUserByContact((MCONTACT)wParam)) != NULL) icq.removeUser(u);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int icqModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ HookEvent(ME_USERINFO_INITIALISE, icqUserInfoInitialise);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+char *CreateServiceName(char *serviceName, char *functionName)
+{
+ strcpy(serviceName, protoName);
+ strcat(serviceName, functionName);
+
+ return serviceName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int LoadServices()
+{
+ char serviceName[MAX_PATH + 30];
+
+ if (!icq.load()) return 1;
+
+ HookEvent(ME_DB_CONTACT_DELETED, icqContactDeleted);
+ HookEvent(ME_OPT_INITIALISE, icqOptionsInitialise);
+ HookEvent(ME_SYSTEM_MODULESLOADED, icqModulesLoaded);
+
+ CreateServiceFunction(CreateServiceName(serviceName, PS_GETCAPS), icqGetCaps);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_GETNAME), icqGetName);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_LOADICON), icqLoadIcon);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_SETSTATUS), icqSetStatus);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_GETSTATUS), icqGetStatus);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_SETAWAYMSG), icqSetAwayMsg);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_AUTHALLOW), icqAuthAllow);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_AUTHDENY), icqAuthDeny);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_BASICSEARCH), icqBasicSearch);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_SEARCHBYEMAIL), icqSearchByEmail);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_SEARCHBYNAME), icqSearchByName);
+// CreateServiceFunction(MS_ICQ_SEARCHBYDETAILS, icqSearchByDetails);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_ADDTOLIST), icqAddToList);
+// CreateServiceFunction(CreateServiceName(serviceName, PS_ADDTOLISTBYEVENT), icqAddToListByEvent);
+ CreateServiceFunction(CreateServiceName(serviceName, PS_FILERESUME), icqFileResume);
+
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_GETINFO), icqGetInfo);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_MESSAGE), icqSendMessage);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_URL), icqSendUrl);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_GETAWAYMSG), icqGetAwayMsg);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_FILE), icqSendFile);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_FILEALLOW), icqFileAllow);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_FILEDENY), icqFileDeny);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_FILECANCEL), icqFileCancel);
+ CreateServiceFunction(CreateServiceName(serviceName, PSS_SETAPPARENTMODE), icqSetApparentMode);
+
+ CreateServiceFunction(CreateServiceName(serviceName, PSR_MESSAGE), icqRecvMessage);
+ CreateServiceFunction(CreateServiceName(serviceName, PSR_URL), icqRecvUrl);
+ CreateServiceFunction(CreateServiceName(serviceName, PSR_AWAYMSG), icqRecvAwayMsg);
+ CreateServiceFunction(CreateServiceName(serviceName, PSR_FILE), icqRecvFile);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UnloadServices()
+{
+ icq.unload();
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/socket.cpp b/protocols/ICQCorp/src/socket.cpp
new file mode 100644
index 0000000000..b3516f2069
--- /dev/null
+++ b/protocols/ICQCorp/src/socket.cpp
@@ -0,0 +1,399 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Socket
+//
+///////////////////////////////////////////////////////////////////////////////
+
+Socket::Socket()
+{
+ handleVal = INVALID_SOCKET;
+ remoteIPVal = 0;
+ remotePortVal = 0;
+ localIPVal = 0;
+ localPortVal = 0;
+ messageVal = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Socket::~Socket()
+{
+ if (connected()) closeConnection();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::connected()
+{
+ return handleVal != INVALID_SOCKET;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::completed(int result)
+{
+ if (result != SOCKET_ERROR || WSAGetLastError() != WSAEWOULDBLOCK) return true;
+
+ Sleep(1);
+ return false;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Socket::openSocket()
+{
+ if (connected()) WSAAsyncSelect(handleVal, icq.hWnd, messageVal, FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Socket::closeSocket()
+{
+ if (connected()) WSAAsyncSelect(handleVal, icq.hWnd, 0, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::setDestination(unsigned long rIp, unsigned short rPort)
+{
+ char localName[128];
+
+ if (rIp == 0) return false;
+ gethostname(localName, 128);
+ localIPVal = lookup(localName);
+
+ // set up remote connection
+ remoteIPVal = rIp;
+ remotePortVal = rPort;
+ remote.sin_port = htons(rPort);
+ remote.sin_addr.s_addr = rIp;
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::setDestination(char *rHost, unsigned short rPort)
+{
+ return setDestination(lookup(rHost), rPort);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned long Socket::lookup(char *h)
+{
+ unsigned long ina;
+ struct hostent *host;
+
+ // check if the hostname is in dot and number notation
+ ina = inet_addr(h);
+ if (ina != INADDR_NONE) return ina;
+
+ // try and resolve hostname
+ if ((host = gethostbyname(h)) == NULL) return 0; // Couldn't resolve hostname/ip
+
+ // return the ip
+ return *((unsigned long *)host->h_addr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::openConnection(int Type)
+{
+ struct sockaddr_in local;
+
+ handleVal = socket(AF_INET, Type, 0);
+ if (handleVal == INVALID_SOCKET) return false;
+
+ memset(&local.sin_zero, 0, 8);
+ local.sin_family = AF_INET;
+ local.sin_port = htons(localPortVal);
+ local.sin_addr.s_addr = htonl(INADDR_ANY);
+// local.sin_addr.s_addr = htonl(localIPVal);
+
+ memset(&remote.sin_zero, 0, 8);
+ remote.sin_family = AF_INET;
+
+ bind(handleVal, (sockaddr*)&local, sizeof(sockaddr));
+
+ int sizeofSockaddr = sizeof(sockaddr);
+ getsockname(handleVal, (sockaddr*)&local, &sizeofSockaddr);
+ localPortVal = ntohs(local.sin_port);
+ if (local.sin_addr.s_addr) localIPVal = ntohl(local.sin_addr.s_addr);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Socket::closeConnection()
+{
+ if (connected())
+ {
+ closeSocket();
+ shutdown(handleVal, SD_BOTH);
+ closesocket(handleVal);
+ handleVal = INVALID_SOCKET;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::sendBuffer(char *buffer, unsigned int bufferSize)
+{
+ int result;
+
+ while (bufferSize > 0)
+ {
+ while (! completed(result = send(handleVal, buffer, bufferSize, 0)));
+ if (result <= 0)
+ {
+ closeConnection();
+ return false;
+ }
+ buffer += result;
+ bufferSize -= result;
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool Socket::receiveBuffer(char *buffer, unsigned int bufferSize)
+{
+ int result;
+
+ while (bufferSize > 0)
+ {
+ while (! completed(result = recv(handleVal, buffer, bufferSize, 0)));
+ if (result <= 0)
+ {
+ closeConnection();
+ return false;
+ }
+ buffer += result;
+ bufferSize -= result;
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// TCPSocket
+//
+///////////////////////////////////////////////////////////////////////////////
+
+TCPSocket::TCPSocket(unsigned int msg)
+{
+ messageVal = msg;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::openConnection()
+{
+ int result;
+
+ if (remoteIPVal == 0) return false;
+ if (! Socket::openConnection(SOCK_STREAM)) return false;
+
+ result = connect(handleVal, (sockaddr*)&remote, sizeof(sockaddr));
+ if (result == SOCKET_ERROR)
+ {
+ closeConnection();
+ return false;
+ }
+ openSocket();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void TCPSocket::receiveConnection(TCPSocket &newSocket)
+{
+ int sizeofSockaddr = sizeof(sockaddr);
+ newSocket.handleVal = accept(handleVal, (sockaddr*)&remote, &sizeofSockaddr);
+ newSocket.openSocket();
+
+ sizeofSockaddr = sizeof(sockaddr);
+ getpeername(newSocket.handleVal, (sockaddr*)&newSocket.remote, &sizeofSockaddr);
+
+ newSocket.remoteIPVal = newSocket.remote.sin_addr.s_addr;
+ newSocket.remotePortVal = ntohs(newSocket.remote.sin_port);
+
+ newSocket.localIPVal = localIPVal;
+ newSocket.localPortVal = localPortVal;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::startServer()
+{
+ if (! Socket::openConnection(SOCK_STREAM)) return false;
+ listen(handleVal, 10);
+ openSocket();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void TCPSocket::transferConnectionFrom(TCPSocket &from)
+{
+ handleVal = from.handleVal;
+ remoteIPVal = from.remoteIPVal;
+ remotePortVal = from.remotePortVal;
+ localIPVal = from.localIPVal;
+ localPortVal = from.localPortVal;
+
+ from.closeSocket();
+ from.handleVal = INVALID_SOCKET;
+ openSocket();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::sendPacket(Packet &p)
+{
+ return sendPacket(p, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::receivePacket(Packet &p)
+{
+ return receivePacket(p, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::sendPacket(Packet &p, bool sendSize)
+{
+ if (! connected()) return false;
+ if (sendSize)
+ {
+ char pSize[2];
+
+ pSize[0] = (p.sizeVal) & 0xFF;
+ pSize[1] = (p.sizeVal >> 8) & 0xFF;
+
+ if (! sendBuffer(pSize, 2)) return false;
+ }
+ return sendBuffer(p.buff, p.sizeVal);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool TCPSocket::receivePacket(Packet &p, bool recvSize)
+{
+ unsigned short sizeVal;
+
+ if (! connected()) return false;
+ WSAAsyncSelect(handleVal, icq.hWnd, messageVal, FD_ACCEPT|FD_CONNECT|FD_CLOSE);
+
+ p.clearPacket();
+ if (recvSize)
+ {
+ if (!receiveBuffer((char*)&sizeVal, 2) || sizeVal > p.maxSize) return false;
+ }
+ else sizeVal = 1;
+
+ if (! receiveBuffer(p.buff, sizeVal)) return false;
+ p.sizeVal = sizeVal;
+
+ WSAAsyncSelect(handleVal, icq.hWnd, messageVal, FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE);
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// UDPSocket
+//
+///////////////////////////////////////////////////////////////////////////////
+
+UDPSocket::UDPSocket(unsigned int msg)
+{
+ messageVal = msg;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool UDPSocket::openConnection()
+{
+ if (remoteIPVal == 0) return false;
+ if (! Socket::openConnection(SOCK_DGRAM)) return false;
+ openSocket();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool UDPSocket::startServer()
+{
+ if (! Socket::openConnection(SOCK_DGRAM)) return false;
+ openSocket();
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool UDPSocket::sendPacket(Packet &p)
+{
+ if (! connected()) return false;
+
+ unsigned int bytesSent = 0;
+ bytesSent = sendto(handleVal, p.buff, p.sizeVal, 0, (sockaddr*)&remote, sizeof(sockaddr));
+
+ // if unable to send anything
+ if (bytesSent != p.sizeVal)
+ {
+ closeConnection();
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool UDPSocket::receivePacket(Packet &p)
+{
+ if (! connected()) return false;
+
+ int sizeofSockaddr = sizeof(sockaddr);
+ p.clearPacket();
+ p.sizeVal = recvfrom(handleVal, p.buff, p.maxSize, 0, (sockaddr*)&remote, &sizeofSockaddr);
+
+ // it didn't manage to receive anything, there was an error, close the socket and return false
+ if (int(p.sizeVal) <= 0)
+ {
+ closeConnection();
+ return false;
+ }
+
+ // make sure the size won't overflow the buffer
+ if (p.sizeVal > p.maxSize) p.sizeVal = p.maxSize - sizeof(unsigned long);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/socket.h b/protocols/ICQCorp/src/socket.h
new file mode 100644
index 0000000000..5efd6e5df1
--- /dev/null
+++ b/protocols/ICQCorp/src/socket.h
@@ -0,0 +1,85 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 socket_h
+#define socket_h
+
+#include "packet.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Socket
+{
+public:
+ SOCKET handleVal;
+ unsigned int remoteIPVal, remotePortVal;
+ unsigned int localIPVal, localPortVal;
+ unsigned int messageVal;
+ Socket();
+ ~Socket();
+ bool connected();
+ bool completed(int result);
+ bool setDestination(unsigned long rIp, unsigned short rPort);
+ bool setDestination(char *rHost, unsigned short rPort);
+ void resetSocket();
+ unsigned long lookup(char *h);
+ bool openConnection(int Type);
+ void closeConnection();
+ virtual bool startServer() = 0;
+ virtual bool sendPacket(Packet &p) = 0;
+ virtual bool receivePacket(Packet &p) = 0;
+protected:
+ struct sockaddr_in remote;
+ void openSocket();
+ void closeSocket();
+ bool sendBuffer(char *buffer, unsigned int bufferSize);
+ bool receiveBuffer(char *buffer, unsigned int bufferSize);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class TCPSocket : public Socket
+{
+public:
+ TCPSocket(unsigned int msg);
+ bool openConnection();
+ virtual bool startServer();
+ virtual bool sendPacket(Packet &p);
+ virtual bool receivePacket(Packet &p);
+ bool sendPacket(Packet &p, bool sendSize);
+ bool receivePacket(Packet &p, bool recvSize);
+ void receiveConnection(TCPSocket &newSocket);
+ void transferConnectionFrom(TCPSocket &from);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class UDPSocket : public Socket
+{
+public:
+ UDPSocket(unsigned int msg);
+ bool openConnection();
+ virtual bool startServer();
+ virtual bool sendPacket(Packet &p);
+ virtual bool receivePacket(Packet &p);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/protocols/ICQCorp/src/stdafx.cpp b/protocols/ICQCorp/src/stdafx.cpp
new file mode 100644
index 0000000000..36e7f91d0c
--- /dev/null
+++ b/protocols/ICQCorp/src/stdafx.cpp
@@ -0,0 +1,18 @@
+/*
+Copyright (c) 2013-14 Miranda NG project (http://miranda-ng.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation version 2
+of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "corp.h"
diff --git a/protocols/ICQCorp/src/transfer.cpp b/protocols/ICQCorp/src/transfer.cpp
new file mode 100644
index 0000000000..eb1a8dbf7b
--- /dev/null
+++ b/protocols/ICQCorp/src/transfer.cpp
@@ -0,0 +1,505 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+std::vector <ICQTransfer *> icqTransfers;
+
+///////////////////////////////////////////////////////////////////////////////
+
+void WINAPI transferTimerProc(HWND hWnd, UINT Msg, UINT_PTR hTimer, DWORD Time)
+{
+ unsigned int i;
+
+ KillTimer(NULL, hTimer);
+ for (i=0; i<icqTransfers.size(); i++) if (hTimer == icqTransfers[i]->hTimer) icqTransfers[i]->process();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQTransfer::ICQTransfer(ICQUser *u, unsigned int theSequence) :
+ socket(WM_NETEVENT_TRANSFER)
+{
+ uin = u->uin;
+ hContact = u->hContact;
+ sequence = theSequence;
+ files = NULL;
+ description = NULL;
+ path = NULL;
+ sending = 0;
+ speed = 100;
+ count = 0;
+ current = -1;
+ fileName = NULL;
+ fileSize = 0;
+ fileProgress = 0;
+ totalSize = 0;
+ totalProgress = 0;
+ lastNotify = 0;
+ hTimer = NULL;
+ hFile = INVALID_HANDLE_VALUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQTransfer::~ICQTransfer()
+{
+ closeFile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::processTcpPacket(Packet &packet)
+{
+ unsigned int /*i,*/ status, junkLong;
+ //unsigned short junkShort;
+ unsigned char cmd/*, junkChar*/;
+ char *name = NULL, *directoryName = NULL;
+
+ packet >> cmd;
+ switch (cmd)
+ {
+ case 0x00:
+ T("[tcp] recieve initialising file transfer\n");
+ packet >> junkLong
+ >> count
+ >> totalSize
+ >> speed
+ >> name;
+
+ files = new char*[count + 1];
+ ZeroMemory(files, (count+1)*sizeof(char*));
+
+ ack(ACKRESULT_INITIALISING);
+ sendPacket0x01();
+ break;
+
+ case 0x01:
+ T("[tcp] ack initialising\n");
+ packet >> speed
+ >> name;
+
+ ack(ACKRESULT_INITIALISING);
+ sendPacket0x02();
+ break;
+
+ case 0x02:
+ T("[tcp] recieve next file\n");
+ packet >> directory
+ >> files[++current]
+ >> directoryName
+ >> fileSize
+ >> fileDate
+ >> speed;
+
+ if (directoryName[0])
+ {
+ char *fullName = new char[strlen(directoryName) + strlen(files[current]) + 2];
+ sprintf(fullName, "%s\\%s", directoryName, files[current]);
+ delete [] files[current];
+ files[current] = fullName;
+ }
+
+ if (directory) createDirectory();
+ else openFile();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (fileProgress) ack(ACKRESULT_FILERESUME);
+ else sendPacket0x03();
+ break;
+
+ case 0x03:
+ T("[tcp] ack next file\n");
+ packet >> fileProgress
+ >> status
+ >> speed;
+
+ totalProgress += fileProgress;
+ setFilePosition();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (status != 0)
+ {
+ totalProgress += fileSize - fileProgress;
+ fileProgress = fileSize;
+ closeFile();
+ ack(ACKRESULT_DATA);
+ }
+
+ process();
+ break;
+
+ case 0x04:
+ T("[tcp] recieve stop file\n");
+ packet >> junkLong;
+
+ totalProgress += fileSize - fileProgress;
+ fileProgress = fileSize;
+ closeFile();
+ ack(ACKRESULT_DATA);
+ break;
+
+ case 0x05:
+ T("[tcp] recieve new speed\n");
+ packet >> speed;
+ break;
+
+ case 0x06:
+ unsigned long result;
+
+ WriteFile(hFile, packet.data(), packet.dataSize(), &result, NULL);
+
+ fileProgress += result;
+ totalProgress += result;
+
+ if (fileProgress >= fileSize) closeFile();
+ ack(ACKRESULT_DATA);
+ break;
+
+ default:
+ T("[tcp] unknown packet:\n%s", packet.print());
+ packet.reset();
+ }
+
+ delete [] directoryName;
+ delete [] name;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x00()
+{
+ char nick[1] = { 0 };
+
+ sending = true;
+
+ Packet packet;
+ packet << (unsigned char)0x00
+ << (unsigned int)0x00
+ << count
+ << totalSize
+ << speed
+ << nick;
+
+ T("[tcp] send packet 0x00\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x01()
+{
+ char nick[1] = { 0 };
+
+ Packet packet;
+ packet << (unsigned char)0x01
+ << speed
+ << nick;
+
+ T("[tcp] send packet 0x01\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x02()
+{
+ char *directoryName, *p;
+
+ current++;
+ openFile();
+
+ directoryName = _strdup(fileName);
+ p = strrchr(directoryName, '\\');
+ p[0] = 0;
+ p[1] = 0;
+
+ Packet packet;
+ packet << (unsigned char)0x02
+ << directory
+ << (strrchr(fileName, '\\') + 1)
+ << (directoryName + strlen(path) + 1)
+ << fileSize
+ << fileDate
+ << speed;
+
+ T("[tcp] send packet 0x02\n");
+ socket.sendPacket(packet);
+ ack(ACKRESULT_NEXTFILE);
+
+ free(directoryName);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x03()
+{
+ Packet packet;
+ packet << (unsigned char)0x03
+ << fileProgress
+ << (unsigned int)0x00
+ << speed;
+
+ setFilePosition();
+
+ T("[tcp] send packet 0x03\n");
+ socket.sendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x04()
+{
+ T("[tcp] send packet 0x04\n");
+/*
+ icq_PacketAppend8(p, 0x04);
+ icq_PacketAppend32(p, filenum);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x05()
+{
+ T("[tcp] send packet 0x05\n");
+/*
+ icq_PacketAppend8(p, 0x05);
+ icq_PacketAppend32(p, speed);
+*/
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::sendPacket0x06()
+{
+ unsigned long result;
+
+ Packet packet;
+ packet << (unsigned char)0x06;
+
+ ReadFile(hFile, packet.data(), 2048, &result, NULL);
+ if (result == 0) return;
+ packet.add(result);
+
+// T("[tcp] send packet 0x06\n");
+ socket.sendPacket(packet);
+
+ fileProgress += result;
+ totalProgress += result;
+
+ if (fileProgress >= fileSize) closeFile();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::ack(unsigned int result)
+{
+ PROTOFILETRANSFERSTATUS fts;
+
+ if (result == ACKRESULT_DATA && GetTickCount() < lastNotify+250 && fileProgress < fileSize) return;
+
+ fts.cbSize = sizeof(fts);
+ fts.hContact = hContact;
+ //fts.sending = sending;
+ fts.pszFiles = files;
+ fts.totalFiles = count;
+ fts.currentFileNumber = current;
+ fts.totalBytes = totalSize;
+ fts.totalProgress = totalProgress;
+ fts.szWorkingDir = path;
+ fts.szCurrentFile = fileName;
+ fts.currentFileSize = fileSize;
+ fts.currentFileProgress = fileProgress;
+ fts.currentFileTime = CallService(MS_DB_TIME_TIMESTAMPTOLOCAL, fileDate, 0);
+/*
+ switch (session->status)
+ {
+ case FILE_STATUS_LISTENING: result = ACKRESULT_SENTREQUEST; break;
+ case FILE_STATUS_CONNECTED: result = ACKRESULT_CONNECTED; break;
+ case FILE_STATUS_CONNECTING: result = ACKRESULT_CONNECTING; break;
+ case FILE_STATUS_INITIALIZING: result = ACKRESULT_INITIALISING; break;
+ case FILE_STATUS_NEXT_FILE: result = ACKRESULT_NEXTFILE; break;
+ case FILE_STATUS_SENDING:
+ case FILE_STATUS_RECEIVING: result=ACKRESULT_DATA; break;
+ }
+*/
+ ProtoBroadcastAck(protoName, hContact, ACKTYPE_FILE, result, this, (LPARAM)&fts);
+ lastNotify = GetTickCount();
+
+ if (result == ACKRESULT_DATA && current >= count-1 && fileProgress >= fileSize)
+ {
+ ProtoBroadcastAck(protoName, hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, this, 0);
+ socket.closeConnection();
+
+ unsigned int i;
+ for (i=0; i<icqTransfers.size(); i++)
+ {
+ if (icqTransfers[i] == this)
+ {
+ delete icqTransfers[i];
+ icqTransfers[i] = icqTransfers[icqTransfers.size() - 1];
+ icqTransfers.pop_back();
+ break;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::process()
+{
+ unsigned int /*i, */startTime;
+
+ hTimer = NULL;
+ if (current >= count) return;
+
+ startTime = GetTickCount();
+ while (fileProgress < fileSize && GetTickCount() < startTime+100) sendPacket0x06();
+ ack(ACKRESULT_DATA);
+
+ if (fileProgress < fileSize) hTimer = SetTimer(NULL, 0, 1, (TIMERPROC)transferTimerProc);
+ else if (current < count-1) sendPacket0x02();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::resume(int action, const char *newName)
+{
+ switch (action)
+ {
+ case FILERESUME_OVERWRITE:
+ T("[ ] overwrite existing file\n");
+ fileProgress = 0;
+ break;
+
+ case FILERESUME_RESUME:
+ T("[ ] file resume\n");
+ break;
+
+ case FILERESUME_RENAME:
+ T("[ ] rename file\n");
+ delete [] fileName;
+ fileName = new char[strlen(newName) + 1];
+ strcpy(fileName, newName);
+ files[current] = fileName;
+
+ openFile();
+ fileProgress = 0;
+ break;
+
+ case FILERESUME_SKIP:
+ T("[ ] skip file\n");
+ fileProgress = fileSize;
+ break;
+ }
+
+ totalProgress += fileProgress;
+
+ sendPacket0x03();
+ ack(ACKRESULT_NEXTFILE);
+
+ if (fileProgress) ack(ACKRESULT_DATA);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::openFile()
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA findData;
+ __int64 fileTime;
+
+ if (hFile != INVALID_HANDLE_VALUE) closeFile();
+ if (path) SetCurrentDirectory(path);
+
+ fileName = files[current];
+
+ hFind = FindFirstFile(fileName, &findData);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ FindClose(hFind);
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ T("open directory %s\n", fileName);
+ directory = 1;
+ fileProgress = 0;
+ fileSize = 0;
+ fileDate = *(__int64*)(&findData.ftLastWriteTime) / 10000000 - 11644473600i64;
+ return;
+ }
+ }
+ directory = 0;
+
+ hFile = CreateFile(fileName, sending ? GENERIC_READ : GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ char msg[2048];
+
+ T("can't open file %s\n", fileName);
+ sprintf(msg, "%s\n%s", sending ? Translate("Your file transfer has been aborted because one of the files that you selected to send is no longer readable from the disk. You may have deleted or moved it.") : Translate("Your file receive has been aborted because Miranda could not open the destination file in order to write to it. You may be trying to save to a read-only folder."), fileName);
+ MessageBox(NULL, msg, Translate(protoName), MB_ICONWARNING|MB_OK);
+ return;
+ }
+
+ if (sending)
+ {
+ fileProgress = 0;
+ fileSize = GetFileSize(hFile, NULL);
+
+ GetFileTime(hFile, NULL, NULL, (LPFILETIME)&fileTime);
+ fileDate = fileTime / 10000000 - 11644473600i64;
+ }
+ else
+ {
+ fileProgress = GetFileSize(hFile, NULL);
+
+ fileTime = (11644473600i64 + (__int64)fileDate) * 10000000;
+ SetFileTime(hFile, NULL, NULL, (LPFILETIME)&fileTime);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::closeFile()
+{
+ CloseHandle(hFile);
+ hFile = INVALID_HANDLE_VALUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::setFilePosition()
+{
+ if (hFile != INVALID_HANDLE_VALUE) SetFilePointer(hFile, fileProgress, NULL, FILE_BEGIN);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQTransfer::createDirectory()
+{
+ if (path) SetCurrentDirectory(path);
+
+ fileName = files[current];
+ CreateDirectory(fileName, NULL);
+
+ fileProgress = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/transfer.h b/protocols/ICQCorp/src/transfer.h
new file mode 100644
index 0000000000..8bfed7fe4a
--- /dev/null
+++ b/protocols/ICQCorp/src/transfer.h
@@ -0,0 +1,75 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 transfer_h
+#define transfer_h
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ICQTransfer
+{
+public:
+ unsigned int uin;
+ MCONTACT hContact;
+ unsigned int sequence;
+ TCPSocket socket;
+ char **files;
+ char *description;
+ char *path;
+ unsigned char directory;
+ unsigned int sending;
+ unsigned int speed;
+ unsigned int count;
+ unsigned int current;
+ char *fileName;
+ unsigned int fileDate;
+ unsigned int fileSize;
+ unsigned int fileProgress;
+ unsigned int totalSize;
+ unsigned int totalProgress;
+ unsigned int lastNotify;
+ unsigned int hTimer;
+ HANDLE hFile;
+
+ ICQTransfer(ICQUser *u, unsigned int theSequence);
+ ~ICQTransfer();
+ void processTcpPacket(Packet &packet);
+ void sendPacket0x00();
+ void sendPacket0x01();
+ void sendPacket0x02();
+ void sendPacket0x03();
+ void sendPacket0x04();
+ void sendPacket0x05();
+ void sendPacket0x06();
+ void ack(unsigned int result);
+ void process();
+ void resume(int action, const char *newName);
+ void openFile();
+ void closeFile();
+ void setFilePosition();
+ void createDirectory();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern std::vector <ICQTransfer *> icqTransfers;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif \ No newline at end of file
diff --git a/protocols/ICQCorp/src/user.cpp b/protocols/ICQCorp/src/user.cpp
new file mode 100644
index 0000000000..c2274c7d26
--- /dev/null
+++ b/protocols/ICQCorp/src/user.cpp
@@ -0,0 +1,160 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 "corp.h"
+
+std::vector <ICQUser *> icqUsers;
+
+///////////////////////////////////////////////////////////////////////////////
+
+ICQUser::ICQUser() :
+ socket(WM_NETEVENT_USER)
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQUser::setStatus(unsigned short newStatus)
+{
+ if (statusVal == newStatus) return;
+
+ statusVal = newStatus;
+ db_set_w(hContact, protoName, "Status", newStatus);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQUser::setInfo(char *name, unsigned int data)
+{
+ if (data && data != 0xFFFFFFFF) db_set_dw(hContact, protoName, name, data);
+ else db_unset(hContact, protoName, name);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQUser::setInfo(char *name, unsigned short data)
+{
+ if (data && data != 0xFFFF) db_set_w(hContact, protoName, name, data);
+ else db_unset(hContact, protoName, name);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQUser::setInfo(char *name, unsigned char data)
+{
+ if (data && data != 0xFF) db_set_b(hContact, protoName, name, data);
+ else db_unset(hContact, protoName, name);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ICQUser::setInfo(char *name, char *data)
+{
+ if (data[0]) db_set_s(hContact, protoName, name, data);
+ else db_unset(hContact, protoName, name);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static char *iptoa(unsigned int ip)
+{
+ struct in_addr addr;
+
+ addr.S_un.S_addr = htonl(ip);
+ return inet_ntoa(addr);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void setTextValue(HWND hWnd, int id, char *value)
+{
+ bool unspecified = value == NULL;
+
+ EnableWindow(GetDlgItem(hWnd, id), !unspecified);
+ SetDlgItemText(hWnd, id, unspecified ? Translate("<not specified>") : value);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK icqUserInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LPNMHDR hdr;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hWnd);
+ return TRUE;
+
+ case WM_NOTIFY:
+ hdr = (LPNMHDR)lParam;
+ if (hdr->idFrom == 0 && hdr->code == PSN_INFOCHANGED)
+ {
+ char buffer[64];
+ unsigned long ip, port;
+ MCONTACT hContact = (MCONTACT)((LPPSHNOTIFY)lParam)->lParam;
+
+ _itoa(db_get_dw(hContact, protoName, "UIN", 0), buffer, 10);
+ setTextValue(hWnd, IDC_INFO_UIN, buffer);
+
+ ip = db_get_dw(hContact, protoName, "IP", 0);
+ setTextValue(hWnd, IDC_INFO_IP, ip ? iptoa(ip) : NULL);
+
+ ip = db_get_dw(hContact, protoName, "RealIP", 0);
+ setTextValue(hWnd, IDC_INFO_REALIP, ip ? iptoa(ip) : NULL);
+
+ port = db_get_w(hContact, protoName, "Port", 0);
+ _itoa(port, buffer, 10);
+ setTextValue(hWnd, IDC_INFO_PORT, port ? buffer : NULL);
+
+ setTextValue(hWnd, IDC_INFO_VERSION, NULL);
+ setTextValue(hWnd, IDC_INFO_MIRVER, NULL);
+ setTextValue(hWnd, IDC_INFO_PING, NULL);
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDCANCEL) SendMessage(GetParent(hWnd), msg, wParam, lParam);
+ break;
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int icqUserInfoInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ char *proto;
+
+ proto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, lParam, 0);
+ if ((proto == NULL || strcmp(proto, protoName)) && lParam) return 0;
+
+ odp.cbSize = sizeof(odp);
+ odp.position = -1900000000;
+ odp.pszTitle = Translate(protoName);
+ odp.pfnDlgProc = (DLGPROC)icqUserInfoDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_INFO_ICQCORP);
+ odp.hInstance = hInstance;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/ICQCorp/src/user.h b/protocols/ICQCorp/src/user.h
new file mode 100644
index 0000000000..9c13867237
--- /dev/null
+++ b/protocols/ICQCorp/src/user.h
@@ -0,0 +1,52 @@
+/*
+ ICQ Corporate protocol plugin for Miranda IM.
+ Copyright (C) 2003-2005 Eugene Tarasenko <zlyden13@inbox.ru>
+
+ 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 user_h
+#define user_h
+
+#include "socket.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+class ICQUser
+{
+public:
+ unsigned int uin;
+ MCONTACT hContact;
+ TCPSocket socket;
+ unsigned short statusVal;
+
+ ICQUser();
+ void setStatus(unsigned short newStatus);
+ void setInfo(char *name, unsigned int data);
+ void setInfo(char *name, unsigned short data);
+ void setInfo(char *name, unsigned char data);
+ void setInfo(char *name, char *data);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern std::vector <ICQUser *> icqUsers;
+
+extern int icqUserInfoInitialise(WPARAM wParam, LPARAM lParam);
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif \ No newline at end of file
diff --git a/protocols/ICQCorp/src/version.h b/protocols/ICQCorp/src/version.h
new file mode 100644
index 0000000000..78cd36b9cc
--- /dev/null
+++ b/protocols/ICQCorp/src/version.h
@@ -0,0 +1,14 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 0
+#define __RELEASE_NUM 1
+#define __BUILD_NUM 0
+
+#include <stdver.h>
+
+#define __PLUGIN_NAME "ICQ corporate protocol"
+#define __FILENAME "ICQCorp.dll"
+#define __DESCRIPTION "ICQ corporate protocol support for Miranda NG."
+#define __AUTHOR "Miranda NG Team, Eugene Tarasenko"
+#define __AUTHOREMAIL ""
+#define __AUTHORWEB "http://miranda-ng.org/p/ICQCorp/"
+#define __COPYRIGHT "© 2014 Miranda NG Team, 2003-2005 Eugene Tarasenko"