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 ==
"." )
247 bff.append(
"ftp://");
252 OUString aPassword,aAccount;
260 !aPassword.isEmpty() )
281 if(!bff.isEmpty() && bff[bff.getLength()-1] !=
'/')
285 return bff.makeStringAndClear();
293 bff.append(
"ftp://");
298 OUString aPassword,aAccount;
333 else if (
last ==
".." )
334 bff.append(
last +
"/..");
337 return bff.makeStringAndClear();
363 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
371#define SET_CONTROL_CONTAINER \
372 MemoryContainer control; \
373 (void)curl_easy_setopt(curl, \
374 CURLOPT_HEADERFUNCTION, \
376 (void)curl_easy_setopt(curl, \
377 CURLOPT_WRITEHEADER, \
383 OString urlParAscii(url.getStr(),
385 RTL_TEXTENCODING_UTF8);
386 (void)curl_easy_setopt(curl,
388 urlParAscii.getStr());
399 OUString url(
ident(
false,
true));
402 oslFileHandle res(
nullptr );
403 if ( osl_createTempFile(
nullptr, &res,
nullptr ) == osl_File_E_None )
405 (void)curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,
file_write);
406 (void)curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
408 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
409 CURLcode
err = curl_easy_perform(curl);
413 oslFileError rc = osl_setFilePos( res, osl_Pos_Absolut, 0 );
415 "osl_setFilePos failed");
435 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
false);
437 (void)curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,
memory_write);
438 (void)curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data);
440 OUString url(
ident(
true,
true));
442 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
444 CURLcode
err = curl_easy_perform(curl);
451 char* fwd =
static_cast<char*
>(data.
m_pBuffer);
455 OS osKind(FTP_UNKNOWN);
456 std::vector<FTPDirentry> resvec;
459 OUString viewurl(
ident(
true,
false));
489 if( osKind !=
int(FTP_UNKNOWN) && aDirEntry.
m_aName !=
".." && aDirEntry.
m_aName !=
"." ) {
490 aDirEntry.
m_aURL = viewurl + encodePathSegment(aDirEntry.
m_aName);
494 case OpenMode::DOCUMENTS:
496 resvec.push_back(aDirEntry);
498 case OpenMode::FOLDERS:
500 resvec.push_back(aDirEntry);
503 resvec.push_back(aDirEntry);
519 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
520 struct curl_slist *slist =
nullptr;
522 slist = curl_slist_append(slist,
"PWD");
523 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
530 OUString url(
ident(
false,
true));
532 if(try_more && !url.endsWith(
"/"))
534 else if(!try_more && url.endsWith(
"/"))
535 url = url.copy(0,url.getLength()-1);
538 err = curl_easy_perform(curl);
540 if(
err == CURLE_OK) {
541 char* fwd =
static_cast<char*
>(control.m_pBuffer);
542 sal_uInt32 len = control.m_nWritePos;
544 aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8);
549 sal_Int32 index1 = aNetTitle.lastIndexOf(
"257");
550 index1 = aNetTitle.indexOf(
'"', index1 + std::strlen(
"257")) + 1;
551 sal_Int32 index2 = aNetTitle.indexOf(
'"', index1);
552 aNetTitle = index2 > index1
553 ? aNetTitle.copy(index1, index2 - index1) : OUString();
554 if( aNetTitle !=
"/" ) {
555 index1 = aNetTitle.lastIndexOf(
'/');
556 aNetTitle = aNetTitle.copy(1+index1);
559 }
else if(
err == CURLE_BAD_PASSWORD_ENTERED)
563#if LIBCURL_VERSION_NUM>=0x070d01
564 else if(
err == CURLE_LOGIN_DENIED)
569 else if(try_more &&
err == CURLE_FTP_ACCESS_DENIED) {
588 curl_slist_free_all(slist);
599 if( nettitle ==
"/" || nettitle ==
".." )
606 if( nettitle !=
"/" ) {
610 std::vector<FTPDirentry> aList =
aURL.list(OpenMode::ALL);
613 if(
d.m_aName == nettitle) {
625 static size_t memory_read(
void *ptr,
size_t size,
size_t nmemb,
void *stream)
627 sal_Int32 nRequested = sal_Int32(
size*nmemb);
630 return size_t(curlInput->
read(
static_cast<sal_Int8*
>(ptr),nRequested));
640 if(!replaceExisting) {
651 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
false);
652 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
653 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
654 (void)curl_easy_setopt(curl,CURLOPT_READFUNCTION,
memory_read);
655 (void)curl_easy_setopt(curl,CURLOPT_READDATA,
stream);
656 (void)curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
658 OUString url(
ident(
false,
true));
661 CURLcode
err = curl_easy_perform(curl);
662 (void)curl_easy_setopt(curl, CURLOPT_UPLOAD,
false);
674 titleOU = decodePathSegment(titleOU);
675 title = OString(titleOU.getStr(),
677 RTL_TEXTENCODING_UTF8);
681 title = OString(
"/");
683 OString aDel =
"del " + title;
684 OString mkd =
"mkd " + title;
686 struct curl_slist *slist =
nullptr;
689 if(!ReplaceExisting) {
694 slist = curl_slist_append(slist,aDel.getStr());
696 slist = curl_slist_append(slist,mkd.getStr());
700 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
701 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
704 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
706 OUString url(
parent(
true));
707 if(!url.endsWith(
"/"))
711 CURLcode
err = curl_easy_perform(curl);
712 curl_slist_free_all(slist);
724 OString renamefrom =
"RNFR " +
725 OString(OldTitle.getStr(),
726 OldTitle.getLength(),
727 RTL_TEXTENCODING_UTF8);
729 OString renameto =
"RNTO " +
730 OString(NewTitle.getStr(),
731 NewTitle.getLength(),
732 RTL_TEXTENCODING_UTF8);
734 struct curl_slist *slist =
nullptr;
735 slist = curl_slist_append(slist,renamefrom.getStr());
736 slist = curl_slist_append(slist,renameto.getStr());
737 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
740 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
741 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
743 OUString url(
parent(
true));
744 if(!url.endsWith(
"/"))
748 CURLcode
err = curl_easy_perform(curl);
749 curl_slist_free_all(slist);
762 OString dele(aDirentry.
m_aName.getStr(),
764 RTL_TEXTENCODING_UTF8);
767 std::vector<FTPDirentry> vec =
list(sal_Int16(OpenMode::ALL));
776 dele =
"RMD " + dele;
779 dele =
"DELE " + dele;
785 struct curl_slist *slist =
nullptr;
786 slist = curl_slist_append(slist,dele.getStr());
787 (void)curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
790 (void)curl_easy_setopt(curl,CURLOPT_NOBODY,
true);
791 (void)curl_easy_setopt(curl,CURLOPT_QUOTE,0);
793 OUString url(
parent(
true));
794 if(!url.endsWith(
"/"))
798 CURLcode
err = curl_easy_perform(curl);
799 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)