📜 ⬆️ ⬇️

Experience of transferring large files using a secure protocol from 1C to the site

transfer of large files using a secure protocol from 1C to the site
During the creation of the next B2B system at the 1C: Enterprise 8.2 integration stage with the web interface, it became necessary to transfer large files from 1C to the web safely.
To solve this problem, SFTP was chosen as a reliable and unlimited transfer file size.
In the embedded language 1C: Enterprise 8.2, there are no functions for transmitting data via SFTP , so I had to look for application tools. On the Internet resources devoted to programming 1C, there are examples of successful use of freeware utilities like WinSCP . To use this method, you need to run the utility from the embedded language 1C with command line parameters.

An example of running the WinCSP utility from 1C:

 = (34)+()+"\"+ "WinSCP.com"+(34)+"/script="+(34)+()+(34)+"\script.txt "+"/parameter "+(34)++(34)+" "+ (34)++(34)+" "+(34) +  + (34) + " " + (34) +  + (34); 

')
The downside of such a solution is the lack of control over startup errors and execution from the embedded language 1C. In this regard, it was decided to write an external DLL component for 1C: Enterprise 8.2.

The 1C: Enterprise platform supports two technologies for creating external components of the Native API and COM. The choice fell on the Native API, since the components created by this technology work both on the client and on the 1C server. Using materials from the ITS disk about the technology of creating external components and the open source library C ++, the file SftpExtension.dll was created (you can download the source here ).

Creating a DLL Component

1. For use in the SFTP component of the protocol, we used two libraries.
- libssh http://www.libssh2.org/ (Download “git clone git: //git.libssh2.org/libssh2.git”)
- openssl http://www.openssl.org/ (Download archive openssl-1.0.1c.tar.gz from here )
We connect libraries to the project.

2. Each component object must be inherited from the abstract class IcomponentBase and IlanguageInterface.

Part of the component code describing the possibility of calling C ++ functions from 1C in Russian:
You can use other languages.

 static wchar_t *g_MethodNames[] = { L"SendFile",L"StartSession", L"EndSession", L"IsSessionStart",L"SetSshHost",L"SetSshLogin",L"SetSshPass",L"SetSftpPath",L"SetLocalPath"}; static wchar_t *g_MethodNamesRu[] = { L"",L"",L"",L"", L"",L"",L"", L"",L""}; const WCHAR_T* SftpExtension::GetMethodName(const long lMethodNum, const long lMethodAlias) { if (lMethodNum >= eMethLast) return NULL; wchar_t *wsCurrentName = NULL; WCHAR_T *wsMethodName = NULL; int iActualSize = 0; switch(lMethodAlias) { case 0: // First language wsCurrentName = g_MethodNames[lMethodNum]; break; case 1: // Second language wsCurrentName = g_MethodNamesRu[lMethodNum]; break; default: return 0; } iActualSize = wcslen(wsCurrentName)+1; if (m_iMemory && wsCurrentName) { if(m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize); } return wsMethodName; } 


3. To call the required function from the component, use the CallAsFunc method from the IcomponentBase interface. When calling methods from 1C components, this C ++ method is called.

As parameters of the method are used:


 bool SftpExtension::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue,tVariant* paParams, const long lSizeArray){ switch(lMethodNum){ case eMethSendFile: { if (!lSizeArray || !paParams) return false; this->local_path = toChar(paParams); WriteToServer(status, this->local_path); // pvarRetValue->pstrVal = status; //status pvarRetValue->strLen = strlen(pvarRetValue->pstrVal); TV_VT(pvarRetValue) = VTYPE_PSTR; ret = true; break; } } return ret; } 


4. In our example of 1C, you can perform 4 methods that correspond to the C ++ methods in the DLL component.

1C (methods)C ++ methods
Start Session ()
Beforehand, it is necessary to define the authorization parameters (host, login, password - either rsa keys, the path on the remote server).
Therefore, the Start Session function acquires the following properties: Host, Login, Password, Remote Path
StartSSHSession (status, this-> ssh_host, this-> ssh_login, this-> ssh_pass);
StartSftpSession (status, this-> sftp_path)
Send File (“Path and file name on client machine”)
WriteToServer (const char * & status, const char * loclfile)
IfSessionStart ()isSessionStart ()
FinishSession ()endSession () - ends an SFTP session and an SSH session


5. In C ++, you need to define access parameters (read / write) to the created properties; two methods, IsPropReadable and IsPropWritable, are responsible for this.

 bool SftpExtension::IsPropReadable(const long lPropNum) { switch(lPropNum) { case ePropSshHost: return true; default: return false; } return false;} 


Table of ratios of properties 1C and C ++
1C (properties)C ++ properties
Hostssh_host
Loginssh_login
Passwordssh_pass
Remote PathSftp_path


The finished library can be downloaded here .

Work with a component in the embedded language 1C

1. We perform the connection and create an object of the external component using the standard commands of the embedded language 1C.

 ("C:\SftpExtension\SftpExtension.dll","",.Native);  = ("AddIn..SftpExtension"); 


2. Fill 4 properties of the object components Host, Login, Password, Remote Path.
 . = "192.168.0.1"; . = "root"; . = "123"; . = "/var/www/company/data/www/import/data.xml"; 


3. We open connection session
 .(); 


4. Send the file
 .("C:\data.xml"); 


5. We send the following file, with a check if the session of the connection is open.
  .()  .("C:\data2.xml");  .(); .("C:\data2.xml"); ; 


6. After sending files, close the session.
 .(); 


As a result of the execution, the file with C: \ data2.xml in /var/www/company/data/www/import/data.xml was successfully transferred.


Materials used
Literature:
Manual to create components
SFTP libraries:


Conclusion: this implementation allows to transfer files from 1C: Enterprise 8.2. large secure protocol SFTP. Plus, it is possible to transfer part of the functionality from 1C to the external component, which protects the written code and allows you to implement additional, not available 1C functionality.

Source: https://habr.com/ru/post/165441/


All Articles