29#include <rtl/ustrbuf.hxx>
30#include <com/sun/star/ucb/OpenMode.hpp>
47OUString encodePathSegment(OUString
const & decoded) {
48 return rtl::Uri::encode(
49 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
50 RTL_TEXTENCODING_UTF8);
53OUString decodePathSegment(OUString
const & encoded) {
54 return rtl::Uri::decode(
55 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
60MemoryContainer::MemoryContainer()
79 sal_uInt32 nLen =
size*nmemb;
80 sal_uInt32 tmp(nLen + m_nWritePos);
85 }
while(m_nLen < tmp);
118 m_aUsername(r.m_aUsername),
119 m_bShowPassword(r.m_bShowPassword),
122 m_aPathSegmentVec(r.m_aPathSegmentVec)
131 m_aUsername(
"anonymous"),
132 m_bShowPassword(false),
146 OUString aPassword, urlRest;
148 if(url.getLength() < 6 || !url.startsWithIgnoreAsciiCase(
"ftp://", &urlRest))
153 sal_Int32 nIdx = urlRest.indexOf(
'/');
161 aExpr = urlRest.copy(0, nIdx);
162 urlRest = urlRest.copy(nIdx + 1);
165 sal_Int32 l = aExpr.indexOf(
'@');
170 aExpr = aExpr.copy(0,l);
171 l = aExpr.indexOf(
':');
173 aPassword = aExpr.copy(1+l);
174 if(!aPassword.isEmpty())
180 else if(!aExpr.isEmpty())
185 sal_Int32 ipv6Back =
m_aHost.lastIndexOf(
']');
186 if((ipv6Back == -1 && l != -1)
188 (ipv6Back != -1 && 1+ipv6Back == l)
197 while(!urlRest.isEmpty())
199 nIdx = urlRest.indexOf(
'/');
208 segment = urlRest.copy(0, nIdx);
209 urlRest = urlRest.copy(nIdx + 1);
213 else if( segment ==
"." )
246 OUStringBuffer bff(
"ftp://");
251 OUString aPassword,aAccount;
259 !aPassword.isEmpty() )
260 bff.append(
":" + aPassword);
267 bff.append(
":" +
m_aPort +
"/");
277 if(!bff.isEmpty() && bff[bff.getLength()-1] !=
'/')
281 return bff.makeStringAndClear();
287 OUStringBuffer bff(
"ftp://");
292 OUString aPassword,aAccount;
300 bff.append(
":" + aPassword);
308 bff.append(
":" +
m_aPort +
"/");
324 else if (
last ==
".." )
325 bff.append(
last +
"/..");
328 return bff.makeStringAndClear();
354 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
362#define SET_CONTROL_CONTAINER \
363 MemoryContainer control; \
364 (void)curl_easy_setopt(curl, \
365 CURLOPT_HEADERFUNCTION, \
367 (void)curl_easy_setopt(curl, \
368 CURLOPT_WRITEHEADER, \
374 OString urlParAscii(url.getStr(),
376 RTL_TEXTENCODING_UTF8);
377 (void)curl_easy_setopt(curl,
379 urlParAscii.getStr());
390 OUString url(
ident(
false,
true));
393 oslFileHandle res(
nullptr );
394 if ( osl_createTempFile(
nullptr, &res,
nullptr ) == osl_File_E_None )
396 (void)curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,
file_write);
397 (void)curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
399 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
400 CURLcode
err = curl_easy_perform(curl);
404 oslFileError rc = osl_setFilePos( res, osl_Pos_Absolut, 0 );
406 "osl_setFilePos failed");
426 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
false);
428 (void)curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,
memory_write);
429 (void)curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data);
431 OUString url(
ident(
true,
true));
433 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
435 CURLcode
err = curl_easy_perform(curl);
442 char* fwd =
static_cast<char*
>(data.
m_pBuffer);
446 OS osKind(FTP_UNKNOWN);
447 std::vector<FTPDirentry> resvec;
450 OUString viewurl(
ident(
true,
false));
480 if( osKind !=
int(FTP_UNKNOWN) && aDirEntry.
m_aName !=
".." && aDirEntry.
m_aName !=
"." ) {
481 aDirEntry.
m_aURL = viewurl + encodePathSegment(aDirEntry.
m_aName);
485 case OpenMode::DOCUMENTS:
487 resvec.push_back(aDirEntry);
489 case OpenMode::FOLDERS:
491 resvec.push_back(aDirEntry);
494 resvec.push_back(aDirEntry);
510 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
511 struct curl_slist *slist =
nullptr;
513 slist = curl_slist_append(slist,
"PWD");
514 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
521 OUString url(
ident(
false,
true));
523 if(try_more && !url.endsWith(
"/"))
525 else if(!try_more && url.endsWith(
"/"))
526 url = url.copy(0,url.getLength()-1);
529 err = curl_easy_perform(curl);
531 if(
err == CURLE_OK) {
532 char* fwd =
static_cast<char*
>(control.m_pBuffer);
533 sal_uInt32 len = control.m_nWritePos;
535 aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8);
540 sal_Int32 index1 = aNetTitle.lastIndexOf(
"257");
541 index1 = aNetTitle.indexOf(
'"', index1 + std::strlen(
"257")) + 1;
542 sal_Int32 index2 = aNetTitle.indexOf(
'"', index1);
543 aNetTitle = index2 > index1
544 ? aNetTitle.copy(index1, index2 - index1) : OUString();
545 if( aNetTitle !=
"/" ) {
546 index1 = aNetTitle.lastIndexOf(
'/');
547 aNetTitle = aNetTitle.copy(1+index1);
550 }
else if(
err == CURLE_BAD_PASSWORD_ENTERED)
554#if LIBCURL_VERSION_NUM>=0x070d01
555 else if(
err == CURLE_LOGIN_DENIED)
560 else if(try_more &&
err == CURLE_FTP_ACCESS_DENIED) {
579 curl_slist_free_all(slist);
590 if( nettitle ==
"/" || nettitle ==
".." )
597 if( nettitle !=
"/" ) {
601 std::vector<FTPDirentry> aList =
aURL.list(OpenMode::ALL);
604 if(
d.m_aName == nettitle) {
616 static size_t memory_read(
void *ptr,
size_t size,
size_t nmemb,
void *stream)
618 sal_Int32 nRequested = sal_Int32(
size*nmemb);
621 return size_t(curlInput->
read(
static_cast<sal_Int8*
>(ptr),nRequested));
631 if(!replaceExisting) {
642 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
false);
643 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
644 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
645 (void)curl_easy_setopt(curl,CURLOPT_READFUNCTION,
memory_read);
646 (void)curl_easy_setopt(curl,CURLOPT_READDATA,
stream);
647 (void)curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
649 OUString url(
ident(
false,
true));
652 CURLcode
err = curl_easy_perform(curl);
653 (void)curl_easy_setopt(curl, CURLOPT_UPLOAD,
false);
665 titleOU = decodePathSegment(titleOU);
666 title = OString(titleOU.getStr(),
668 RTL_TEXTENCODING_UTF8);
672 title = OString(
"/");
674 OString aDel =
"del " + title;
675 OString mkd =
"mkd " + title;
677 struct curl_slist *slist =
nullptr;
680 if(!ReplaceExisting) {
685 slist = curl_slist_append(slist,aDel.getStr());
687 slist = curl_slist_append(slist,mkd.getStr());
691 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
692 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
695 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
697 OUString url(
parent(
true));
698 if(!url.endsWith(
"/"))
702 CURLcode
err = curl_easy_perform(curl);
703 curl_slist_free_all(slist);
715 OString renamefrom =
"RNFR " +
717 RTL_TEXTENCODING_UTF8);
719 OString renameto =
"RNTO " +
721 RTL_TEXTENCODING_UTF8);
723 struct curl_slist *slist =
nullptr;
724 slist = curl_slist_append(slist,renamefrom.getStr());
725 slist = curl_slist_append(slist,renameto.getStr());
726 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
729 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
730 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
732 OUString url(
parent(
true));
733 if(!url.endsWith(
"/"))
737 CURLcode
err = curl_easy_perform(curl);
738 curl_slist_free_all(slist);
751 OString dele(aDirentry.
m_aName.getStr(),
753 RTL_TEXTENCODING_UTF8);
756 std::vector<FTPDirentry> vec =
list(sal_Int16(OpenMode::ALL));
765 dele =
"RMD " + dele;
768 dele =
"DELE " + dele;
774 struct curl_slist *slist =
nullptr;
775 slist = curl_slist_append(slist,dele.getStr());
776 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
779 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
780 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
782 OUString url(
parent(
true));
783 if(!url.endsWith(
"/"))
787 CURLcode
err = curl_easy_perform(curl);
788 curl_slist_free_all(slist);
void forHost(std::u16string_view host, std::u16string_view port, std::u16string_view username, OUString &password, OUString &account)
host is in the form host:port.
bool setHost(const OUString &host, const OUString &port, const OUString &username, const OUString &password, const OUString &account)
static bool parseDOS(FTPDirentry &rEntry, const char *pBuffer)
static bool parseUNIX(FTPDirentry &rEntry, const char *pBuffer)
static bool parseVMS(FTPDirentry &rEntry, const char *pBuffer)
OUString net_title() const
void insert(bool ReplaceExisting, void *stream) const
void parse(const OUString &url)
OUString parent(bool internal=false) const
returns the parent url.
FTPDirentry direntry() const
OUString child() const
returns the unencoded title
std::vector< FTPDirentry > list(sal_Int16 nMode) const
std::vector< OUString > m_aPathSegmentVec
Contains the encoded pathsegments of the url.
OUString ren(const OUString &NewTitle)
OUString ident(bool withslash, bool internal) const
This returns the URL, but cleaned from unnecessary ellipses.
void mkdir(bool ReplaceExisting) const
FTPURL(const OUString &aIdent, FTPContentProvider *pFCP)
FTPContentProvider * m_pFCP
int append(const void *pBuffer, size_t size, size_t nmemb) noexcept
sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1]
Reference< XOutputStream > stream
int file_write(void *buffer, size_t size, size_t nmemb, void *stream)
callback for curl_easy_perform(), forwarding the written content to the stream.
#define SET_CONTROL_CONTAINER
static size_t memory_read(void *ptr, size_t size, size_t nmemb, void *stream)
static void setCurlUrl(CURL *curl, OUString const &url)
int memory_write(void *buffer, size_t size, size_t nmemb, void *stream)
#define SAL_WARN_IF(condition, area, stream)
Definition of ftpcontentprovider.
@ FOLDER_MIGHT_EXIST_DURING_INSERT
@ FILE_MIGHT_EXIST_DURING_INSERT
@ INETCOREFTP_FILEMODE_ISDIR
@ INETCOREFTP_FILEMODE_UNKNOWN
constexpr OUStringLiteral last
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)