[Common] add network lib

This commit is contained in:
Vladimir Gorshenkov
2021-05-13 18:43:25 +03:00
parent 8123b8d899
commit c71da950ee
19 changed files with 1800 additions and 224 deletions

View File

@ -0,0 +1,97 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include <string>
#include "../../../kernel_config.h"
namespace NSNetwork
{
namespace NSFileTransport
{
typedef void (*CFileTransporter_OnComplete)(int error);
// <return> cancel: 1, else 0
typedef int (*CFileTransporter_OnProgress)(int percent);
class CFileTransporter_private;
class KERNEL_DECL CFileTransporter
{
protected:
// создаем в зависимости от платформы
CFileTransporter_private* m_pInternal;
#ifdef _MAC
static bool m_bIsARCEnabled;
#endif
public:
CFileTransporter(std::wstring &sDownloadFileUrl, bool bDelete = true); //download constructor
CFileTransporter(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize); //upload constructor
virtual ~CFileTransporter();
void SetDownloadFilePath(const std::wstring& sPath);
std::wstring GetDownloadFilePath();
bool IsFileDownloaded();
void SetDownloadProp(std::wstring &sDownloadFileUrl, bool bDelete = true);
bool DownloadSync();
void DownloadAsync();
void SetUploadProp(std::wstring &url, unsigned char* data, const int size);
bool UploadSync();
void UploadAsync();
std::wstring& GetResponse();
void Start(int lPriority);
void Suspend();
void Resume();
void Stop();
int IsSuspended();
int IsRunned();
int GetError();
int GetPriority();
void CheckSuspend();
//events
void SetEvent_OnProgress(CFileTransporter_OnProgress);
void SetEvent_OnComplete(CFileTransporter_OnComplete);
#ifdef _MAC
static void SetARCEnabled(const bool& enabled);
static bool GetARCEnabled();
#endif
};
}
}

View File

@ -0,0 +1,177 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include "./FileTransporter_private.h"
#include "../include/FileTransporter.h"
namespace NSNetwork
{
namespace NSFileTransport
{
CFileTransporter::CFileTransporter(std::wstring &sDownloadFileUrl, bool bDelete)
{
m_pInternal = new CFileTransporter_private(sDownloadFileUrl, bDelete);
}
CFileTransporter::CFileTransporter(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_pInternal = new CFileTransporter_private(sUploadPathUrl, cData, nSize);
}
CFileTransporter::~CFileTransporter()
{
Stop();
if (NULL != m_pInternal)
delete m_pInternal;
}
void CFileTransporter::SetDownloadFilePath(const std::wstring& sPath)
{
return m_pInternal->SetDownloadFilePath(sPath);
}
std::wstring CFileTransporter::GetDownloadFilePath()
{
return m_pInternal->GetDownloadFilePath();
}
bool CFileTransporter::IsFileDownloaded()
{
return m_pInternal->IsFileDownloaded();
}
void CFileTransporter::SetDownloadProp(std::wstring &sDownloadFileUrl, bool bDelete)
{
m_pInternal->SetDownloadProp(sDownloadFileUrl, bDelete);
}
bool CFileTransporter::DownloadSync()
{
return m_pInternal->TransferSync();
}
void CFileTransporter::DownloadAsync()
{
m_pInternal->TransferAsync();
}
void CFileTransporter::SetUploadProp(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_pInternal->SetUploadProp(sUploadPathUrl, cData, nSize);
}
bool CFileTransporter::UploadSync()
{
return m_pInternal->TransferSync();
}
void CFileTransporter::UploadAsync()
{
m_pInternal->TransferAsync();
}
std::wstring& CFileTransporter::GetResponse()
{
return m_pInternal->GetResponse();
}
void CFileTransporter::Start(int lPriority)
{
return m_pInternal->Start(lPriority);
}
void CFileTransporter::Suspend()
{
return m_pInternal->Suspend();
}
void CFileTransporter::Resume()
{
return m_pInternal->Resume();
}
void CFileTransporter::Stop()
{
return m_pInternal->Stop();
}
int CFileTransporter::IsSuspended()
{
return m_pInternal->IsSuspended();
}
int CFileTransporter::IsRunned()
{
return m_pInternal->IsRunned();
}
int CFileTransporter::GetError()
{
return m_pInternal->GetError();
}
int CFileTransporter::GetPriority()
{
return m_pInternal->GetPriority();
}
void CFileTransporter::CheckSuspend()
{
return m_pInternal->CheckSuspend();
}
void CFileTransporter::SetEvent_OnProgress(CFileTransporter_OnProgress func)
{
m_pInternal->GetInternal()->m_func_onProgress = func;
}
void CFileTransporter::SetEvent_OnComplete(CFileTransporter_OnComplete func)
{
m_pInternal->GetInternal()->m_func_onComplete = func;
}
#ifdef _MAC
bool CFileTransporter::m_bIsARCEnabled = false;
void CFileTransporter::SetARCEnabled(const bool& enabled)
{
m_bIsARCEnabled = enabled;
}
bool CFileTransporter::GetARCEnabled()
{
return m_bIsARCEnabled;
}
#endif
}
}

View File

@ -0,0 +1,243 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "FileTransporter_private.h"
#include <iostream>
#include <unistd.h>
#include "../../DesktopEditor/common/Directory.h"
#ifndef USE_EXTERNAL_TRANSPORT
#include <fcntl.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include <stdio.h>
#else
#include "transport_external.h"
#endif
namespace NSNetwork
{
namespace NSFileTransport
{
class CFileTransporterBaseCURL : public CFileTransporterBase
{
public :
CFileTransporterBaseCURL(std::wstring &sDownloadFileUrl, bool bDelete = true)
: CFileTransporterBase(sDownloadFileUrl, bDelete)
{
}
CFileTransporterBaseCURL(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
: CFileTransporterBase(sUploadPathUrl, cData, nSize)
{
}
virtual ~CFileTransporterBaseCURL()
{
if (m_bDelete && !m_sFilePath.empty())
{
std::string sFilePath = U_TO_UTF8(m_sFilePath);
unlink(sFilePath.c_str());
}
}
#ifndef USE_EXTERNAL_TRANSPORT
static size_t write_data(void *ptr, size_t size, size_t nmemb, int fd) {
size_t written = write(fd, ptr, size * nmemb);
return written;
}
static size_t write_data_to_string(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
virtual int DownloadFile()
{
CURL *curl;
int fp;
CURLcode res;
std::string sUrl = U_TO_UTF8(m_sFileUrl);
std::string sOut;
const char *url = sUrl.c_str();
curl = curl_easy_init();
if (curl)
{
fp = createUniqueTempFile(sOut);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
#if defined(__linux__)
//в linux нет встроенных в систему корневых сертификатов, поэтому отключаем проверку
//http://curl.haxx.se/docs/sslcerts.html
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
/* tell libcurl to follow redirection(default false) */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* some servers don't like requests that are made without a user-agent field, so we provide one */
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
close(fp);
}
m_bComplete = (CURLE_OK == res);
if (m_bComplete)
{
if (m_sFilePath.empty())
m_sFilePath = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)sOut.c_str(), sOut.length());
else
NSFile::CFileBinary::Move(UTF8_TO_U(sOut), m_sFilePath);
}
//int nRes = execl("/usr/bin/wget", stringWstingToUtf8String (m_sFileUrl).c_str(), "-P", stringWstingToUtf8String (m_sFilePath).c_str(), (char *)NULL);
//m_bComplete = nRes >= 0;
return m_bComplete ? 0 : 1;
}
virtual int UploadFile()
{
CURL *curl;
CURLcode res;
std::string sUrl = U_TO_UTF8(m_sUploadUrl);
const char *url = sUrl.c_str();
struct curl_slist *headerlist = NULL;
std::string readBuffer;
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
headerlist = curl_slist_append(headerlist, "Content-Type: application/octet-stream");
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_HEADER, true);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, url);
/* Now specify the POST data */
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, m_nSize);
/* binary data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, m_cData);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_to_string);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
#if defined(__linux__)
//в linux нет встроенных в систему корневых сертификатов, поэтому отключаем проверку
//http://curl.haxx.se/docs/sslcerts.html
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
long http_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (res == CURLE_OK)
{
if (http_code == 200 || http_code == 1223)
{
size_t startLenghtPos = readBuffer.find("Content-Length:") + sizeof("Content-Length:");
size_t endLenghtPos = readBuffer.substr(startLenghtPos, readBuffer.length()).find("\r");
std::string dataSize = readBuffer.substr(startLenghtPos, endLenghtPos);
readBuffer = readBuffer.substr(readBuffer.length() - std::stoi(dataSize));
NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)readBuffer.c_str(), (LONG)readBuffer.length(), m_sResponse);
}
else
{
res = CURLE_HTTP_RETURNED_ERROR;
}
}
/* always cleanup */
curl_easy_cleanup(curl);
}
m_bComplete = (CURLE_OK == res);
return m_bComplete ? 0 : 1;
}
protected:
int createUniqueTempFile (std::string &filename)
{
std::string sTempPath = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(NSDirectory::GetTempPath());
sTempPath += "/fileXXXXXX";
int fd = mkstemp(const_cast <char *> (sTempPath.c_str()));
if (-1 != fd)
filename = sTempPath;
return fd;
}
#else
virtual int DownloadFile() override
{
if (m_sFilePath.empty())
{
m_sFilePath = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSDirectory::GetTempPath(), L"DW");
if (NSFile::CFileBinary::Exists(m_sFilePath))
NSFile::CFileBinary::Remove(m_sFilePath);
}
return download_external(m_sDownloadFileUrl, m_sFilePath);
}
virtual int UploadFile() override
{
if (!m_sUploadPathUrl.empty() && m_cData != NULL && m_nSize != 0)
{
return upload_external(m_sUploadPathUrl, m_cData, m_nSize);
}
else return -1;
}
#endif
};
CFileTransporter_private::CFileTransporter_private(std::wstring &sDownloadFileUrl, bool bDelete)
{
m_pInternal = new CFileTransporterBaseCURL(sDownloadFileUrl, bDelete);
}
CFileTransporter_private::CFileTransporter_private(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_pInternal = new CFileTransporterBaseCURL(sUploadPathUrl, cData, nSize);
}
}
}

View File

@ -0,0 +1,136 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "FileTransporter_private.h"
#include "FileTransporter.h"
#ifdef USE_EXTERNAL_DOWNLOAD
#include "transport_external.h"
#endif
#if _IOS
#import <Foundation/Foundation.h>
#else
#include <Cocoa/Cocoa.h>
#endif
namespace NSNetwork
{
namespace NSFileTransport
{
static NSString* StringWToNSString ( const std::wstring& Str )
{
NSString* pString = [ [ NSString alloc ]
initWithBytes : (char*)Str.data()
length : Str.size() * sizeof(wchar_t)
encoding : CFStringConvertEncodingToNSStringEncoding ( kCFStringEncodingUTF32LE ) ];
return pString;
}
class CFileTransporterBaseCocoa : public CFileTransporterBase
{
public :
CFileTransporterBaseCocoa(std::wstring sFileUrl, bool bDelete = true)
: CFileTransporterBase(sFileUrl, bDelete)
{
}
virtual ~CFileTransporterBaseCocoa()
{
}
virtual int DownloadFile()
{
if (m_sFilePath.empty())
{
m_sFilePath = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"DWD");
if (NSFile::CFileBinary::Exists(m_sFilePath))
NSFile::CFileBinary::Remove(m_sFilePath);
}
#ifdef USE_EXTERNAL_DOWNLOAD
int nExternalTransport = Transport_external(m_sFileUrl, m_sFilePath);
if (0 == nExternalTransport)
return 0;
#endif
NSString* stringURL = StringWToNSString(m_sFileUrl);
NSString *escapedURL = [stringURL stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:escapedURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = StringWToNSString ( m_sFilePath );
[urlData writeToFile:filePath atomically:YES];
#if defined(_IOS)
return 0;
#else
#ifndef _ASC_USE_ARC_
if (!CFileTransporter::GetARCEnabled())
{
[stringURL release];
//[url release];
[urlData release];
}
#endif
#endif
return 0;
}
#if defined(_IOS)
return 1;
#else
#ifndef _ASC_USE_ARC_
if (!CFileTransporter::GetARCEnabled())
{
[stringURL release];
//[url release];
}
#endif
#endif
return 1;
}
};
CFileTransporter_private::CFileTransporter_private(std::wstring sFileUrl, bool bDelete)
{
m_pInternal = new CFileTransporterBaseCocoa(sFileUrl, bDelete);
}
CFileTransporter_private::CFileTransporter_private(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_pInternal = new CFileTransporterBaseCocoa(sUploadPathUrl, cData, nSize);
}
}
}

View File

@ -0,0 +1,199 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include "../../../../DesktopEditor/common/File.h"
#include "../../../../DesktopEditor/graphics/BaseThread.h"
#include "../include/FileTransporter.h"
namespace NSNetwork
{
namespace NSFileTransport
{
class CFileTransporterBase
{
public :
CFileTransporterBase(std::wstring &sDownloadFileUrl, bool bDelete)
{
m_sFilePath = L"";
m_sDownloadFileUrl = sDownloadFileUrl;
m_bComplete = false;
m_bDelete = bDelete;
m_bIsUpload = false;
m_sUploadPathUrl = L"";
m_cData = NULL;
m_nSize = 0;
m_sResponse = L"";
m_func_onComplete = NULL;
m_func_onProgress = NULL;
}
CFileTransporterBase(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_sFilePath = L"";
m_sDownloadFileUrl = L"";
m_bComplete = false;
m_bDelete = true;
m_bIsUpload = true;
m_sUploadPathUrl = sUploadPathUrl;
m_cData = cData;
m_nSize = nSize;
m_sResponse = L"";
m_func_onComplete = NULL;
m_func_onProgress = NULL;
}
virtual ~CFileTransporterBase ()
{
if ( m_sFilePath.length() > 0 && m_bDelete )
{
NSFile::CFileBinary::Remove(m_sFilePath);
m_sFilePath = L"";
}
}
virtual int DownloadFile() = 0;
virtual int UploadFile() = 0;
public:
std::wstring m_sFilePath; // Путь к сохраненному файлу на диске
std::wstring m_sDownloadFileUrl; // Ссылка на скачивание файла
bool m_bComplete; // Закачался файл или нет
bool m_bDelete; // Удалять ли файл в деструкторе
bool m_bIsUpload; // Если хотим выгрузку данных
std::wstring m_sUploadPathUrl; // URL для выгрузки данных
unsigned char* m_cData; // Данные в сыром виде
int m_nSize; // Размер данных
std::wstring m_sResponse; // Ответ сервера
CFileTransporter_OnComplete m_func_onComplete;
CFileTransporter_OnProgress m_func_onProgress;
};
class CFileTransporter_private : public NSThreads::CBaseThread
{
protected:
// создаем в зависимости от платформы
CFileTransporterBase* m_pInternal;
public:
CFileTransporterBase* GetInternal()
{
return m_pInternal;
}
public:
CFileTransporter_private(std::wstring &sDownloadFileUrl, bool bDelete = true);
CFileTransporter_private(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize);
virtual ~CFileTransporter_private()
{
Stop();
if (NULL != m_pInternal)
delete m_pInternal;
}
void SetDownloadProp(std::wstring &sDownloadFileUrl, bool bDelete = true)
{
m_pInternal->m_sDownloadFileUrl = sDownloadFileUrl;
m_pInternal->m_bDelete = bDelete;
m_pInternal->m_bIsUpload = false;
}
void SetDownloadFilePath(const std::wstring& sPath)
{
m_pInternal->m_sFilePath = sPath;
}
std::wstring GetDownloadFilePath()
{
return m_pInternal->m_sFilePath;
}
bool IsFileDownloaded()
{
return m_pInternal->m_bComplete;
}
void SetUploadProp(std::wstring &sDownloadFileUrl, unsigned char* cData, const int nSize)
{
m_pInternal->m_sUploadPathUrl = sDownloadFileUrl;
m_pInternal->m_cData = cData;
m_pInternal->m_nSize = nSize;
m_pInternal->m_bIsUpload = true;
}
std::wstring& GetResponse()
{
return m_pInternal->m_sResponse;
}
bool TransferSync()
{
this->Start( 1 );
while ( this->IsRunned() )
{
NSThreads::Sleep( 10 );
}
return IsFileDownloaded();
}
void TransferAsync()
{
this->Start( 1 );
}
protected :
virtual DWORD ThreadProc ()
{
m_pInternal->m_bComplete = false;
int hrResultAll = m_pInternal->m_bIsUpload?m_pInternal->UploadFile():m_pInternal->DownloadFile();
if (0 == hrResultAll)
m_pInternal->m_bComplete = true;
if (m_pInternal->m_func_onComplete)
m_pInternal->m_func_onComplete(hrResultAll);
m_bRunThread = FALSE;
return 0;
}
};
}
}

View File

@ -0,0 +1,424 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "FileTransporter_private.h"
#include <wininet.h>
#pragma comment(lib, "Wininet")
#pragma comment(lib, "Ole32.lib")
//------------------------------------------------------------------------------------------------------
// Константа для максимального числа символов в строке
#define MAX_SIZE 256
// Константа для максимального числа загружаемых байт
#define DOWNLOAD_FILE_SIZE 32768
#define MAX_SINGLE_DOWNLOAD_FILE_SIZE 524288
// Константа для получения размера файла
#define CONTENT_RANGE L"bytes 0-0/"
// Константа для колличества символов у CONTENT_RANGE
#define CONTENT_RANGE_SIZE ( 11/*sizeof ( CONTENT_RANGE )*/ - 1 )
namespace NSNetwork
{
namespace NSFileTransport
{
class CFileTransporterBaseWin : public CFileTransporterBase
{
public :
CFileTransporterBaseWin(std::wstring &sDownloadFileUrl, bool bDelete = true) :
CFileTransporterBase(sDownloadFileUrl, bDelete)
{
m_pFile = NULL;
}
CFileTransporterBaseWin(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize) :
CFileTransporterBase(sUploadPathUrl, cData, nSize)
{
m_pFile = NULL;
}
virtual ~CFileTransporterBaseWin()
{
if ( m_pFile )
{
::fclose( m_pFile );
m_pFile = NULL;
}
}
virtual int DownloadFile() override
{
CoInitialize ( NULL );
if ( /*S_OK != _DownloadFile ( m_sFileUrl )*/TRUE )
{
HRESULT hrResultAll = DownloadFileAll(m_sDownloadFileUrl, m_sFilePath);
if (S_OK != hrResultAll)
{
hrResultAll = (true == DownloadFilePS(m_sDownloadFileUrl, m_sFilePath)) ? S_OK : S_FALSE;
CoUninitialize ();
return hrResultAll;
}
}
CoUninitialize ();
m_bComplete = true;
return S_OK;
}
virtual int UploadFile() override
{
//stub
return S_OK;
}
protected:
FILE *m_pFile; // Хэндл на временный файл
unsigned int _DownloadFile(std::wstring sFileUrl)
{
// Проверяем состояние соединения
if ( FALSE == InternetGetConnectedState ( 0, 0 ) )
return S_FALSE;
wchar_t sTempPath[MAX_PATH], sTempFile[MAX_PATH];
if ( 0 == GetTempPathW( MAX_PATH, sTempPath ) )
return S_FALSE;
if ( 0 == GetTempFileNameW( sTempPath, L"CSS", 0, sTempFile ) )
return S_FALSE;
m_pFile = ::_wfopen( sTempFile, L"wb" );
if ( !m_pFile )
return S_FALSE;
m_sFilePath = std::wstring( sTempFile );
// Открываем сессию
HINTERNET hInternetSession = InternetOpenW ( L"Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
if ( NULL == hInternetSession )
return S_FALSE;
// Заголовок запроса ( пока содержит 0 байт ( необходимо для проверки ) )
std::wstring sHTTPHdr = L"Range: bytes=0-0";
// Открываем ссылку для проверки на ее существование, а также на возможность чтения частями
HINTERNET hInternetOpenURL = InternetOpenUrlW ( hInternetSession, sFileUrl.c_str(), sHTTPHdr.c_str(), -1, INTERNET_FLAG_RESYNCHRONIZE, 0 );
if ( NULL != hInternetOpenURL )
{
// Открытие произошло, проверяем ответ
if ( TRUE == QueryStatusCode ( hInternetOpenURL, TRUE ) )
{
// Запрос прошел удачно, проверяем возможность чтения частями и получаем размер данных
LONGLONG nFileSize = IsAccept_Ranges ( hInternetOpenURL );
// Закрываем хендл
InternetCloseHandle ( hInternetOpenURL );
if ( -1 == nFileSize )
{
// Чтение частями недоступно
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
// Закрываем файл (сделается на DownloadAll)
// Попробуем записать его целиком
return S_FALSE;
}
else
{
// Чтение частями доступно
LONGLONG nStartByte = 0;
while ( true )
{
// Если закачали весь файл - то выходим
if ( nStartByte == nFileSize - 1 )
{
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
return S_OK;
}
LONGLONG nEndByte = nStartByte + DOWNLOAD_FILE_SIZE;
// Если файл заканчивается, то загружаем меньшее колличество байт ( на 1 меньше, чем размер, т.к. начинается с 0 )
if ( nEndByte >= nFileSize )
nEndByte = nFileSize - 1;
// Буффер для закачки
BYTE arrBuffer [ DOWNLOAD_FILE_SIZE ] = { 0 };
DWORD dwBytesDownload = DownloadFilePath ( hInternetSession, arrBuffer, nStartByte, nEndByte, sFileUrl );
nStartByte = nEndByte;
if ( -1 == dwBytesDownload )
{
// Ничего не прочиталось - это плохо!!!!
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
// Закрываем файл (сделается на DownloadAll)
// Попробуем записать его целиком
return S_FALSE;
}
// Пишем в файл
::fwrite( (BYTE*)arrBuffer, 1, dwBytesDownload, m_pFile );
::fflush( m_pFile );
NSThreads::Sleep(10);
}
}
}
else
{
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
// Закрываем файл (сделается на DownloadAll)
// Попробуем записать его целиком
return S_FALSE;
}
}
else
{
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
// Закрываем файл (сделается на DownloadAll)
// Попробуем записать его целиком
return S_FALSE;
}
// Закрываем хендл соединения
InternetCloseHandle ( hInternetSession );
return S_OK;
}
DWORD DownloadFilePath ( HINTERNET hInternet, LPBYTE pBuffer, LONGLONG nStartByte, LONGLONG nEndByte, std::wstring sFileURL )
{
// Неоткрытая сессия
if ( NULL == hInternet )
return -1;
// Пришли непонятные параметры
if ( nStartByte > nEndByte || !pBuffer )
return -1;
// Заголовок запроса ( содержит nEndByte - nStartByte байт )
std::wstring sHTTPHdr = L"Range: bytes=" + std::to_wstring(nStartByte) + L"-" + std::to_wstring(nEndByte);
// Открываем ссылку для закачки
HINTERNET hInternetOpenURL = InternetOpenUrlW ( hInternet, sFileURL.c_str(), sHTTPHdr.c_str(), -1, INTERNET_FLAG_RESYNCHRONIZE, 0 );
if ( NULL == hInternetOpenURL )
return -1;
// Открытие произошло, проверяем ответ
if ( FALSE == QueryStatusCode ( hInternetOpenURL, TRUE ) )
{
// Закрываем хендл соединения
InternetCloseHandle ( hInternetOpenURL );
return -1;
}
// Какое колличество байт прочитано
DWORD dwBytesRead = 0;
// Читаем файл
if ( FALSE == InternetReadFile ( hInternetOpenURL, pBuffer, DOWNLOAD_FILE_SIZE, &dwBytesRead ) )
{
// Закрываем хендл соединения
InternetCloseHandle ( hInternetOpenURL );
return -1;
}
// Закрываем хендл соединения
InternetCloseHandle ( hInternetOpenURL );
return dwBytesRead;
}
BOOL QueryStatusCode ( HINTERNET hInternet, BOOL bIsRanges )
{
// Зачем проверять у неоткрытой сессии что-то
if ( NULL == hInternet )
return FALSE;
// Результат ответа
INT nResult = 0;
// Размер данных ответа ( должно быть = 4 )
DWORD dwLengthDataSize = 4;
// Делаем запрос, если не проходит - то возвращаем FALSE
if ( FALSE == HttpQueryInfo ( hInternet, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &nResult, &dwLengthDataSize, NULL ) )
return FALSE;
// Запрос прошел, теперь проверяем код ответа
if ( HTTP_STATUS_NOT_FOUND == nResult )
{
// Объект не найден, плохая ссылка или что-то еще
return FALSE;
}
else if ( ( HTTP_STATUS_OK != nResult && FALSE == bIsRanges ) || ( HTTP_STATUS_PARTIAL_CONTENT != nResult && TRUE == bIsRanges ) )
{
// Запрос не прошел по какой-то причине
return FALSE;
}
// Все отлично, запрос прошел
return TRUE;
}
// Проверяет, доступно ли для ресурса чтение частями и возвращает -1 если не доступно и размер данных, если доступно
LONGLONG IsAccept_Ranges ( HINTERNET hInternet )
{
// Зачем проверять у неоткрытой сессии что-то
if ( NULL == hInternet )
return -1;
// Результат ответа
wchar_t arrResult [ MAX_SIZE ] = { 0 };
// Размер данных ответа
DWORD dwLengthDataSize = sizeof ( arrResult );
// Делаем запрос, если не проходит - то возвращаем FALSE
if ( FALSE == HttpQueryInfoW ( hInternet, HTTP_QUERY_CONTENT_RANGE, &arrResult, &dwLengthDataSize, NULL ) )
{
// Получаем последнюю ошибку
DWORD dwLastError = GetLastError ();
if ( dwLastError == ERROR_HTTP_HEADER_NOT_FOUND )
{
// Не пришел заголовок, значит ресурс не поддерживает чтение частями
return -1;
}
// Возникла какая-то другая ошибка - возвращаем FALSE
return -1;
}
// Если размер 0, то заголовка нет
if ( 0 >= dwLengthDataSize )
return -1;
// Приведем к std::wstring
std::wstring strResult ( arrResult );
// Содержит размер данных
LONGLONG nFileSize = 0;
try
{
// Ищем индекс размера данных в строке
INT nStartIndex = (INT)strResult.find ( CONTENT_RANGE );
if ( -1 == nStartIndex )
return -1;
// Оставляем в строке только размер данных
strResult = strResult.substr( nStartIndex + CONTENT_RANGE_SIZE );
// Теперь получим размер данных, переводя стринг в LONGLONG
nFileSize = _wtoi64 ( strResult.c_str() );
// Т.к. реально нумерация с 0 ( поэтому добавляем еще 1 байт )
if ( 0 < nFileSize )
nFileSize += 1;
}
catch ( ... )
{
// не нашли возвращаем ошибку
return -1;
}
// Все отлично, ресурс поддерживает чтение частями, возвращаем размер
return nFileSize;
}
HRESULT DownloadFileAll(std::wstring sFileURL, std::wstring strFileOutput)
{
if ( m_pFile )
{
::fclose( m_pFile );
m_pFile = NULL;
}
// Скачиваем файл
return URLDownloadToFileW (NULL, sFileURL.c_str(), strFileOutput.c_str(), NULL, NULL);
}
bool DownloadFilePS(const std::wstring& sFileURL, const std::wstring& strFileOutput)
{
STARTUPINFO sturtupinfo;
ZeroMemory(&sturtupinfo,sizeof(STARTUPINFO));
sturtupinfo.cb = sizeof(STARTUPINFO);
std::wstring sFileDst = strFileOutput;
size_t posn = 0;
while (std::wstring::npos != (posn = sFileDst.find('\\', posn)))
{
sFileDst.replace(posn, 1, L"/");
posn += 1;
}
std::wstring sApp = L"powershell.exe c \"(new-object System.Net.WebClient).DownloadFile('" + sFileURL + L"','" + sFileDst + L"')\"";
wchar_t* pCommandLine = new wchar_t[sApp.length() + 1];
memcpy(pCommandLine, sApp.c_str(), sApp.length() * sizeof(wchar_t));
pCommandLine[sApp.length()] = (wchar_t)'\0';
HANDLE ghJob = CreateJobObject(NULL, NULL);
if (ghJob)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
// Configure all child processes associated with the job to terminate when the
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if ( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
{
CloseHandle(ghJob);
ghJob = NULL;
}
}
PROCESS_INFORMATION processinfo;
ZeroMemory(&processinfo,sizeof(PROCESS_INFORMATION));
BOOL bResult = CreateProcessW(NULL, pCommandLine, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &sturtupinfo, &processinfo);
if (bResult && ghJob)
{
AssignProcessToJobObject(ghJob, processinfo.hProcess);
}
::WaitForSingleObject(processinfo.hProcess, INFINITE);
RELEASEARRAYOBJECTS(pCommandLine);
return NSFile::CFileBinary::Exists(sFileDst);
}
};
CFileTransporter_private::CFileTransporter_private(std::wstring &sDownloadFileUrl, bool bDelete)
{
m_pInternal = new CFileTransporterBaseWin(sDownloadFileUrl, bDelete);
}
CFileTransporter_private::CFileTransporter_private(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
m_pInternal = new CFileTransporterBaseWin(sUploadPathUrl, cData, nSize);
}
}
}

View File

@ -0,0 +1,168 @@
/*
* (c) Copyright Ascensio System SIA 2010-2021
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include <iostream>
#include <unistd.h>
#include "../../DesktopEditor/common/Directory.h"
#ifdef USE_EXTERNAL_TRANSPORT
#include <unistd.h>
#include <sys/wait.h>
namespace NSNetwork
{
namespace NSFileTransport
{
std::string wget_url_validate(const std::string& url)
{
std::string::size_type pos = 0;
const char* url_ptr = url.c_str();
while ('-' == *url_ptr++) // '\0' => break
++pos;
if (*url_ptr == '\0')
return "";
return url.substr(pos);
}
int download_external(const std::wstring& sUrl, const std::wstring& sOutput)
{
int nReturnCode = -1;
std::string sUrlA = U_TO_UTF8(sUrl);
//sUrlA =("\"" + sUrlA + "\"");
std::string sOutputA = U_TO_UTF8(sOutput);
//sOutputA =("\"" + sOutputA + "\"");
if (0 != nReturnCode && NSFile::CFileBinary::Exists(L"/usr/bin/curl"))
{
pid_t pid = fork(); // create child process
int status;
switch (pid)
{
case -1: // error
break;
case 0: // child process
{
const char* nargs[10];
nargs[0] = "/usr/bin/curl";
nargs[1] = "--url";
nargs[2] = sUrlA.c_str();
nargs[3] = "--output";
nargs[4] = sOutputA.c_str();
nargs[5] = "--silent";
nargs[6] = "-L";
nargs[7] = "--connect-timeout";
nargs[8] = "10";
nargs[9] = NULL;
const char* nenv[3];
nenv[0] = "LD_PRELOAD=";
nenv[1] = "LD_LIBRARY_PATH=";
nenv[2] = NULL;
execve("/usr/bin/curl", (char * const *)nargs, (char * const *)nenv);
exit(EXIT_SUCCESS);
break;
}
default: // parent process, pid now contains the child pid
while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
if (WIFEXITED(status))
{
nReturnCode = WEXITSTATUS(status);
}
break;
}
}
if (0 != nReturnCode && NSFile::CFileBinary::Exists(L"/usr/bin/wget"))
{
std::string sUrlValidateA = wget_url_validate(sUrlA);
pid_t pid = fork(); // create child process
int status;
switch (pid)
{
case -1: // error
break;
case 0: // child process
{
const char* nargs[8];
nargs[0] = "/usr/bin/wget";
nargs[1] = sUrlValidateA.c_str();
nargs[2] = "-O";
nargs[3] = sOutputA.c_str();
nargs[4] = "-q";
nargs[5] = "--connect-timeout=10";
nargs[6] = "--tries=2";
nargs[7] = NULL;
const char* nenv[2];
nenv[0] = "LD_PRELOAD=";
nenv[1] = NULL;
execve("/usr/bin/wget", (char * const *)nargs, (char * const *)nenv);
exit(EXIT_SUCCESS);
break;
}
default: // parent process, pid now contains the child pid
while (-1 == waitpid(pid, &status, 0)); // wait for child to complete
if (WIFEXITED(status))
{
nReturnCode = WEXITSTATUS(status);
}
break;
}
}
if (0 == nReturnCode)
{
if (!NSFile::CFileBinary::Exists(sOutput))
nReturnCode = -1;
}
return nReturnCode;
}
int upload_external(std::wstring &sUploadPathUrl, unsigned char* cData, const int nSize)
{
//stub
return -1;
}
}
}
#endif