├── CMakeLists.txt ├── LICENSE_1_0.txt ├── README.md ├── appveyor.yml ├── include ├── AddInDefBase.h ├── ComponentBase.h ├── IMemoryManager.h ├── com.h └── types.h ├── install_prereq.bat ├── src ├── TelegramNative.cpp ├── TelegramNative.def ├── TelegramNative.h ├── dllmain.cpp ├── exports.cpp └── stdafx.h └── tools ├── docker └── linux-builder │ └── Dockerfile └── vcpkg └── ports └── tdlib ├── CONTROL ├── openssl.patch ├── portfile.cmake └── static.patch /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | project(TELEGRAM_NATIVE) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | if (UNIX) 7 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 8 | set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 9 | set(CMAKE_SHARED_LIBRARY_PREFIX "") 10 | endif () 11 | 12 | find_package(Td 1.6.1 REQUIRED) 13 | find_package(OpenSSL REQUIRED) 14 | find_package(ICU REQUIRED COMPONENTS uc dt) 15 | find_package(ZLIB REQUIRED) 16 | 17 | add_library(telegram_native SHARED 18 | src/stdafx.h 19 | src/TelegramNative.def 20 | src/TelegramNative.h 21 | src/TelegramNative.cpp 22 | src/dllmain.cpp 23 | src/exports.cpp) 24 | 25 | target_include_directories(telegram_native PRIVATE include) 26 | target_link_libraries(telegram_native PRIVATE 27 | Td::TdJsonStatic 28 | ICU::uc ICU::dt) 29 | 30 | if (MSVC) 31 | target_link_libraries(telegram_native PRIVATE 32 | OpenSSL::SSL OpenSSL::Crypto 33 | ZLIB::ZLIB) 34 | set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /DNDEBUG") 35 | set(CMAKE_CXX_FLAGS_DEBUG "/MTd") 36 | target_compile_definitions(telegram_native PRIVATE _WINDOWS) 37 | endif () 38 | -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TDLib bindings for 1C:Enterprise 2 | 3 | [![Build status](https://ci.appveyor.com/api/projects/status/2ium20h8q5moqkj8/branch/master?svg=true)](https://ci.appveyor.com/project/Infactum/telegram-native/branch/master) 4 | 5 | Cross platform native API [add-in](https://1c-dn.com/library/add_in_creation_technology/) bindings for [TDLib](https://github.com/tdlib/td) (Telegram Database library) that allows to create full featured telegram clients within 1C:Enterprise platform. 6 | 7 | ## How to use 8 | 9 | ```bsl 10 | AttachAddIn("", "Telegram", AddInType.Native); 11 | ComponentObject = New("AddIn.Telegram.TelegramNative"); 12 | ``` 13 | 14 | ## Latest builds 15 | [Windows x86](https://ci.appveyor.com/api/projects/Infactum/telegram-native/artifacts/telegram_native_x86.dll?job=Image%3A%20Visual%20Studio%202017%3B%20Environment%3A%20TARGET_PLATFORM%3Dx86) 16 | 17 | [Windows x64](https://ci.appveyor.com/api/projects/Infactum/telegram-native/artifacts/telegram_native_x64.dll?job=Image%3A%20Visual%20Studio%202017%3B%20Environment%3A%20TARGET_PLATFORM%3Dx64) 18 | 19 | [Linux x64](https://ci.appveyor.com/api/projects/Infactum/telegram-native/artifacts/telegram_native_x64.so?job=Image%3A%20Ubuntu%3B%20Environment%3A%20TARGET_PLATFORM%3Dx64) 20 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.0+{build} 2 | 3 | image: 4 | - Visual Studio 2017 5 | - Ubuntu 6 | 7 | configuration: Release 8 | 9 | platform: x64 10 | 11 | environment: 12 | APPVEYOR_SAVE_CACHE_ON_ERROR: true 13 | 14 | VCPKG_PATH: "c:\\tools\\vcpkg" 15 | NINJA_URL_WIN: "https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip" 16 | MSVC_HOME: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community" 17 | 18 | DOCKER_LOGIN: infactum 19 | DOCKER_PASSWORD: 20 | secure: wWPsUiEtw8rfnjX2/Y3/AA== 21 | DOCKER_IMAGE: infactum/telegram-native-builder 22 | 23 | matrix: 24 | - TARGET_PLATFORM: x86 25 | - TARGET_PLATFORM: x64 26 | 27 | matrix: 28 | exclude: 29 | - image: Ubuntu 30 | TARGET_PLATFORM: x86 31 | 32 | init: 33 | - ps: | 34 | If ($isLinux) { 35 | $env:APPVEYOR_CACHE_SKIP_RESTORE = "true" 36 | $env:APPVEYOR_CACHE_SKIP_SAVE = "true" 37 | } 38 | - cmd: | 39 | appveyor DownloadFile %NINJA_URL_WIN% -FileName ninja.zip 40 | 7z x ninja.zip -oC:\ninja > nul 41 | rm ninja.zip 42 | set PATH=C:\ninja;%PATH% 43 | ninja --version 44 | - cmd: | 45 | echo. >> "%VCPKG_PATH%\triplets\%TARGET_PLATFORM%-windows-static.cmake" 46 | echo set(VCPKG_BUILD_TYPE release) >> "%VCPKG_PATH%\triplets\%TARGET_PLATFORM%-windows-static.cmake" 47 | - sh: | 48 | docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD 49 | docker pull $DOCKER_IMAGE 50 | 51 | install: 52 | - cmd: | 53 | vcpkg list 54 | .\install_prereq.bat "%VCPKG_PATH%" %TARGET_PLATFORM% 55 | - sh: docker build . --cache-from $DOCKER_IMAGE -t $DOCKER_IMAGE:latest -f tools/docker/linux-builder/Dockerfile 56 | 57 | cache: 58 | - '%VCPKG_PATH%\installed\ -> install_prereq.bat, ports' 59 | 60 | build_script: 61 | - cmd: | 62 | call "%MSVC_HOME%\VC\Auxiliary\Build\vcvarsall.bat" %TARGET_PLATFORM% 63 | mkdir build 64 | cd build 65 | cmake "-DCMAKE_TOOLCHAIN_FILE=%VCPKG_PATH%\scripts\buildsystems\vcpkg.cmake" "-DVCPKG_TARGET_TRIPLET=%TARGET_PLATFORM%-windows-static" "-DCMAKE_BUILD_TYPE=%CONFIGURATION%" -GNinja .. 66 | ninja 67 | - sh: >- 68 | docker run --rm -v $(pwd):/src $DOCKER_IMAGE /bin/bash -c " 69 | mkdir build && cd build; 70 | cmake -DCMAKE_BUILD_TYPE=Release /src; 71 | cmake --build .; 72 | ldd telegram_native.so; 73 | cp telegram_native.so /src;" 74 | 75 | after_build: 76 | - sh: docker push $DOCKER_IMAGE 77 | - ps: | 78 | $prefix = "telegram_native" 79 | $suffix = If ($isLinux) {".so"} Else {".dll"} 80 | $artifact = "$($prefix)_$($env:TARGET_PLATFORM)$($suffix)" 81 | Rename-Item -Path "$prefix$suffix" -NewName "$artifact" 82 | Write-Host "Pushing artifact $artifact" 83 | Push-AppveyorArtifact $artifact 84 | 85 | on_failure: 86 | - cmd: | 87 | 7z a logs.zip "%VCPKG_PATH%\buildtrees\**\*.log" 88 | appveyor PushArtifact logs.zip 89 | -------------------------------------------------------------------------------- /include/AddInDefBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | #ifndef __ADAPTER_DEF_H__ 7 | #define __ADAPTER_DEF_H__ 8 | #include "types.h" 9 | 10 | struct IInterface 11 | { 12 | }; 13 | 14 | 15 | enum Interfaces 16 | { 17 | eIMsgBox = 0, 18 | eIPlatformInfo, 19 | 20 | #if defined(__ANDROID__) 21 | 22 | eIAndroidComponentHelper, 23 | 24 | #endif 25 | 26 | }; 27 | 28 | //////////////////////////////////////////////////////////////////////////////// 29 | /** 30 | * This class serves as representation of a platform for external 31 | * components External components use it to communicate with a platform. 32 | * 33 | */ 34 | /// Base interface for object components. 35 | class IAddInDefBase 36 | { 37 | public: 38 | virtual ~IAddInDefBase() {} 39 | /// Adds the error message 40 | /** 41 | * @param wcode - error code 42 | * @param source - source of error 43 | * @param descr - description of error 44 | * @param scode - error code (HRESULT) 45 | * @return the result of 46 | */ 47 | virtual bool ADDIN_API AddError(unsigned short wcode, const WCHAR_T* source, 48 | const WCHAR_T* descr, long scode) = 0; 49 | 50 | /// Reads a property value 51 | /** 52 | * @param wszPropName -property name 53 | * @param pVal - value being returned 54 | * @param pErrCode - error code (if any error occured) 55 | * @param errDescriptor - error description (if any error occured) 56 | * @return the result of read. 57 | */ 58 | virtual bool ADDIN_API Read(WCHAR_T* wszPropName, 59 | tVariant* pVal, 60 | long *pErrCode, 61 | WCHAR_T** errDescriptor) = 0; 62 | /// Writes a property value 63 | /** 64 | * @param wszPropName - property name 65 | * @param pVar - new property value 66 | * @return the result of write. 67 | */ 68 | virtual bool ADDIN_API Write(WCHAR_T* wszPropName, 69 | tVariant *pVar) = 0; 70 | 71 | ///Registers profile components 72 | /** 73 | * @param wszProfileName - profile name 74 | * @return the result of 75 | */ 76 | virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName) = 0; 77 | 78 | /// Changes the depth of event buffer 79 | /** 80 | * @param lDepth - new depth of event buffer 81 | * @return the result of 82 | */ 83 | virtual bool ADDIN_API SetEventBufferDepth(long lDepth) = 0; 84 | /// Returns the depth of event buffer 85 | /** 86 | * @return the depth of event buffer 87 | */ 88 | virtual long ADDIN_API GetEventBufferDepth() = 0; 89 | /// Registers external event 90 | /** 91 | * @param wszSource - source of event 92 | * @param wszMessage - event message 93 | * @param wszData - message parameters 94 | * @return the result of 95 | */ 96 | virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, 97 | WCHAR_T* wszMessage, 98 | WCHAR_T* wszData) = 0; 99 | /// Clears event buffer 100 | /** 101 | */ 102 | virtual void ADDIN_API CleanEventBuffer() = 0; 103 | 104 | /// Sets status line contents 105 | /** 106 | * @param wszStatusLine - new status line contents 107 | * @return the result of 108 | */ 109 | virtual bool ADDIN_API SetStatusLine(WCHAR_T* wszStatusLine) = 0; 110 | /// Resets the status line contents 111 | /** 112 | * @return the result of 113 | */ 114 | virtual void ADDIN_API ResetStatusLine() = 0; 115 | }; 116 | 117 | class IAddInDefBaseEx : 118 | public IAddInDefBase 119 | { 120 | public: 121 | virtual ~IAddInDefBaseEx() {} 122 | 123 | virtual IInterface* ADDIN_API GetInterface(Interfaces iface) = 0; 124 | }; 125 | 126 | struct IMsgBox : 127 | public IInterface 128 | { 129 | virtual bool ADDIN_API Confirm(const WCHAR_T* queryText, tVariant* retVal) = 0; 130 | 131 | virtual bool ADDIN_API Alert(const WCHAR_T* text) = 0; 132 | }; 133 | 134 | struct IPlatformInfo : 135 | public IInterface 136 | { 137 | enum AppType 138 | { 139 | eAppUnknown = -1, 140 | eAppThinClient = 0, 141 | eAppThickClient, 142 | eAppWebClient, 143 | eAppServer, 144 | eAppExtConn, 145 | eAppMobileClient, 146 | eAppMobileServer, 147 | }; 148 | 149 | struct AppInfo 150 | { 151 | const WCHAR_T* AppVersion; 152 | const WCHAR_T* UserAgentInformation; 153 | AppType Application; 154 | }; 155 | 156 | virtual const AppInfo* ADDIN_API GetPlatformInfo() = 0; 157 | }; 158 | 159 | #endif //__ADAPTER_DEF_H__ 160 | -------------------------------------------------------------------------------- /include/ComponentBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | 7 | #ifndef __COMPONENT_BASE_H__ 8 | #define __COMPONENT_BASE_H__ 9 | 10 | #include "types.h" 11 | //////////////////////////////////////////////////////////////////////////////// 12 | /** 13 | * The given interface is intended for initialization and 14 | * uninitialization of component and its adjustments 15 | */ 16 | /// Interface of component initialization. 17 | class IInitDoneBase 18 | { 19 | public: 20 | virtual ~IInitDoneBase() {} 21 | /// Initializes component 22 | /** 23 | * @param disp - 1C:Enterpise interface 24 | * @return the result of 25 | */ 26 | virtual bool ADDIN_API Init(void* disp) = 0; 27 | /// Sets the memory manager 28 | /* 29 | * @param mem - pointer to memory manager interface. 30 | * @return the result of 31 | */ 32 | virtual bool ADDIN_API setMemManager(void* mem) = 0; 33 | 34 | /// Returns component version 35 | /** 36 | * @return - component version (2000 - version 2) 37 | */ 38 | virtual long ADDIN_API GetInfo() = 0; 39 | 40 | /// Uninitializes component 41 | /** 42 | * Component here should release all consumed resources. 43 | */ 44 | virtual void ADDIN_API Done() = 0; 45 | 46 | }; 47 | /////////////////////////////////////////////////////////////////////////// 48 | /** 49 | * The given interface defines methods that are intented to be used by the Platform 50 | */ 51 | /// Interface describing extension of language. 52 | class ILanguageExtenderBase 53 | { 54 | public: 55 | virtual ~ILanguageExtenderBase(){} 56 | /// Registers language extension 57 | /** 58 | * @param wsExtensionName - extension name 59 | * @return the result of 60 | */ 61 | virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T** wsExtensionName) = 0; 62 | 63 | /// Returns number of component properties 64 | /** 65 | * @return number of properties 66 | */ 67 | virtual long ADDIN_API GetNProps() = 0; 68 | 69 | /// Finds property by name 70 | /** 71 | * @param wsPropName - property name 72 | * @return property index or -1, if it is not found 73 | */ 74 | virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName) = 0; 75 | 76 | /// Returns property name 77 | /** 78 | * @param lPropNum - property index (starting with 0) 79 | * @param lPropAlias - 0 - international alias, 80 | * 1 - russian alias. (International alias is required) 81 | * @return proeprty name or 0 if it is not found 82 | */ 83 | virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, 84 | long lPropAlias) = 0; 85 | 86 | /// Returns property value 87 | /** 88 | * @param lPropNum - property index (starting with 0) 89 | * @param pvarPropVal - the pointer to a variable for property value 90 | * @return the result of 91 | */ 92 | virtual bool ADDIN_API GetPropVal(const long lPropNum, 93 | tVariant* pvarPropVal) = 0; 94 | 95 | /// Sets the property value 96 | /** 97 | * @param lPropNum - property index (starting with 0) 98 | * @param varPropVal - the pointer to a variable for property value 99 | * @return the result of 100 | */ 101 | virtual bool ADDIN_API SetPropVal(const long lPropNum, 102 | tVariant* varPropVal) = 0; 103 | 104 | /// Is property readable? 105 | /** 106 | * @param lPropNum - property index (starting with 0) 107 | * @return true if property is readable 108 | */ 109 | virtual bool ADDIN_API IsPropReadable(const long lPropNum) = 0; 110 | 111 | /// Is property writable? 112 | /** 113 | * @param lPropNum - property index (starting with 0) 114 | * @return true if property is writable 115 | */ 116 | virtual bool ADDIN_API IsPropWritable(const long lPropNum) = 0; 117 | 118 | /// Returns number of component methods 119 | /** 120 | * @return number of component methods 121 | */ 122 | virtual long ADDIN_API GetNMethods() = 0; 123 | 124 | /// Finds a method by name 125 | /** 126 | * @param wsMethodName - method name 127 | * @return - method index 128 | */ 129 | virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName) = 0; 130 | 131 | /// Returns method name 132 | /** 133 | * @param lMethodNum - method index(starting with 0) 134 | * @param lMethodAlias - 0 - international alias, 135 | * 1 - russian alias. (International alias is required) 136 | * @return method name or 0 if method is not found 137 | */ 138 | virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, 139 | const long lMethodAlias) = 0; 140 | 141 | /// Returns number of method parameters 142 | /** 143 | * @param lMethodNum - method index (starting with 0) 144 | * @return number of parameters 145 | */ 146 | virtual long ADDIN_API GetNParams(const long lMethodNum) = 0; 147 | 148 | /// Returns default value of method parameter 149 | /** 150 | * @param lMethodNum - method index(starting with 0) 151 | * @param lParamNum - parameter index (starting with 0) 152 | * @param pvarParamDefValue - the pointer to a variable for default value 153 | * @return the result of 154 | */ 155 | virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, 156 | const long lParamNum, 157 | tVariant *pvarParamDefValue) = 0; 158 | 159 | /// Does the method have a return value? 160 | /** 161 | * @param lMethodNum - method index (starting with 0) 162 | * @return true if the method has a return value 163 | */ 164 | virtual bool ADDIN_API HasRetVal(const long lMethodNum) = 0; 165 | 166 | /// Calls the method as a procedure 167 | /** 168 | * @param lMethodNum - method index (starting with 0) 169 | * @param paParams - the pointer to array of method parameters 170 | * @param lSizeArray - the size of array 171 | * @return the result of 172 | */ 173 | virtual bool ADDIN_API CallAsProc(const long lMethodNum, 174 | tVariant* paParams, 175 | const long lSizeArray) = 0; 176 | 177 | /// Calls the method as a function 178 | /** 179 | * @param lMethodNum - method index (starting with 0) 180 | * @param pvarRetValue - the pointer to returned value 181 | * @param paParams - the pointer to array of method parameters 182 | * @param lSizeArray - the size of array 183 | * @return the result of 184 | */ 185 | virtual bool ADDIN_API CallAsFunc(const long lMethodNum, 186 | tVariant* pvarRetValue, 187 | tVariant* paParams, 188 | const long lSizeArray) = 0; 189 | }; 190 | /////////////////////////////////////////////////////////////////////////// 191 | /** 192 | * This interface is used to change component locale 193 | */ 194 | /// Base interface for component localization. 195 | class LocaleBase 196 | { 197 | public: 198 | virtual ~LocaleBase(){} 199 | /// Changes component locale 200 | /** 201 | * @param loc - new locale (for Windows - rus_RUS, 202 | * for Linux - ru_RU, etc...) 203 | */ 204 | virtual void ADDIN_API SetLocale(const WCHAR_T* loc) = 0; 205 | }; 206 | 207 | /////////////////////////////////////////////////////////////////////////// 208 | /** 209 | * The given interface is generalized, for its obligatory inheritance 210 | * in implementing components. 211 | */ 212 | /// Base interface describing object as a set of properties and methods. 213 | class IComponentBase : 214 | public IInitDoneBase, 215 | public ILanguageExtenderBase, 216 | public LocaleBase 217 | { 218 | public: 219 | virtual ~IComponentBase(){} 220 | }; 221 | 222 | enum AppCapabilities 223 | { 224 | eAppCapabilitiesInvalid = -1, 225 | eAppCapabilities1 = 1, 226 | eAppCapabilitiesLast = eAppCapabilities1, 227 | }; 228 | 229 | /// Announcements of exported functions 230 | /** 231 | * These functions should be implemented that component can be loaded and created. 232 | */ 233 | extern "C" long GetClassObject(const WCHAR_T*, IComponentBase** pIntf); 234 | extern "C" long DestroyObject(IComponentBase** pIntf); 235 | extern "C" const WCHAR_T* GetClassNames(); 236 | extern "C" AppCapabilities SetPlatformCapabilities(const AppCapabilities capabilities); 237 | 238 | typedef long (*GetClassObjectPtr)(const WCHAR_T* wsName, IComponentBase** pIntf); 239 | typedef long (*DestroyObjectPtr)(IComponentBase** pIntf); 240 | typedef const WCHAR_T* (*GetClassNamesPtr)(); 241 | typedef AppCapabilities (*SetPlatformCapabilitiesPtr)(const AppCapabilities capabilities); 242 | 243 | #endif //__COMPONENT_BASE_H__ 244 | -------------------------------------------------------------------------------- /include/IMemoryManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | 7 | #ifndef __IMEMORY_MANAGER_H__ 8 | #define __IMEMORY_MANAGER_H__ 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * The given class allocates and releases memory for a component 13 | */ 14 | /// Interface representing memory manager. 15 | class IMemoryManager 16 | { 17 | public: 18 | virtual ~IMemoryManager() {} 19 | /// Allocates memory of specified size 20 | /** 21 | * @param pMemory - the double pointer to variable, that will hold newly 22 | * allocated block of memory of NULL if allocation fails. 23 | * @param ulCountByte - memory size 24 | * @return the result of 25 | */ 26 | virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0; 27 | /// Releases memory 28 | /** 29 | * @param pMemory - The double pointer to the memory block being released 30 | */ 31 | virtual void ADDIN_API FreeMemory (void** pMemory) = 0; 32 | }; 33 | 34 | #endif //__IMEMORY_MANAGER_H__ 35 | -------------------------------------------------------------------------------- /include/com.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __COM_H__ 3 | #define __COM_H__ 4 | 5 | #if defined(__linux__) || defined(__APPLE__) || defined(__ANDROID__) 6 | 7 | #ifdef __ANDROID__ 8 | 9 | typedef struct { 10 | unsigned int Data1; 11 | unsigned short Data2; 12 | unsigned short Data3; 13 | unsigned char Data4[ 8 ]; 14 | } uuid_t; 15 | 16 | #else 17 | #include 18 | #endif //__ANDROID__ 19 | 20 | #ifndef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ // iOS 21 | #include 22 | #endif //!__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 23 | 24 | #pragma GCC system_header 25 | 26 | typedef long HRESULT; 27 | 28 | #ifdef __GNUC__ 29 | #define STDMETHODCALLTYPE __attribute__ ((__stdcall__)) 30 | #define DECLSPEC_NOTHROW __attribute__ ((nothrow)) 31 | #define STDMETHOD(method) virtual DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE method 32 | #else 33 | #define STDMETHODCALLTYPE 34 | #endif 35 | 36 | #define __stdcall STDMETHODCALLTYPE 37 | #define near 38 | #define far 39 | #define CONST const 40 | #define FAR far 41 | 42 | typedef unsigned long DWORD; 43 | #ifndef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ // iOS 44 | typedef int BOOL; 45 | #elif defined(__LP64__) 46 | typedef bool BOOL; 47 | #else 48 | typedef signed char BOOL; 49 | #endif //!__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 50 | 51 | typedef void VOID; 52 | typedef short SHORT; 53 | typedef unsigned char BYTE; 54 | typedef unsigned short WORD; 55 | typedef float FLOAT; 56 | typedef FLOAT *PFLOAT; 57 | typedef BOOL near *PBOOL; 58 | typedef BOOL far *LPBOOL; 59 | typedef BYTE near *PBYTE; 60 | typedef BYTE far *LPBYTE; 61 | typedef int near *PINT; 62 | typedef int far *LPINT; 63 | typedef WORD near *PWORD; 64 | typedef WORD far *LPWORD; 65 | typedef long far *LPLONG; 66 | typedef DWORD near *PDWORD; 67 | typedef DWORD far *LPDWORD; 68 | typedef void far *LPVOID; 69 | typedef CONST void far *LPCVOID; 70 | typedef wchar_t *BSTR; 71 | typedef long SCODE; 72 | typedef int INT; 73 | typedef unsigned int UINT; 74 | typedef unsigned int *PUINT; 75 | typedef wchar_t WCHAR; 76 | typedef wchar_t OLECHAR; 77 | typedef wchar_t *LPOLESTR; 78 | typedef const wchar_t *LPCOLESTR; 79 | typedef DWORD LCID; 80 | typedef PDWORD PLCID; 81 | typedef long LONG; 82 | typedef unsigned long ULONG; 83 | typedef long long LONGLONG; 84 | typedef unsigned long long ULONGLONG; 85 | typedef LONG DISPID; 86 | typedef double DOUBLE; 87 | typedef double DATE; 88 | typedef short VARIANT_BOOL; 89 | typedef void *PVOID; 90 | typedef char CHAR; 91 | typedef CONST CHAR *LPCSTR; 92 | typedef unsigned short USHORT; 93 | typedef void *HMODULE; 94 | #define OLESTR(str) L##str 95 | 96 | typedef uuid_t GUID; 97 | typedef uuid_t IID; 98 | typedef uuid_t UUID; 99 | #define REFIID const IID & 100 | #define MAX_PATH 260 101 | 102 | #define IsEqualIID(x,y) uuid_compare((x),(y)) 103 | #ifdef __GNUC__ 104 | #define LoadLibraryA(x) dlopen((x), RTLD_LAZY) 105 | #define FreeLibrary(x) dlclose((x)) 106 | #define GetProcAddress(x, y) dlsym((x), (y)) 107 | #endif //__GNUC__ 108 | 109 | #define E_FAIL 0x80004005L 110 | #define S_OK 0L 111 | #define S_FALSE 1L 112 | #define E_NOINTERFACE 0x80004002L 113 | #define E_NOTIMPL 0x80004001L 114 | #define E_INVALIDARG 0x80070057L 115 | #define E_UNEXPECTED 0x8000FFFFL 116 | #define E_OUTOFMEMORY 0x8007000EL 117 | #define DISP_E_UNKNOWNNAME 0x80020006L 118 | #define DISPID_UNKNOWN ( -1 ) 119 | #define TRUE 1 120 | #define FALSE 0 121 | 122 | typedef long ITypeInfo; 123 | 124 | #if defined (__GNUC__) && !defined (NONAMELESSUNION) 125 | __extension__ /* no named members */ 126 | #endif 127 | union tCY { 128 | __extension__ struct 129 | { 130 | unsigned long Lo; 131 | long Hi; 132 | }; 133 | long long int64; 134 | }; 135 | typedef union tagCY CY; 136 | #define CLSIDFromString(x,y) uuid_parse((x),(unsigned char*)(y)) 137 | 138 | #endif //defined(__linux__) || defined(__APPLE__) 139 | 140 | #endif //__COM_H__ 141 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CON_TYPES_H__ 3 | #define __CON_TYPES_H__ 4 | 5 | #if defined(_WINDOWS) || defined(WINAPI_FAMILY) 6 | #include 7 | #endif 8 | 9 | #if defined(WINAPI_FAMILY) 10 | #include 11 | #endif 12 | 13 | #if __GNUC__ >=3 14 | #pragma GCC system_header 15 | #endif 16 | 17 | #include "com.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define EXTERN_C extern "C" 24 | 25 | #ifdef __GNUC__ 26 | #define _ANONYMOUS_UNION __extension__ 27 | #define _ANONYMOUS_STRUCT __extension__ 28 | #else 29 | #define _ANONYMOUS_UNION 30 | #define _ANONYMOUS_STRUCT 31 | #endif //__GNUC__ 32 | 33 | #ifdef NONAMELESSUNION 34 | #define __VARIANT_NAME_1 u 35 | #define __VARIANT_NAME_2 iface 36 | #define __VARIANT_NAME_3 str 37 | #define __VARIANT_NAME_4 wstr 38 | #else 39 | #define __VARIANT_NAME_1 40 | #define __VARIANT_NAME_2 41 | #define __VARIANT_NAME_3 42 | #define __VARIANT_NAME_4 43 | #endif //NONAMELESSUNION 44 | 45 | #define RESULT_FROM_ERRNO(x) ((long)(x) <= 0 ? ((long)(x)) \ 46 | : ((long) (((x) & 0x0000FFFF) | (BASE_ERRNO << 16) | 0x80000000))) 47 | 48 | #define ADDIN_E_NONE 1000 49 | #define ADDIN_E_ORDINARY 1001 50 | #define ADDIN_E_ATTENTION 1002 51 | #define ADDIN_E_IMPORTANT 1003 52 | #define ADDIN_E_VERY_IMPORTANT 1004 53 | #define ADDIN_E_INFO 1005 54 | #define ADDIN_E_FAIL 1006 55 | #define ADDIN_E_MSGBOX_ATTENTION 1007 56 | #define ADDIN_E_MSGBOX_INFO 1008 57 | #define ADDIN_E_MSGBOX_FAIL 1009 58 | 59 | #ifndef ADDIN_API 60 | #ifdef _WINDOWS 61 | #define ADDIN_API __stdcall 62 | #else 63 | //#define ADDIN_API __attribute__ ((__stdcall__)) 64 | #define ADDIN_API 65 | #endif //_WINDOWS 66 | #endif //ADDIN_API 67 | 68 | #include 69 | 70 | #ifdef _WINDOWS 71 | #define WCHAR_T wchar_t 72 | #else 73 | #define WCHAR_T uint16_t 74 | #endif //_WINDOWS 75 | typedef unsigned short TYPEVAR; 76 | enum ENUMVAR 77 | { 78 | VTYPE_EMPTY = 0, 79 | VTYPE_NULL, 80 | VTYPE_I2, //int16_t 81 | VTYPE_I4, //int32_t 82 | VTYPE_R4, //float 83 | VTYPE_R8, //double 84 | VTYPE_DATE, //DATE (double) 85 | VTYPE_TM, //struct tm 86 | VTYPE_PSTR, //struct str string 87 | VTYPE_INTERFACE, //struct iface 88 | VTYPE_ERROR, //int32_t errCode 89 | VTYPE_BOOL, //bool 90 | VTYPE_VARIANT, //struct _tVariant * 91 | VTYPE_I1, //int8_t 92 | VTYPE_UI1, //uint8_t 93 | VTYPE_UI2, //uint16_t 94 | VTYPE_UI4, //uint32_t 95 | VTYPE_I8, //int64_t 96 | VTYPE_UI8, //uint64_t 97 | VTYPE_INT, //int Depends on architecture 98 | VTYPE_UINT, //unsigned int Depends on architecture 99 | VTYPE_HRESULT, //long hRes 100 | VTYPE_PWSTR, //struct wstr 101 | VTYPE_BLOB, //means in struct str binary data contain 102 | VTYPE_CLSID, //UUID 103 | VTYPE_STR_BLOB = 0xfff, 104 | VTYPE_VECTOR = 0x1000, 105 | VTYPE_ARRAY = 0x2000, 106 | VTYPE_BYREF = 0x4000, //Only with struct _tVariant * 107 | VTYPE_RESERVED = 0x8000, 108 | VTYPE_ILLEGAL = 0xffff, 109 | VTYPE_ILLEGALMASKED = 0xfff, 110 | VTYPE_TYPEMASK = 0xfff 111 | } ; 112 | #if defined (__GNUC__) && !defined (NONAMELESSUNION) 113 | __extension__ /* no named members */ 114 | #endif 115 | struct _tVariant 116 | { 117 | _ANONYMOUS_UNION union 118 | { 119 | int8_t i8Val; 120 | int16_t shortVal; 121 | int32_t lVal; 122 | int intVal; 123 | unsigned int uintVal; 124 | int64_t llVal; 125 | uint8_t ui8Val; 126 | uint16_t ushortVal; 127 | uint32_t ulVal; 128 | uint64_t ullVal; 129 | int32_t errCode; 130 | long hRes; 131 | float fltVal; 132 | double dblVal; 133 | bool bVal; 134 | char chVal; 135 | wchar_t wchVal; 136 | DATE date; 137 | IID IDVal; 138 | struct _tVariant *pvarVal; 139 | struct tm tmVal; 140 | _ANONYMOUS_STRUCT struct 141 | { 142 | void* pInterfaceVal; 143 | IID InterfaceID; 144 | } __VARIANT_NAME_2/*iface*/; 145 | _ANONYMOUS_STRUCT struct 146 | { 147 | char* pstrVal; 148 | uint32_t strLen; //count of bytes 149 | } __VARIANT_NAME_3/*str*/; 150 | _ANONYMOUS_STRUCT struct 151 | { 152 | WCHAR_T* pwstrVal; 153 | uint32_t wstrLen; //count of symbol 154 | } __VARIANT_NAME_4/*wstr*/; 155 | } __VARIANT_NAME_1; 156 | uint32_t cbElements; //Dimension for an one-dimensional array in pvarVal 157 | TYPEVAR vt; 158 | }; 159 | typedef struct _tVariant tVariant; 160 | typedef tVariant tVariantArg; 161 | 162 | 163 | #if defined(NONAMELESSUNION) 164 | #define TV_JOIN(X, Y) ((X)->u.Y) 165 | #else 166 | #define TV_JOIN(X, Y) ((X)->Y) 167 | #endif 168 | 169 | #define TV_VT(X) ((X)->vt) 170 | #define TV_ISBYREF(X) (TV_VT(X)&VT_BYREF) 171 | #define TV_ISARRAY(X) (TV_VT(X)&VT_ARRAY) 172 | #define TV_ISVECTOR(X) (TV_VT(X)&VT_VECTOR) 173 | #define TV_NONE(X) TV_I2(X) 174 | 175 | #define TV_UI1(X) TV_JOIN(X, ui8Val) 176 | #define TV_I2(X) TV_JOIN(X, shortVal) 177 | #define TV_I4(X) TV_JOIN(X, lVal) 178 | #define TV_I8(X) TV_JOIN(X, llVal) 179 | #define TV_R4(X) TV_JOIN(X, fltVal) 180 | #define TV_R8(X) TV_JOIN(X, dblVal) 181 | #define TV_I1(X) TV_JOIN(X, i8Val) 182 | #define TV_UI2(X) TV_JOIN(X, ushortVal) 183 | #define TV_UI4(X) TV_JOIN(X, ulVal) 184 | #define TV_UI8(X) TV_JOIN(X, ullVal) 185 | #define TV_INT(X) TV_JOIN(X, intVal) 186 | #define TV_UINT(X) TV_JOIN(X, uintVal) 187 | 188 | #ifdef _WIN64 189 | #define TV_INT_PTR(X) TV_JOIN(X, llVal) 190 | #define TV_UINT_PTR(X) TV_JOIN(X, ullVal) 191 | #else 192 | #define TV_INT_PTR(X) TV_JOIN(X, lVal) 193 | #define TV_UINT_PTR(X) TV_JOIN(X, ulVal) 194 | #endif 195 | 196 | 197 | #define TV_DATE(X) TV_JOIN(X, date) 198 | #define TV_STR(X) TV_JOIN(X, pstrVal) 199 | #define TV_WSTR(X) TV_JOIN(X, pwstrVal) 200 | #define TV_BOOL(X) TV_JOIN(X, bVal) 201 | #define TV_UNKNOWN(X) TV_JOIN(X, pInterfaceVal) 202 | #define TV_VARIANTREF(X) TV_JOIN(X, pvarVal) 203 | 204 | void tVarInit(tVariant* tvar); 205 | 206 | inline 207 | void tVarInit(tVariant* tvar) 208 | { 209 | assert(tvar != NULL); 210 | memset(tvar, 0, sizeof(tVariant)); 211 | TV_VT(tvar) = VTYPE_EMPTY; 212 | } 213 | //----------------------------------------------------------------------------// 214 | // static setter functions... 215 | 216 | #define DATA_SET_BEGIN(data_) \ 217 | tVarInit(data_); 218 | 219 | #define DATA_SET_END(data_, type_) \ 220 | TV_VT(data_) = type_; 221 | 222 | 223 | #define DATA_SET(data_, type_, member_, value_) \ 224 | DATA_SET_BEGIN(data_) \ 225 | TV_JOIN(data_, member_) = value_; \ 226 | DATA_SET_END(data_, type_) 227 | 228 | #define DATA_SET_WITH_CAST(data_, type_, member_, cast_, value_) \ 229 | DATA_SET_BEGIN(data_) \ 230 | TV_JOIN(data_, member_) = cast_ value_; \ 231 | DATA_SET_END(data_, type_) 232 | 233 | #endif //__CON_TYPES_H__ 234 | -------------------------------------------------------------------------------- /install_prereq.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set _VCPKG_PATH=%~1 4 | set _TARGET_PLATFORM=%~2 5 | set _TARGET_TRIPLET=%_TARGET_PLATFORM%-windows-static 6 | 7 | xcopy tools\vcpkg\. "%_VCPKG_PATH%\" /E 8 | vcpkg install ^ 9 | openssl:%_TARGET_TRIPLET% ^ 10 | zlib:%_TARGET_TRIPLET% ^ 11 | tdlib:%_TARGET_TRIPLET% ^ 12 | icu:%_TARGET_TRIPLET% 13 | -------------------------------------------------------------------------------- /src/TelegramNative.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "TelegramNative.h" 6 | 7 | bool TelegramNative::Init(void *connection_) { 8 | connection = static_cast(connection_); 9 | return connection != nullptr; 10 | } 11 | 12 | bool TelegramNative::setMemManager(void *memory_manager_) { 13 | memory_manager = static_cast(memory_manager_); 14 | return memory_manager != nullptr; 15 | } 16 | 17 | bool TelegramNative::RegisterExtensionAs(WCHAR_T **ext_name) { 18 | char16_t name[] = u"TelegramNative"; 19 | 20 | if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast(ext_name), sizeof(name))) { 21 | return false; 22 | }; 23 | 24 | memcpy(*ext_name, name, sizeof(name)); 25 | 26 | return true; 27 | } 28 | 29 | long TelegramNative::FindMethod(const WCHAR_T *method_name) { 30 | icu::UnicodeString lookup_name{method_name}; 31 | 32 | for (auto i = 0u; i < methods.size(); ++i) { 33 | if (methods[i].toLower() == lookup_name.toLower()) { 34 | return static_cast(i); 35 | } 36 | } 37 | 38 | for (auto i = 0u; i < methods_ru.size(); ++i) { 39 | if (methods_ru[i].toLower() == lookup_name.toLower()) { 40 | return static_cast(i); 41 | } 42 | } 43 | 44 | return -1; 45 | } 46 | 47 | const WCHAR_T *TelegramNative::GetMethodName(const long num, const long lang_alias) { 48 | if (num > LastMethod) { 49 | return nullptr; 50 | } 51 | 52 | icu::UnicodeString method_name; 53 | 54 | switch (lang_alias) { 55 | case 0: 56 | method_name = methods[num]; 57 | break; 58 | case 1: 59 | method_name = methods_ru[num]; 60 | break; 61 | default: 62 | return nullptr; 63 | } 64 | 65 | if (method_name.isEmpty()) { 66 | return nullptr; 67 | } 68 | 69 | WCHAR_T *result = nullptr; 70 | 71 | size_t bytes = (method_name.length() + 1) * sizeof(char16_t); 72 | 73 | if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast(&result), bytes)) { 74 | return nullptr; 75 | }; 76 | 77 | memcpy(result, method_name.getTerminatedBuffer(), bytes); 78 | 79 | return result; 80 | } 81 | 82 | long TelegramNative::GetNParams(const long method_num) { 83 | switch (method_num) { 84 | case TdExecute: 85 | case TdSend: 86 | case SetAsyncMode: 87 | case TdSetLogFilePath: 88 | case TdSetLogMaxFileSize: 89 | case TdSetLogVerbosityLevel: 90 | return 1; 91 | case TdReceive: 92 | default: 93 | return 0; 94 | } 95 | } 96 | 97 | bool TelegramNative::HasRetVal(const long method_num) { 98 | switch (method_num) { 99 | case TdExecute: 100 | case TdReceive: 101 | case TdSetLogFilePath: 102 | return true; 103 | case TdSend: 104 | case SetAsyncMode: 105 | case TdSetLogMaxFileSize: 106 | case TdSetLogVerbosityLevel: 107 | default: 108 | return false; 109 | } 110 | } 111 | 112 | bool TelegramNative::CallAsProc(const long method_num, tVariant *params, const long array_size) { 113 | switch (method_num) { 114 | case TdSend: { 115 | 116 | std::string command; 117 | if (!parse_param(params[0], command)) { 118 | return false; 119 | }; 120 | 121 | td_json_client_send(telegram_client, command.c_str()); 122 | 123 | return true; 124 | } 125 | 126 | case SetAsyncMode: { 127 | 128 | if (params[0].vt != VTYPE_BOOL) { 129 | return false; 130 | } 131 | 132 | if (async_mode == params[0].bVal) { 133 | return false; 134 | } 135 | 136 | async_mode = params[0].bVal; 137 | 138 | if (connection && connection->GetEventBufferDepth() < buffer_depth) { 139 | connection->SetEventBufferDepth(buffer_depth); 140 | } 141 | 142 | if (async_mode) { 143 | rcv_thread = std::thread(&TelegramNative::rcv_loop, this); 144 | } else { 145 | if (rcv_thread.joinable()) { 146 | rcv_thread.join(); 147 | } 148 | } 149 | 150 | return true; 151 | } 152 | 153 | case TdSetLogMaxFileSize: { 154 | 155 | auto max_file_size = TV_I4(¶ms[0]); 156 | td_set_log_max_file_size(max_file_size); 157 | 158 | return true; 159 | } 160 | 161 | case TdSetLogVerbosityLevel: { 162 | 163 | auto log_level = TV_I4(¶ms[0]); 164 | td_set_log_verbosity_level(log_level); 165 | 166 | return true; 167 | } 168 | 169 | default: 170 | return false; 171 | } 172 | 173 | } 174 | 175 | bool 176 | TelegramNative::CallAsFunc(const long method_num, tVariant *ret_value, tVariant *params, const long array_size) { 177 | 178 | switch (method_num) { 179 | case TdExecute: { 180 | 181 | std::string command; 182 | if (!parse_param(params[0], command)) { 183 | return false; 184 | }; 185 | 186 | icu::UnicodeString result = td_json_client_execute(telegram_client, command.c_str()); 187 | return set_wstr_val(ret_value, result); 188 | 189 | } 190 | 191 | case TdReceive: { 192 | std::lock_guard lock(rcv_mtx); 193 | icu::UnicodeString result = td_json_client_receive(telegram_client, rcv_timeout); 194 | return set_wstr_val(ret_value, result); 195 | } 196 | 197 | case TdSetLogFilePath: { 198 | 199 | std::string command; 200 | if (!parse_param(params[0], command)) { 201 | return false; 202 | }; 203 | 204 | auto success = td_set_log_file_path(command.c_str()); 205 | 206 | TV_VT(ret_value) = VTYPE_BOOL; 207 | ret_value->bVal = static_cast(success); 208 | 209 | return true; 210 | } 211 | 212 | default: 213 | return false; 214 | } 215 | 216 | } 217 | 218 | TelegramNative::TelegramNative() { 219 | 220 | props = { 221 | u"EventSourceName" 222 | }; 223 | props_ru = { 224 | u"ИмяИсточникаСобытий" 225 | }; 226 | 227 | methods = { 228 | u"Send", u"Receive", u"Execute", u"SetAsyncMode", 229 | u"SetLogFilePath", u"SetLogMaxFileSize", u"SetLogVerbosityLevel" 230 | }; 231 | methods_ru = { 232 | u"Отправить", u"Получить", u"Выполнить", u"УстановитьАсинхронныйРежим", 233 | u"УстановитьФайлЖурнала", u"УстановитьМаксимальныйРазмерФайлаЖурнала", u"УстановитьУровеньДетализацииЖурнала" 234 | }; 235 | 236 | telegram_client = td_json_client_create(); 237 | } 238 | 239 | TelegramNative::~TelegramNative() { 240 | 241 | async_mode = false; 242 | 243 | if (rcv_thread.joinable()) { 244 | rcv_thread.join(); 245 | } 246 | 247 | td_json_client_destroy(telegram_client); 248 | } 249 | 250 | bool TelegramNative::parse_param(const tVariant param, std::string &out) { 251 | switch (param.vt) { 252 | case VTYPE_PSTR: { 253 | out.assign(param.pstrVal, param.strLen); 254 | break; 255 | } 256 | case VTYPE_PWSTR: { 257 | icu::UnicodeString tmp{param.pwstrVal, static_cast(param.wstrLen)}; 258 | tmp.toUTF8String(out); 259 | break; 260 | } 261 | default: 262 | return false; 263 | } 264 | 265 | return true; 266 | } 267 | 268 | void TelegramNative::rcv_loop() { 269 | 270 | while (async_mode) { 271 | 272 | auto es_len = static_cast(event_source_name.length() + 1); 273 | auto source = new char16_t[es_len]; 274 | memcpy(source, event_source_name.getTerminatedBuffer(), sizeof(WCHAR_T) * es_len); 275 | 276 | char16_t message[] = u"Response"; 277 | 278 | std::lock_guard lock(rcv_mtx); 279 | icu::UnicodeString response = td_json_client_receive(telegram_client, rcv_timeout); 280 | 281 | if (response.isEmpty()) { 282 | continue; 283 | } 284 | 285 | auto len = static_cast(response.length() + 1); 286 | auto data = new char16_t[len]; 287 | memcpy(data, response.getTerminatedBuffer(), len * sizeof(char16_t)); 288 | 289 | connection->ExternalEvent(reinterpret_cast(source), 290 | reinterpret_cast(message), 291 | reinterpret_cast(data)); 292 | 293 | delete[] source; 294 | delete[] data; 295 | } 296 | 297 | } 298 | 299 | long TelegramNative::FindProp(const WCHAR_T *prop_name) { 300 | icu::UnicodeString lookup_name{prop_name}; 301 | 302 | for (auto i = 0u; i < props.size(); ++i) { 303 | if (props[i].toLower() == lookup_name.toLower()) { 304 | return static_cast(i); 305 | } 306 | } 307 | 308 | for (auto i = 0u; i < props_ru.size(); ++i) { 309 | if (props_ru[i].toLower() == lookup_name.toLower()) { 310 | return static_cast(i); 311 | } 312 | } 313 | 314 | return -1; 315 | } 316 | 317 | bool TelegramNative::GetPropVal(const long num, tVariant *value) { 318 | switch (num) { 319 | case EventSourceName: { 320 | return set_wstr_val(value, event_source_name); 321 | } 322 | default: 323 | return false; 324 | } 325 | } 326 | 327 | bool TelegramNative::set_wstr_val(tVariant *dest, icu::UnicodeString &src) { 328 | 329 | auto len = static_cast(src.length()); 330 | 331 | TV_VT(dest) = VTYPE_PWSTR; 332 | size_t bytes = (len + 1) * sizeof(WCHAR_T); 333 | 334 | if (!memory_manager || 335 | !memory_manager->AllocMemory(reinterpret_cast(&dest->pwstrVal), bytes)) { 336 | return false; 337 | }; 338 | 339 | memcpy(dest->pwstrVal, src.getTerminatedBuffer(), bytes); 340 | dest->wstrLen = len; 341 | 342 | return true; 343 | } 344 | 345 | bool TelegramNative::SetPropVal(const long num, tVariant *value) { 346 | 347 | switch (num) { 348 | case EventSourceName: 349 | event_source_name = icu::UnicodeString{value->pwstrVal, static_cast(value->wstrLen)}; 350 | return true; 351 | default: 352 | return false; 353 | } 354 | } 355 | 356 | const WCHAR_T *TelegramNative::GetPropName(long num, long lang_alias) { 357 | if (num > LastMethod) { 358 | return nullptr; 359 | } 360 | 361 | icu::UnicodeString prop_name; 362 | 363 | switch (lang_alias) { 364 | case 0: 365 | prop_name = props[num]; 366 | break; 367 | case 1: 368 | prop_name = props_ru[num]; 369 | break; 370 | default: 371 | return nullptr; 372 | } 373 | 374 | if (prop_name.isEmpty()) { 375 | return nullptr; 376 | } 377 | 378 | WCHAR_T *result = nullptr; 379 | 380 | size_t bytes = (prop_name.length() + 1) * sizeof(char16_t); 381 | 382 | if (!memory_manager || !memory_manager->AllocMemory(reinterpret_cast(&result), bytes)) { 383 | return nullptr; 384 | }; 385 | 386 | memcpy(result, prop_name.getTerminatedBuffer(), bytes); 387 | 388 | return result; 389 | } 390 | 391 | bool TelegramNative::IsPropReadable(const long lPropNum) { 392 | switch (lPropNum) { 393 | case EventSourceName: 394 | return true; 395 | default: 396 | return false; 397 | } 398 | } 399 | 400 | bool TelegramNative::IsPropWritable(const long lPropNum) { 401 | switch (lPropNum) { 402 | case EventSourceName: 403 | return true; 404 | default: 405 | return false; 406 | } 407 | } 408 | -------------------------------------------------------------------------------- /src/TelegramNative.def: -------------------------------------------------------------------------------- 1 | LIBRARY "telegram_native" 2 | 3 | EXPORTS 4 | GetClassObject 5 | DestroyObject 6 | GetClassNames 7 | SetPlatformCapabilities 8 | -------------------------------------------------------------------------------- /src/TelegramNative.h: -------------------------------------------------------------------------------- 1 | #ifndef __ADDIN_NATIVE_H__ 2 | #define __ADDIN_NATIVE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class TelegramNative : public IComponentBase { 14 | public: 15 | enum Props { 16 | EventSourceName = 0, 17 | LastProp 18 | }; 19 | 20 | enum Methods { 21 | TdSend = 0, 22 | TdReceive, 23 | TdExecute, 24 | SetAsyncMode, 25 | TdSetLogFilePath, 26 | TdSetLogMaxFileSize, 27 | TdSetLogVerbosityLevel, 28 | LastMethod 29 | }; 30 | 31 | TelegramNative(); 32 | 33 | ~TelegramNative() override; 34 | 35 | bool ADDIN_API Init(void *connection_) override; 36 | 37 | bool ADDIN_API setMemManager(void *memory_manager_) override; 38 | 39 | long ADDIN_API GetInfo() override { return 2000; }; 40 | 41 | void ADDIN_API Done() override {}; 42 | 43 | bool ADDIN_API RegisterExtensionAs(WCHAR_T **ext_name) override; 44 | 45 | long ADDIN_API GetNProps() override { return LastProp; }; 46 | 47 | long ADDIN_API FindProp(const WCHAR_T *prop_name) override; 48 | 49 | const WCHAR_T *ADDIN_API GetPropName(long num, long lang_alias) override; 50 | 51 | bool ADDIN_API GetPropVal(const long num, tVariant *value) override; 52 | 53 | bool ADDIN_API SetPropVal(const long num, tVariant *value) override; 54 | 55 | bool ADDIN_API IsPropReadable(const long lPropNum) override; 56 | 57 | bool ADDIN_API IsPropWritable(const long lPropNum) override; 58 | 59 | long ADDIN_API GetNMethods() override { return LastMethod; }; 60 | 61 | long ADDIN_API FindMethod(const WCHAR_T *method_name) override; 62 | 63 | const WCHAR_T *ADDIN_API GetMethodName(const long num, const long lang_alias) override; 64 | 65 | long ADDIN_API GetNParams(const long method_num) override; 66 | 67 | bool ADDIN_API GetParamDefValue(const long method_num, const long param_num, 68 | tVariant *def_value) override { return false; }; 69 | 70 | bool ADDIN_API HasRetVal(const long method_num) override; 71 | 72 | bool ADDIN_API CallAsProc(const long method_num, tVariant *params, const long array_size) override; 73 | 74 | bool ADDIN_API CallAsFunc(const long method_num, tVariant *ret_value, tVariant *params, 75 | const long array_size) override; 76 | 77 | void ADDIN_API SetLocale(const WCHAR_T *locale) override {}; 78 | 79 | private: 80 | static bool parse_param(tVariant param, std::string &out); 81 | 82 | bool set_wstr_val(tVariant *dest, icu::UnicodeString &src); 83 | 84 | IAddInDefBase *connection{nullptr}; 85 | IMemoryManager *memory_manager{nullptr}; 86 | 87 | std::vector methods; 88 | std::vector methods_ru; 89 | std::vector props; 90 | std::vector props_ru; 91 | 92 | icu::UnicodeString event_source_name{u"TelegramNative"}; 93 | long buffer_depth{100}; 94 | 95 | std::thread rcv_thread; 96 | double rcv_timeout{1.0}; 97 | 98 | void rcv_loop(); 99 | 100 | bool async_mode{false}; 101 | void *telegram_client{nullptr}; 102 | std::mutex rcv_mtx; 103 | }; 104 | 105 | #endif //__ADDIN_NATIVE_H__ 106 | -------------------------------------------------------------------------------- /src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #ifndef __linux__ 4 | 5 | BOOL APIENTRY DllMain(HMODULE hModule, 6 | DWORD ul_reason_for_call, 7 | LPVOID lpReserved 8 | ) { 9 | switch (ul_reason_for_call) { 10 | case DLL_PROCESS_ATTACH: 11 | case DLL_THREAD_ATTACH: 12 | case DLL_THREAD_DETACH: 13 | case DLL_PROCESS_DETACH: 14 | default: 15 | break; 16 | } 17 | return TRUE; 18 | } 19 | 20 | #endif //__linux__ 21 | -------------------------------------------------------------------------------- /src/exports.cpp: -------------------------------------------------------------------------------- 1 | #include "TelegramNative.h" 2 | 3 | const WCHAR_T *GetClassNames() { 4 | 5 | static char16_t cls_names[] = u"TelegramNative"; 6 | return reinterpret_cast(cls_names); 7 | 8 | } 9 | 10 | long GetClassObject(const WCHAR_T *clsName, IComponentBase **pInterface) { 11 | if (!*pInterface) { 12 | *pInterface = new TelegramNative; 13 | return (long) *pInterface; 14 | } 15 | return 0; 16 | } 17 | 18 | long DestroyObject(IComponentBase **pInterface) { 19 | if (!*pInterface) { 20 | return -1; 21 | } 22 | 23 | delete *pInterface; 24 | *pInterface = nullptr; 25 | return 0; 26 | } 27 | 28 | AppCapabilities SetPlatformCapabilities(const AppCapabilities capabilities) { 29 | return eAppCapabilitiesLast; 30 | } 31 | -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDAFX_H__ 2 | #define __STDAFX_H__ 3 | 4 | #ifndef __linux__ 5 | 6 | #include 7 | 8 | #endif //__linux__ 9 | 10 | #endif //__STDAFX_H__ 11 | -------------------------------------------------------------------------------- /tools/docker/linux-builder/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y --no-install-recommends \ 5 | build-essential git \ 6 | wget ca-certificates \ 7 | libssl-dev gperf uuid-dev \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | RUN set -xe \ 11 | && wget -O install_cmake.sh https://cmake.org/files/v3.11/cmake-3.11.1-Linux-x86_64.sh \ 12 | && chmod +x install_cmake.sh \ 13 | && ./install_cmake.sh --skip-license \ 14 | && rm install_cmake.sh 15 | 16 | RUN set -xe \ 17 | && git clone https://github.com/madler/zlib.git \ 18 | && cd zlib \ 19 | && git reset --hard v1.2.11 \ 20 | && mkdir build \ 21 | && cd build \ 22 | && cmake -DCMAKE_RELEASE_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. \ 23 | && cmake --build . --target install \ 24 | && cd / && rm -rf zlib 25 | 26 | RUN set -xe \ 27 | && git clone https://github.com/openssl/openssl.git \ 28 | && cd openssl \ 29 | && git reset --hard OpenSSL_1_1_0h \ 30 | && ./config -fPIC \ 31 | && make \ 32 | && make install_sw \ 33 | && cd / && rm -rf openssl 34 | 35 | RUN set -xe \ 36 | && wget -O icu.tar.gz https://github.com/unicode-org/icu/releases/download/release-61-2/icu4c-61_2-src.tgz \ 37 | && tar xzvf icu.tar.gz \ 38 | && cd icu/source \ 39 | && CXXFLAGS=-fPIC CFLAGS=-fPIC ./runConfigureICU Linux/gcc --enable-static \ 40 | && make install \ 41 | && cd / && rm icu.tar.gz && rm -rf icu 42 | 43 | RUN set -xe \ 44 | && git clone https://github.com/tdlib/td.git \ 45 | && cd td \ 46 | && git reset --hard c407b244a086e71773e0b9f8f64d4fb0536bc447 \ 47 | && sed -i '0,/if (NOT OPENSSL_FOUND)/s//set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")\n&/' CMakeLists.txt \ 48 | && sed -i '/add_subdirectory(benchmark)/ s/^#*/#/' CMakeLists.txt \ 49 | && mkdir build \ 50 | && cd build \ 51 | && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DZLIB_ROOT=/usr/local/lib -DOPENSSL_ROOT_DIR=/usr/local/lib -DOPENSSL_USE_STATIC_LIBS=TRUE .. \ 52 | && cmake --build . --target install \ 53 | && cd / && rm -rf td 54 | -------------------------------------------------------------------------------- /tools/vcpkg/ports/tdlib/CONTROL: -------------------------------------------------------------------------------- 1 | Source: tdlib 2 | Version: 1.6.1 3 | Description: Telegram Database library. 4 | Build-Depends: zlib, openssl -------------------------------------------------------------------------------- /tools/vcpkg/ports/tdlib/openssl.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index b8cf3b05..60a84bb8 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -774,6 +774,10 @@ target_include_directories(tdcore PUBLIC $) 37 | target_include_directories(tdsqlite SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR}) 38 | target_link_libraries(tdsqlite PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES}) 39 | + 40 | +if (NOT UNIX) 41 | + target_link_libraries(tdsqlite PUBLIC crypt32.lib) 42 | +endif() 43 | + 44 | target_compile_definitions(tdsqlite PRIVATE 45 | -DSQLITE_DEFAULT_MEMSTATUS=0 46 | -DSQLITE_OMIT_LOAD_EXTENSION 47 | diff --git a/tdnet/CMakeLists.txt b/tdnet/CMakeLists.txt 48 | index ca7e33bf..e86b33e7 100644 49 | --- a/tdnet/CMakeLists.txt 50 | +++ b/tdnet/CMakeLists.txt 51 | @@ -58,6 +58,10 @@ if (NOT EMSCRIPTEN) 52 | endif() 53 | target_link_libraries(tdnet PRIVATE ${OPENSSL_CRYPTO_LIBRARY}) 54 | 55 | +if (NOT UNIX) 56 | + target_link_libraries(tdnet PUBLIC crypt32.lib) 57 | +endif() 58 | + 59 | if (WIN32) 60 | target_link_libraries(tdnet PRIVATE Crypt32) 61 | endif() 62 | diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt 63 | index d57d93c8..00742e71 100644 64 | --- a/tdutils/CMakeLists.txt 65 | +++ b/tdutils/CMakeLists.txt 66 | @@ -302,6 +302,9 @@ target_include_directories(tdutils PUBLIC $