summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/ftp/ftpurl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/ftp/ftpurl.cxx')
-rw-r--r--ucb/source/ucp/ftp/ftpurl.cxx840
1 files changed, 840 insertions, 0 deletions
diff --git a/ucb/source/ucp/ftp/ftpurl.cxx b/ucb/source/ucp/ftp/ftpurl.cxx
new file mode 100644
index 000000000000..7ef4db27dca5
--- /dev/null
+++ b/ucb/source/ucp/ftp/ftpurl.cxx
@@ -0,0 +1,840 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+
+#include <memory>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <string.h>
+#include <rtl/uri.hxx>
+
+#include "ftpstrcont.hxx"
+#include "ftpurl.hxx"
+#include "ftphandleprovider.hxx"
+#include "ftpinpstr.hxx"
+#include "ftpcfunc.hxx"
+#include "ftpcontainer.hxx"
+
+using namespace ftp;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+
+namespace {
+
+rtl::OUString encodePathSegment(rtl::OUString const & decoded) {
+ return rtl::Uri::encode(
+ decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8);
+}
+
+rtl::OUString decodePathSegment(rtl::OUString const & encoded) {
+ return rtl::Uri::decode(
+ encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+}
+
+}
+
+MemoryContainer::MemoryContainer()
+ : m_nLen(0),
+ m_nWritePos(0),
+ m_pBuffer(0)
+{
+}
+
+MemoryContainer::~MemoryContainer()
+{
+ rtl_freeMemory(m_pBuffer);
+}
+
+
+int MemoryContainer::append(
+ const void* pBuffer,
+ size_t size,
+ size_t nmemb
+) throw()
+{
+ sal_uInt32 nLen = size*nmemb;
+ sal_uInt32 tmp(nLen + m_nWritePos);
+
+ if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
+ do {
+ m_nLen+=1024;
+ } while(m_nLen < tmp);
+
+ m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen);
+ }
+
+ rtl_copyMemory(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
+ pBuffer,nLen);
+ m_nWritePos = tmp;
+ return nLen;
+}
+
+
+extern "C" {
+
+ int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
+ {
+ MemoryContainer *_stream =
+ reinterpret_cast<MemoryContainer*>(stream);
+
+ if(!_stream)
+ return 0;
+
+ return _stream->append(buffer,size,nmemb);
+ }
+
+}
+
+
+FTPURL::FTPURL(const FTPURL& r)
+ : m_mutex(),
+ m_pFCP(r.m_pFCP),
+ m_aUsername(r.m_aUsername),
+ m_bShowPassword(r.m_bShowPassword),
+ m_aHost(r.m_aHost),
+ m_aPort(r.m_aPort),
+ m_aPathSegmentVec(r.m_aPathSegmentVec)
+
+{
+}
+
+
+FTPURL::FTPURL(const rtl::OUString& url,
+ FTPHandleProvider* pFCP)
+ throw(
+ malformed_exception
+ )
+ : m_pFCP(pFCP),
+ m_aUsername(RTL_CONSTASCII_USTRINGPARAM("anonymous")),
+ m_bShowPassword(false),
+ m_aPort(RTL_CONSTASCII_USTRINGPARAM("21"))
+{
+ parse(url); // can reset m_bShowPassword
+}
+
+
+FTPURL::~FTPURL()
+{
+}
+
+
+void FTPURL::parse(const rtl::OUString& url)
+ throw(
+ malformed_exception
+ )
+{
+ rtl::OUString aPassword,aAccount;
+ rtl::OString aIdent(url.getStr(),
+ url.getLength(),
+ RTL_TEXTENCODING_UTF8);
+
+ rtl::OString lower = aIdent.toAsciiLowerCase();
+ if(lower.getLength() < 6 ||
+ strncmp("ftp://",lower.getStr(),6))
+ throw malformed_exception();
+
+ char *buffer = new char[1+aIdent.getLength()];
+ const char* p2 = aIdent.getStr();
+ p2 += 6;
+
+ char ch;
+ char *p1 = buffer; // determine "username:password@host:port"
+ while((ch = *p2++) != '/' && ch)
+ *p1++ = ch;
+ *p1 = 0;
+
+ rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer),
+ RTL_TEXTENCODING_UTF8));
+
+ sal_Int32 l = aExpr.indexOf(sal_Unicode('@'));
+ m_aHost = aExpr.copy(1+l);
+
+ if(l != -1) {
+ // Now username and password.
+ aExpr = aExpr.copy(0,l);
+ l = aExpr.indexOf(sal_Unicode(':'));
+ if(l != -1) {
+ aPassword = aExpr.copy(1+l);
+ if(aPassword.getLength())
+ m_bShowPassword = true;
+ }
+ if(l > 0)
+ // Overwritte only if the username is not empty.
+ m_aUsername = aExpr.copy(0,l);
+ else if(aExpr.getLength())
+ m_aUsername = aExpr;
+ }
+
+ l = m_aHost.lastIndexOf(sal_Unicode(':'));
+ sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']'));
+ if((ipv6Back == -1 && l != -1) // not ipv6, but a port
+ ||
+ (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
+ )
+ {
+ if(1+l<m_aHost.getLength())
+ m_aPort = m_aHost.copy(1+l);
+ m_aHost = m_aHost.copy(0,l);
+ }
+
+ while(ch) { // now determine the pathsegments ...
+ p1 = buffer;
+ while((ch = *p2++) != '/' && ch)
+ *p1++ = ch;
+ *p1 = 0;
+
+ if(buffer[0]) {
+ if(strcmp(buffer,"..") == 0 &&
+ m_aPathSegmentVec.size() &&
+ ! m_aPathSegmentVec.back().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("..")))
+ m_aPathSegmentVec.pop_back();
+ else if(strcmp(buffer,".") == 0)
+ ; // Ignore
+ else
+ // This is a legal name.
+ m_aPathSegmentVec.push_back(
+ rtl::OUString(buffer,
+ strlen(buffer),
+ RTL_TEXTENCODING_UTF8));
+ }
+ }
+
+ delete[] buffer;
+
+ if(m_bShowPassword)
+ m_pFCP->setHost(m_aHost,
+ m_aPort,
+ m_aUsername,
+ aPassword,
+ aAccount);
+
+ // now check for something like ";type=i" at end of url
+ if(m_aPathSegmentVec.size() &&
+ (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) {
+ m_aType = m_aPathSegmentVec.back().copy(l);
+ m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
+ }
+}
+
+
+rtl::OUString FTPURL::ident(bool withslash,bool internal) const
+{
+ // rebuild the url as one without ellipses,
+ // and more important, as one without username and
+ // password. ( These are set together with the command. )
+
+ rtl::OUStringBuffer bff;
+ bff.appendAscii("ftp://");
+
+ if(!m_aUsername.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("anonymous"))) {
+ bff.append(m_aUsername);
+
+ rtl::OUString aPassword,aAccount;
+ m_pFCP->forHost(m_aHost,
+ m_aPort,
+ m_aUsername,
+ aPassword,
+ aAccount);
+
+ if((m_bShowPassword || internal) &&
+ aPassword.getLength() )
+ bff.append(sal_Unicode(':'))
+ .append(aPassword);
+
+ bff.append(sal_Unicode('@'));
+ }
+ bff.append(m_aHost);
+
+ if(!m_aPort.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("21")))
+ bff.append(sal_Unicode(':'))
+ .append(m_aPort)
+ .append(sal_Unicode('/'));
+ else
+ bff.append(sal_Unicode('/'));
+
+ for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i)
+ if(i == 0)
+ bff.append(m_aPathSegmentVec[i]);
+ else
+ bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
+ if(withslash)
+ if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/'))
+ bff.append(sal_Unicode('/'));
+
+ bff.append(m_aType);
+ return bff.makeStringAndClear();
+}
+
+
+rtl::OUString FTPURL::parent(bool internal) const
+{
+ rtl::OUStringBuffer bff;
+
+ bff.appendAscii("ftp://");
+
+ if(!m_aUsername.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("anonymous"))) {
+ bff.append(m_aUsername);
+
+ rtl::OUString aPassword,aAccount;
+ m_pFCP->forHost(m_aHost,
+ m_aPort,
+ m_aUsername,
+ aPassword,
+ aAccount);
+
+ if((internal || m_bShowPassword) && aPassword.getLength())
+ bff.append(sal_Unicode(':'))
+ .append(aPassword);
+
+ bff.append(sal_Unicode('@'));
+ }
+
+ bff.append(m_aHost);
+
+ if(!m_aPort.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("21")))
+ bff.append(sal_Unicode(':'))
+ .append(m_aPort)
+ .append(sal_Unicode('/'));
+ else
+ bff.append(sal_Unicode('/'));
+
+ rtl::OUString last;
+
+ for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i)
+ if(1+i == m_aPathSegmentVec.size())
+ last = m_aPathSegmentVec[i];
+ else if(i == 0)
+ bff.append(m_aPathSegmentVec[i]);
+ else
+ bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
+
+ if(!last.getLength())
+ bff.appendAscii("..");
+ else if(last.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("..")))
+ bff.append(last).appendAscii("/..");
+
+ bff.append(m_aType);
+ return bff.makeStringAndClear();
+}
+
+
+void FTPURL::child(const rtl::OUString& title)
+{
+ m_aPathSegmentVec.push_back(encodePathSegment(title));
+}
+
+
+rtl::OUString FTPURL::child() const
+{
+ return
+ m_aPathSegmentVec.size() ?
+ decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString();
+}
+
+
+
+/** Listing of a directory.
+ */
+
+namespace ftp {
+
+ enum OS {
+ FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
+ };
+
+}
+
+
+#define SET_CONTROL_CONTAINER \
+ MemoryContainer control; \
+ curl_easy_setopt(curl, \
+ CURLOPT_HEADERFUNCTION, \
+ memory_write); \
+ curl_easy_setopt(curl, \
+ CURLOPT_WRITEHEADER, \
+ &control)
+
+
+#define SET_DATA_CONTAINER \
+ curl_easy_setopt(curl,CURLOPT_NOBODY,false); \
+ MemoryContainer data; \
+ curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \
+ curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data)
+
+#define SET_URL(url) \
+ rtl::OString urlParAscii(url.getStr(), \
+ url.getLength(), \
+ RTL_TEXTENCODING_UTF8); \
+ curl_easy_setopt(curl, \
+ CURLOPT_URL, \
+ urlParAscii.getStr());
+
+ // Setting username:password
+#define SET_USER_PASSWORD(username,password) \
+ rtl::OUString combi(username + \
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + \
+ password); \
+ rtl::OString aUserPsswd(combi.getStr(), \
+ combi.getLength(), \
+ RTL_TEXTENCODING_UTF8); \
+ curl_easy_setopt(curl, \
+ CURLOPT_USERPWD, \
+ aUserPsswd.getStr())
+
+
+
+FILE* FTPURL::open()
+ throw(curl_exception)
+{
+ if(!m_aPathSegmentVec.size())
+ throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
+
+ CURL *curl = m_pFCP->handle();
+
+ SET_CONTROL_CONTAINER;
+ rtl::OUString url(ident(false,true));
+ SET_URL(url);
+ FILE *res = tmpfile();
+ curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
+ curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
+
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
+ CURLcode err = curl_easy_perform(curl);
+
+ if(err == CURLE_OK)
+ rewind(res);
+ else {
+ fclose(res),res = 0;
+ throw curl_exception(err);
+ }
+
+ return res;
+}
+
+
+std::vector<FTPDirentry> FTPURL::list(
+ sal_Int16 nMode
+) const
+ throw(
+ curl_exception
+ )
+{
+ CURL *curl = m_pFCP->handle();
+
+ SET_CONTROL_CONTAINER;
+ SET_DATA_CONTAINER;
+ rtl::OUString url(ident(true,true));
+ SET_URL(url);
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
+
+ CURLcode err = curl_easy_perform(curl);
+ if(err != CURLE_OK)
+ throw curl_exception(err);
+
+ // now evaluate the error messages
+
+ sal_uInt32 len = data.m_nWritePos;
+ char* fwd = (char*) data.m_pBuffer;
+ rtl::OString str(fwd,len);
+ char *p1, *p2;
+ p1 = p2 = fwd;
+
+ OS osKind(FTP_UNKNOWN);
+ std::vector<FTPDirentry> resvec;
+ FTPDirentry aDirEntry;
+ // ensure slash at the end
+ rtl::OUString viewurl(ident(true,false));
+
+ while(true) {
+ while(p2-fwd < int(len) && *p2 != '\n') ++p2;
+ if(p2-fwd == int(len)) break;
+
+ *p2 = 0;
+ switch(osKind) {
+ // While FTP knows the 'system'-command,
+ // which returns the operating system type,
+ // this is not usable here: There are Windows-server
+ // formatting the output like UNIX-ls command.
+ case FTP_DOS:
+ FTPDirectoryParser::parseDOS(aDirEntry,p1);
+ break;
+ case FTP_UNIX:
+ FTPDirectoryParser::parseUNIX(aDirEntry,p1);
+ break;
+ case FTP_VMS:
+ FTPDirectoryParser::parseVMS(aDirEntry,p1);
+ break;
+ default:
+ if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
+ osKind = FTP_UNIX;
+ else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
+ osKind = FTP_DOS;
+ else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
+ osKind = FTP_VMS;
+ }
+ aDirEntry.m_aName = aDirEntry.m_aName.trim();
+ if(osKind != int(FTP_UNKNOWN) &&
+ !aDirEntry.m_aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("..")) &&
+ !aDirEntry.m_aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) {
+ aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
+
+ sal_Bool isDir =
+ sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR);
+ switch(nMode) {
+ case OpenMode::DOCUMENTS:
+ if(!isDir)
+ resvec.push_back(aDirEntry);
+ break;
+ case OpenMode::FOLDERS:
+ if(isDir)
+ resvec.push_back(aDirEntry);
+ break;
+ default:
+ resvec.push_back(aDirEntry);
+ };
+ }
+ aDirEntry.clear();
+ p1 = p2 + 1;
+ }
+
+ return resvec;
+}
+
+
+rtl::OUString FTPURL::net_title() const
+ throw(curl_exception)
+{
+ CURL *curl = m_pFCP->handle();
+
+ SET_CONTROL_CONTAINER;
+ curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
+ struct curl_slist *slist = 0;
+ // post request
+ slist = curl_slist_append(slist,"PWD");
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
+
+ bool try_more(true);
+ CURLcode err;
+ rtl::OUString aNetTitle;
+
+ while(true) {
+ rtl::OUString url(ident(false,true));
+
+ if(try_more &&
+ 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
+ url += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); // add end-slash
+ else if(!try_more &&
+ 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength())
+ url = url.copy(0,url.getLength()-1); // remove end-slash
+
+ SET_URL(url);
+ err = curl_easy_perform(curl);
+
+ if(err == CURLE_OK) { // get the title from the server
+ char* fwd = (char*) control.m_pBuffer;
+ sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
+
+ aNetTitle = rtl::OUString(fwd,len,RTL_TEXTENCODING_UTF8);
+ // the buffer now contains the name of the file;
+ // analyze the output:
+ // Format of current working directory:
+ // 257 "/bla/bla" is current directory
+ sal_Int32 index1 = aNetTitle.lastIndexOf(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("257")));
+ index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1);
+ sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1);
+ aNetTitle = aNetTitle.copy(index1,index2-index1);
+ if(!aNetTitle.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) {
+ index1 = aNetTitle.lastIndexOf(sal_Unicode('/'));
+ aNetTitle = aNetTitle.copy(1+index1);
+ }
+ try_more = false;
+ } else if(err == CURLE_BAD_PASSWORD_ENTERED)
+ // the client should retry after getting the correct
+ // username + password
+ throw curl_exception(err);
+#if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
+ else if(err == CURLE_LOGIN_DENIED)
+ // the client should retry after getting the correct
+ // username + password
+ throw curl_exception(err);
+#endif
+ else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
+ // We were either denied access when trying to login to
+ // an FTP server or when trying to change working directory
+ // to the one given in the URL.
+ if(m_aPathSegmentVec.size())
+ // determine title form url
+ aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
+ else
+ // must be root
+ aNetTitle = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+ try_more = false;
+ }
+
+ if(try_more)
+ try_more = false;
+ else
+ break;
+ }
+
+ curl_slist_free_all(slist);
+ return aNetTitle;
+}
+
+
+FTPDirentry FTPURL::direntry() const
+ throw(curl_exception)
+{
+ rtl::OUString nettitle = net_title();
+ FTPDirentry aDirentry;
+
+ aDirentry.m_aName = nettitle; // init aDirentry
+ if(nettitle.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("/")) ||
+ nettitle.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("..")))
+ aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
+ else
+ aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
+
+ aDirentry.m_nSize = 0;
+
+ if(!nettitle.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) {
+ // try to open the parent directory
+ FTPURL aURL(parent(),m_pFCP);
+
+ std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
+
+ for(unsigned i = 0; i < aList.size(); ++i) {
+ if(aList[i].m_aName == nettitle) { // the relevant file is found
+ aDirentry = aList[i];
+ break;
+ }
+ }
+ }
+ return aDirentry;
+}
+
+
+extern "C" {
+
+ size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
+ {
+ sal_Int32 nRequested = sal_Int32(size*nmemb);
+ CurlInput *curlInput = static_cast<CurlInput*>(stream);
+ if(curlInput)
+ return size_t(curlInput->read(((sal_Int8*)ptr),nRequested));
+ else
+ return 0;
+ }
+
+}
+
+
+void FTPURL::insert(bool replaceExisting,void* stream) const
+ throw(curl_exception)
+{
+ if(!replaceExisting) {
+// FTPDirentry aDirentry(direntry());
+// if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
+ // throw curl_exception(FILE_EXIST_DURING_INSERT);
+ throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
+ } // else
+ // overwrite is default in libcurl
+
+ CURL *curl = m_pFCP->handle();
+
+ SET_CONTROL_CONTAINER;
+ curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
+ curl_easy_setopt(curl,CURLOPT_QUOTE,0);
+ curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
+ curl_easy_setopt(curl,CURLOPT_READDATA,stream);
+ curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
+
+ rtl::OUString url(ident(false,true));
+ SET_URL(url);
+
+ CURLcode err = curl_easy_perform(curl);
+ curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
+
+ if(err != CURLE_OK)
+ throw curl_exception(err);
+}
+
+
+
+void FTPURL::mkdir(bool ReplaceExisting) const
+ throw(curl_exception)
+{
+ rtl::OString title;
+ if(m_aPathSegmentVec.size()) {
+ rtl::OUString titleOU = m_aPathSegmentVec.back();
+ titleOU = decodePathSegment(titleOU);
+ title = rtl::OString(titleOU.getStr(),
+ titleOU.getLength(),
+ RTL_TEXTENCODING_UTF8);
+ }
+ else
+ // will give an error
+ title = rtl::OString("/");
+
+ rtl::OString aDel("del "); aDel += title;
+ rtl::OString mkd("mkd "); mkd += title;
+
+ struct curl_slist *slist = 0;
+
+ FTPDirentry aDirentry(direntry());
+ if(!ReplaceExisting) {
+// if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
+// throw curl_exception(FOLDER_EXIST_DURING_INSERT);
+ throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
+ } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
+ slist = curl_slist_append(slist,aDel.getStr());
+
+ slist = curl_slist_append(slist,mkd.getStr());
+
+ CURL *curl = m_pFCP->handle();
+ SET_CONTROL_CONTAINER;
+ curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
+ curl_easy_setopt(curl,CURLOPT_QUOTE,0);
+
+ // post request
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
+
+ rtl::OUString url(parent(true));
+ if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
+ url += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+ SET_URL(url);
+
+ CURLcode err = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if(err != CURLE_OK)
+ throw curl_exception(err);
+}
+
+
+rtl::OUString FTPURL::ren(const rtl::OUString& NewTitle)
+ throw(curl_exception)
+{
+ CURL *curl = m_pFCP->handle();
+
+ // post request
+ rtl::OString renamefrom("RNFR ");
+ rtl::OUString OldTitle = net_title();
+ renamefrom +=
+ rtl::OString(OldTitle.getStr(),
+ OldTitle.getLength(),
+ RTL_TEXTENCODING_UTF8);
+
+ rtl::OString renameto("RNTO ");
+ renameto +=
+ rtl::OString(NewTitle.getStr(),
+ NewTitle.getLength(),
+ RTL_TEXTENCODING_UTF8);
+
+ struct curl_slist *slist = 0;
+ slist = curl_slist_append(slist,renamefrom.getStr());
+ slist = curl_slist_append(slist,renameto.getStr());
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
+
+ SET_CONTROL_CONTAINER;
+ curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
+ curl_easy_setopt(curl,CURLOPT_QUOTE,0);
+
+ rtl::OUString url(parent(true));
+ if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
+ url += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+ SET_URL(url);
+
+ CURLcode err = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if(err != CURLE_OK)
+ throw curl_exception(err);
+ else if(m_aPathSegmentVec.size() &&
+ !m_aPathSegmentVec.back().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("..")))
+ m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
+ return OldTitle;
+}
+
+
+
+void FTPURL::del() const
+ throw(curl_exception)
+{
+ FTPDirentry aDirentry(direntry());
+
+ rtl::OString dele(aDirentry.m_aName.getStr(),
+ aDirentry.m_aName.getLength(),
+ RTL_TEXTENCODING_UTF8);
+
+ if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
+ std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
+ for( unsigned int i = 0; i < vec.size(); ++i )
+ try {
+ FTPURL url(vec[i].m_aURL,m_pFCP);
+ url.del();
+ } catch(const curl_exception&) {
+ }
+ dele = rtl::OString("RMD ") + dele;
+ }
+ else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
+ dele = rtl::OString("DELE ") + dele;
+ else
+ return;
+
+ // post request
+ CURL *curl = m_pFCP->handle();
+ struct curl_slist *slist = 0;
+ slist = curl_slist_append(slist,dele.getStr());
+ curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
+
+ SET_CONTROL_CONTAINER;
+ curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
+ curl_easy_setopt(curl,CURLOPT_QUOTE,0);
+
+ rtl::OUString url(parent(true));
+ if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
+ url += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
+ SET_URL(url);
+
+ CURLcode err = curl_easy_perform(curl);
+ curl_slist_free_all(slist);
+ if(err != CURLE_OK)
+ throw curl_exception(err);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */