| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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::OUString::createFromAscii("anonymous")), |
| m_bShowPassword(false), |
| m_aPort(rtl::OUString::createFromAscii("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().equalsAscii("..")) |
| 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.equalsAscii("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.equalsAscii("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.equalsAscii("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.equalsAscii("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.equalsAscii("..")) |
| 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::createFromAscii(":") + \ |
| password); \ |
| rtl::OString aUserPsswd(combi.getStr(), \ |
| combi.getLength(), \ |
| RTL_TEXTENCODING_UTF8); \ |
| curl_easy_setopt(curl, \ |
| CURLOPT_USERPWD, \ |
| aUserPsswd.getStr()) |
| |
| |
| |
| oslFileHandle 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); |
| |
| oslFileHandle res( NULL ); |
| if ( osl_createTempFile( NULL, &res, NULL ) == osl_File_E_None ) |
| { |
| 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) |
| osl_setFilePos( res, osl_Pos_Absolut, 0 ); |
| else { |
| osl_closeFile(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.equalsAscii("..") && |
| !aDirEntry.m_aName.equalsAscii(".")) { |
| 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::createFromAscii("/"); // 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::createFromAscii("257")); |
| index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1); |
| sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1); |
| aNetTitle = aNetTitle.copy(index1,index2-index1); |
| if(!aNetTitle.equalsAscii("/")) { |
| 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::createFromAscii("/"); |
| 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.equalsAscii("/") || |
| nettitle.equalsAscii("..")) |
| aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR; |
| else |
| aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN; |
| |
| aDirentry.m_nSize = 0; |
| |
| if(!nettitle.equalsAscii("/")) { |
| // 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::createFromAscii("/"); |
| 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::createFromAscii("/"); |
| 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().equalsAscii("..")) |
| 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::createFromAscii("/"); |
| SET_URL(url); |
| |
| CURLcode err = curl_easy_perform(curl); |
| curl_slist_free_all(slist); |
| if(err != CURLE_OK) |
| throw curl_exception(err); |
| } |
| |