27#include <osl/diagnose.h>
29#include <com/sun/star/beans/PropertyValue.hpp>
30#include <com/sun/star/configuration/theDefaultProvider.hpp>
31#include <com/sun/star/container/XNameAccess.hpp>
32#include <com/sun/star/lang/XMultiServiceFactory.hpp>
47 OUString DestinationDir;
48 oslFileHandle FileHandle;
50 osl::Condition& StopCondition;
53 explicit OutData(osl::Condition& rCondition) : FileHandle(nullptr),
Offset(0), StopCondition(rCondition), curl(nullptr) {};
61 curl_easy_getinfo(out.curl, CURLINFO_EFFECTIVE_URL, &effective_url);
63 curl_off_t nDownloadSize;
64 curl_easy_getinfo(out.curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &nDownloadSize);
66 OString
aURL(effective_url);
69 sal_Int32 nLen =
aURL.getLength();
70 while( (nLen > 0) && (
'/' ==
aURL[nLen-1]) )
77 out.File = out.DestinationDir
78 + OStringToOUString(
aURL.subView(
nIndex), RTL_TEXTENCODING_UTF8);
83 const sal_Int32 openFlags = osl_File_OpenFlag_Write | osl_File_OpenFlag_Create;
86 rc = osl_openFile(out.File.pData, &out.FileHandle, openFlags);
88 if( osl_File_E_EXIST == rc && ! out.Handler->downloadTargetExists(out.File) )
90 out.StopCondition.set();
94 }
while( osl_File_E_EXIST == rc );
96 if( osl_File_E_None == rc )
97 out.Handler->downloadStarted(out.File,
static_cast<sal_Int64
>(nDownloadSize));
103getStringValue(
const uno::Reference< container::XNameAccess >& xNameAccess,
const OUString& aName)
105 OSL_ASSERT(xNameAccess->hasByName(
aName));
114 const OUString& aName)
116 OSL_ASSERT(xNameAccess->hasByName(
aName));
128 OutData *out =
static_cast < OutData *
> (
stream);
130 if(
nullptr == out->FileHandle )
133 sal_uInt64 nBytesWritten = 0;
135 if(
nullptr != out->FileHandle )
136 osl_writeFile(out->FileHandle, ptr,
size * nmemb, &nBytesWritten);
138 return static_cast<size_t>(nBytesWritten);
143progress_callback(
void *clientp, curl_off_t dltotal, curl_off_t dlnow, SAL_UNUSED_PARAMETER curl_off_t, SAL_UNUSED_PARAMETER curl_off_t)
145 OutData *out =
static_cast < OutData *
> (clientp);
149 if (out && !out->StopCondition.check())
152 if ( dltotal + out->Offset )
153 fPercent = (dlnow + out->Offset) * 100 / (dltotal + out->Offset);
159 curl_easy_getinfo(out->curl, CURLINFO_RESPONSE_CODE, &nCode);
160 if( (nCode != 302) && (nCode != 303) && (dltotal > 0) )
161 out->Handler->downloadProgressAt(
static_cast<sal_Int8>(fPercent));
174 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
175 css::configuration::theDefaultProvider::get(
m_xContext ) );
177 beans::PropertyValue aProperty;
178 aProperty.Name =
"nodepath";
179 aProperty.Value <<= OUString(
"org.openoffice.Inet/Settings");
181 uno::Sequence< uno::Any > aArgumentList{
uno::Any(aProperty) };
183 uno::Reference< container::XNameAccess > xNameAccess(
184 xConfigProvider->createInstanceWithArguments(
185 "com.sun.star.configuration.ConfigurationAccess", aArgumentList ),
186 uno::UNO_QUERY_THROW );
188 OSL_ASSERT(xNameAccess->hasByName(
"ooInetProxyType"));
189 uno::Any aValue = xNameAccess->getByName(
"ooInetProxyType");
191 sal_Int32 nProxyType = aValue.get< sal_Int32 >();
192 if( 0 != nProxyType )
213static bool curl_run(std::u16string_view rURL, OutData& out,
const OString& aProxyHost, sal_Int32 nProxyPort)
220 CURL * pCURL = curl_easy_init();
223 if(
nullptr != pCURL )
228 (void)curl_easy_setopt(pCURL, CURLOPT_URL,
aURL.getStr());
231 (void)curl_easy_setopt(pCURL, CURLOPT_FAILONERROR, 1);
234 (void)curl_easy_setopt(pCURL, CURLOPT_FOLLOWLOCATION, 1);
236#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 85)
237 (void)curl_easy_setopt(pCURL, CURLOPT_REDIR_PROTOCOLS_STR,
"https");
239 (void)curl_easy_setopt(pCURL, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
243 (void)curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, &out);
244 (void)curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, &
write_function);
247 (void)curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 0);
249 (void)curl_easy_setopt(pCURL, CURLOPT_PROGRESSDATA, &out);
252 (void)curl_easy_setopt(pCURL, CURLOPT_PROXY, aProxyHost.getStr());
253 (void)curl_easy_setopt(pCURL, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
254 if( -1 != nProxyPort )
255 (void)curl_easy_setopt(pCURL, CURLOPT_PROXYPORT, nProxyPort);
261 sal_Int64 offset =
static_cast<sal_Int64
>(out.Offset);
262 (void)curl_easy_setopt(pCURL, CURLOPT_RESUME_FROM_LARGE, offset);
265 CURLcode cc = curl_easy_perform(pCURL);
268 if(
nullptr == out.FileHandle )
273 out.Handler->downloadFinished(out.File);
277 if ( CURLE_PARTIAL_FILE == cc )
281 curl_off_t nDownloadSize;
282 curl_easy_getinfo( pCURL, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &nDownloadSize );
283 if ( -1 == nDownloadSize )
285 out.Handler->downloadFinished(out.File);
291 else if( (CURLE_ABORTED_BY_CALLBACK == cc) || out.StopCondition.check() )
297 OString aMessage(
"Unknown error");
299 const char * error_message = curl_easy_strerror(cc);
300 if(
nullptr != error_message )
301 aMessage = error_message;
303 if ( CURLE_HTTP_RETURNED_ERROR == cc )
306 curl_easy_getinfo( pCURL, CURLINFO_RESPONSE_CODE, &nError );
309 aMessage +=
" 403: Access denied!";
310 else if ( 404 == nError )
311 aMessage +=
" 404: File not found!";
312 else if ( 416 == nError )
315 out.Handler->downloadFinished(out.File);
320 aMessage +=
":error code = " + OString::number( nError ) +
" !";
324 out.Handler->downloadStalled( OStringToOUString(aMessage, RTL_TEXTENCODING_UTF8) );
327 curl_easy_cleanup(pCURL);
335Download::start(
const OUString& rURL,
const OUString& rFile,
const OUString& rDestinationDir)
340 OUString aFile( rFile );
344 if ( aFile.isEmpty() )
347 OUString
aURL( rURL );
349 sal_Int32 nLen =
aURL.getLength();
350 while( (nLen > 0) && (
'/' ==
aURL[ nLen-1 ]) )
355 aFile = rDestinationDir +
aURL.subView(
nIndex );
358 oslFileError rc = osl_openFile( aFile.pData, &out.FileHandle, osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
359 osl_closeFile(out.FileHandle);
360 out.FileHandle =
nullptr;
362 if( osl_File_E_EXIST == rc )
366 osl_removeFile( aFile.pData );
374 osl_removeFile( aFile.pData );
380 out.DestinationDir = rDestinationDir;
383 if( !aFile.isEmpty() )
385 oslFileError rc = osl_openFile(aFile.pData, &out.FileHandle, osl_File_OpenFlag_Write);
387 if( osl_File_E_None == rc )
390 if( osl_File_E_None == osl_setFilePos(out.FileHandle, osl_Pos_End, 0) )
392 osl_getFilePos(out.FileHandle, &out.Offset);
395 else if( osl_File_E_NOENT == rc )
400 sal_Int32 nProxyPort = -1;
403 bool ret =
curl_run(rURL, out, aProxyHost, nProxyPort);
405 if(
nullptr != out.FileHandle )
407 osl_syncFile(out.FileHandle);
408 osl_closeFile(out.FileHandle);
bool start(const OUString &rURL, const OUString &rFile, const OUString &rDestinationDir)
void getProxyForURL(std::u16string_view rURL, OString &rHost, sal_Int32 &rPort) const
const rtl::Reference< DownloadInteractionHandler > m_aHandler
const css::uno::Reference< css::uno::XComponentContext > & m_xContext
osl::Condition m_aCondition
Reference< XOutputStream > stream
static bool curl_run(std::u16string_view rURL, OutData &out, const OString &aProxyHost, sal_Int32 nProxyPort)
static sal_Int32 getInt32Value(const uno::Reference< container::XNameAccess > &xNameAccess, const OUString &aName)
static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, SAL_UNUSED_PARAMETER curl_off_t, SAL_UNUSED_PARAMETER curl_off_t)
static void openFile(OutData &out)
static size_t write_function(void *ptr, size_t size, size_t nmemb, void *stream)
static OString getStringValue(const uno::Reference< container::XNameAccess > &xNameAccess, const OUString &aName)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)