bump product version to 5.0.4.1
[LibreOffice.git] / ucb / source / ucp / ftp / ftpurl.cxx
blob8bbcfbdfba7ec2e049b6168e9f347f867bd0deaa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 /**************************************************************************
21 TODO
22 **************************************************************************
24 *************************************************************************/
26 #include <sal/config.h>
28 #include <cstring>
29 #include <vector>
31 #include <rtl/ustrbuf.hxx>
32 #include <com/sun/star/ucb/OpenMode.hpp>
33 #include <string.h>
34 #include <rtl/uri.hxx>
36 #include "ftpstrcont.hxx"
37 #include "ftpurl.hxx"
38 #include "ftphandleprovider.hxx"
39 #include "ftpcfunc.hxx"
40 #include "ftpcontainer.hxx"
41 #include <boost/scoped_array.hpp>
43 using namespace ftp;
44 using namespace com::sun::star::ucb;
45 using namespace com::sun::star::uno;
46 using namespace com::sun::star::io;
48 namespace {
50 OUString encodePathSegment(OUString const & decoded) {
51 return rtl::Uri::encode(
52 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
53 RTL_TEXTENCODING_UTF8);
56 OUString decodePathSegment(OUString const & encoded) {
57 return rtl::Uri::decode(
58 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
63 MemoryContainer::MemoryContainer()
64 : m_nLen(0),
65 m_nWritePos(0),
66 m_pBuffer(0)
70 MemoryContainer::~MemoryContainer()
72 rtl_freeMemory(m_pBuffer);
76 int MemoryContainer::append(
77 const void* pBuffer,
78 size_t size,
79 size_t nmemb
80 ) throw()
82 sal_uInt32 nLen = size*nmemb;
83 sal_uInt32 tmp(nLen + m_nWritePos);
85 if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
86 do {
87 m_nLen+=1024;
88 } while(m_nLen < tmp);
90 m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen);
93 memcpy(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
94 pBuffer,nLen);
95 m_nWritePos = tmp;
96 return nLen;
100 extern "C" {
102 int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
104 MemoryContainer *_stream =
105 static_cast<MemoryContainer*>(stream);
107 if(!_stream)
108 return 0;
110 return _stream->append(buffer,size,nmemb);
116 FTPURL::FTPURL(const FTPURL& r)
117 : m_pFCP(r.m_pFCP),
118 m_aUsername(r.m_aUsername),
119 m_bShowPassword(r.m_bShowPassword),
120 m_aHost(r.m_aHost),
121 m_aPort(r.m_aPort),
122 m_aPathSegmentVec(r.m_aPathSegmentVec)
128 FTPURL::FTPURL(const OUString& url,
129 FTPHandleProvider* pFCP)
130 throw(
131 malformed_exception
133 : m_pFCP(pFCP),
134 m_aUsername("anonymous"),
135 m_bShowPassword(false),
136 m_aPort("21")
138 parse(url); // can reset m_bShowPassword
142 FTPURL::~FTPURL()
147 void FTPURL::parse(const OUString& url)
148 throw(
149 malformed_exception
152 OUString aPassword,aAccount;
153 OString aIdent(url.getStr(),
154 url.getLength(),
155 RTL_TEXTENCODING_UTF8);
157 OString lower = aIdent.toAsciiLowerCase();
158 if(lower.getLength() < 6 ||
159 strncmp("ftp://",lower.getStr(),6))
160 throw malformed_exception();
162 boost::scoped_array<char> buffer(new char[1+aIdent.getLength()]);
163 const char* p2 = aIdent.getStr();
164 p2 += 6;
166 char ch;
167 char *p1 = buffer.get(); // determine "username:password@host:port"
168 while((ch = *p2++) != '/' && ch)
169 *p1++ = ch;
170 *p1 = 0;
172 OUString aExpr(buffer.get(), strlen(buffer.get()), RTL_TEXTENCODING_UTF8);
174 sal_Int32 l = aExpr.indexOf('@');
175 m_aHost = aExpr.copy(1+l);
177 if(l != -1) {
178 // Now username and password.
179 aExpr = aExpr.copy(0,l);
180 l = aExpr.indexOf(':');
181 if(l != -1) {
182 aPassword = aExpr.copy(1+l);
183 if(!aPassword.isEmpty())
184 m_bShowPassword = true;
186 if(l > 0)
187 // Overwritte only if the username is not empty.
188 m_aUsername = aExpr.copy(0,l);
189 else if(!aExpr.isEmpty())
190 m_aUsername = aExpr;
193 l = m_aHost.lastIndexOf(':');
194 sal_Int32 ipv6Back = m_aHost.lastIndexOf(']');
195 if((ipv6Back == -1 && l != -1) // not ipv6, but a port
197 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
200 if(1+l<m_aHost.getLength())
201 m_aPort = m_aHost.copy(1+l);
202 m_aHost = m_aHost.copy(0,l);
205 while(ch) { // now determine the pathsegments ...
206 p1 = buffer.get();
207 while((ch = *p2++) != '/' && ch)
208 *p1++ = ch;
209 *p1 = 0;
211 if(buffer[0]) {
212 if( strcmp(buffer.get(),"..") == 0 && !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." )
213 m_aPathSegmentVec.pop_back();
214 else if(strcmp(buffer.get(),".") == 0)
215 ; // Ignore
216 else
217 // This is a legal name.
218 m_aPathSegmentVec.push_back(
219 OUString(buffer.get(),
220 strlen(buffer.get()),
221 RTL_TEXTENCODING_UTF8));
225 buffer.reset();
227 if(m_bShowPassword)
228 m_pFCP->setHost(m_aHost,
229 m_aPort,
230 m_aUsername,
231 aPassword,
232 aAccount);
234 // now check for something like ";type=i" at end of url
235 if(m_aPathSegmentVec.size() &&
236 (l = m_aPathSegmentVec.back().indexOf(';')) != -1) {
237 m_aType = m_aPathSegmentVec.back().copy(l);
238 m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
243 OUString FTPURL::ident(bool withslash,bool internal) const
245 // rebuild the url as one without ellipses,
246 // and more important, as one without username and
247 // password. ( These are set together with the command. )
249 OUStringBuffer bff;
250 bff.appendAscii("ftp://");
252 if( m_aUsername != "anonymous" ) {
253 bff.append(m_aUsername);
255 OUString aPassword,aAccount;
256 m_pFCP->forHost(m_aHost,
257 m_aPort,
258 m_aUsername,
259 aPassword,
260 aAccount);
262 if((m_bShowPassword || internal) &&
263 !aPassword.isEmpty() )
264 bff.append(':')
265 .append(aPassword);
267 bff.append('@');
269 bff.append(m_aHost);
271 if( m_aPort != "21" )
272 bff.append(':')
273 .append(m_aPort)
274 .append('/');
275 else
276 bff.append('/');
278 for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i)
279 if(i == 0)
280 bff.append(m_aPathSegmentVec[i]);
281 else
282 bff.append('/').append(m_aPathSegmentVec[i]);
283 if(withslash)
284 if(!bff.isEmpty() && bff[bff.getLength()-1] != '/')
285 bff.append('/');
287 bff.append(m_aType);
288 return bff.makeStringAndClear();
292 OUString FTPURL::parent(bool internal) const
294 OUStringBuffer bff;
296 bff.appendAscii("ftp://");
298 if( m_aUsername != "anonymous" ) {
299 bff.append(m_aUsername);
301 OUString aPassword,aAccount;
302 m_pFCP->forHost(m_aHost,
303 m_aPort,
304 m_aUsername,
305 aPassword,
306 aAccount);
308 if((internal || m_bShowPassword) && !aPassword.isEmpty())
309 bff.append(':')
310 .append(aPassword);
312 bff.append('@');
315 bff.append(m_aHost);
317 if( m_aPort != "21" )
318 bff.append(':')
319 .append(m_aPort)
320 .append('/');
321 else
322 bff.append('/');
324 OUString last;
326 for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i)
327 if(1+i == m_aPathSegmentVec.size())
328 last = m_aPathSegmentVec[i];
329 else if(i == 0)
330 bff.append(m_aPathSegmentVec[i]);
331 else
332 bff.append('/').append(m_aPathSegmentVec[i]);
334 if(last.isEmpty())
335 bff.appendAscii("..");
336 else if ( last == ".." )
337 bff.append(last).appendAscii("/..");
339 bff.append(m_aType);
340 return bff.makeStringAndClear();
344 void FTPURL::child(const OUString& title)
346 m_aPathSegmentVec.push_back(encodePathSegment(title));
350 OUString FTPURL::child() const
352 return
353 m_aPathSegmentVec.size() ?
354 decodePathSegment(m_aPathSegmentVec.back()) : OUString();
359 /** Listing of a directory.
362 namespace ftp {
364 enum OS {
365 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
371 #define SET_CONTROL_CONTAINER \
372 MemoryContainer control; \
373 curl_easy_setopt(curl, \
374 CURLOPT_HEADERFUNCTION, \
375 memory_write); \
376 curl_easy_setopt(curl, \
377 CURLOPT_WRITEHEADER, \
378 &control)
381 #define SET_DATA_CONTAINER \
382 curl_easy_setopt(curl,CURLOPT_NOBODY,false); \
383 MemoryContainer data; \
384 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \
385 curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data)
387 #define SET_URL(url) \
388 OString urlParAscii(url.getStr(), \
389 url.getLength(), \
390 RTL_TEXTENCODING_UTF8); \
391 curl_easy_setopt(curl, \
392 CURLOPT_URL, \
393 urlParAscii.getStr());
395 oslFileHandle FTPURL::open()
396 throw(curl_exception)
398 if(m_aPathSegmentVec.empty())
399 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
401 CURL *curl = m_pFCP->handle();
403 SET_CONTROL_CONTAINER;
404 OUString url(ident(false,true));
405 SET_URL(url);
407 oslFileHandle res( NULL );
408 if ( osl_createTempFile( NULL, &res, NULL ) == osl_File_E_None )
410 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
411 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
413 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
414 CURLcode err = curl_easy_perform(curl);
416 if(err == CURLE_OK)
418 oslFileError rc = osl_setFilePos( res, osl_Pos_Absolut, 0 );
419 SAL_WARN_IF(rc != osl_File_E_None, "ucb.ucp.ftp",
420 "osl_setFilePos failed");
422 else {
423 osl_closeFile(res),res = 0;
424 throw curl_exception(err);
428 return res;
432 std::vector<FTPDirentry> FTPURL::list(
433 sal_Int16 nMode
434 ) const
435 throw(
436 curl_exception
439 CURL *curl = m_pFCP->handle();
441 SET_CONTROL_CONTAINER;
442 SET_DATA_CONTAINER;
443 OUString url(ident(true,true));
444 SET_URL(url);
445 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
447 CURLcode err = curl_easy_perform(curl);
448 if(err != CURLE_OK)
449 throw curl_exception(err);
451 // now evaluate the error messages
453 sal_uInt32 len = data.m_nWritePos;
454 char* fwd = static_cast<char*>(data.m_pBuffer);
455 char *p1, *p2;
456 p1 = p2 = fwd;
458 OS osKind(FTP_UNKNOWN);
459 std::vector<FTPDirentry> resvec;
460 FTPDirentry aDirEntry;
461 // ensure slash at the end
462 OUString viewurl(ident(true,false));
464 while(true) {
465 while(p2-fwd < int(len) && *p2 != '\n') ++p2;
466 if(p2-fwd == int(len)) break;
468 *p2 = 0;
469 switch(osKind) {
470 // While FTP knows the 'system'-command,
471 // which returns the operating system type,
472 // this is not usable here: There are Windows-server
473 // formatting the output like UNIX-ls command.
474 case FTP_DOS:
475 FTPDirectoryParser::parseDOS(aDirEntry,p1);
476 break;
477 case FTP_UNIX:
478 FTPDirectoryParser::parseUNIX(aDirEntry,p1);
479 break;
480 case FTP_VMS:
481 FTPDirectoryParser::parseVMS(aDirEntry,p1);
482 break;
483 default:
484 if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
485 osKind = FTP_UNIX;
486 else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
487 osKind = FTP_DOS;
488 else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
489 osKind = FTP_VMS;
491 aDirEntry.m_aName = aDirEntry.m_aName.trim();
492 if( osKind != int(FTP_UNKNOWN) && aDirEntry.m_aName != ".." && aDirEntry.m_aName != "." ) {
493 aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
495 bool isDir = (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR;
496 switch(nMode) {
497 case OpenMode::DOCUMENTS:
498 if(!isDir)
499 resvec.push_back(aDirEntry);
500 break;
501 case OpenMode::FOLDERS:
502 if(isDir)
503 resvec.push_back(aDirEntry);
504 break;
505 default:
506 resvec.push_back(aDirEntry);
509 aDirEntry.clear();
510 p1 = p2 + 1;
513 return resvec;
517 OUString FTPURL::net_title() const
518 throw(curl_exception)
520 CURL *curl = m_pFCP->handle();
522 SET_CONTROL_CONTAINER;
523 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
524 struct curl_slist *slist = 0;
525 // post request
526 slist = curl_slist_append(slist,"PWD");
527 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
529 bool try_more(true);
530 CURLcode err;
531 OUString aNetTitle;
533 while(true) {
534 OUString url(ident(false,true));
536 if(try_more && !url.endsWith("/"))
537 url += "/"; // add end-slash
538 else if(!try_more && url.endsWith("/"))
539 url = url.copy(0,url.getLength()-1); // remove end-slash
541 SET_URL(url);
542 err = curl_easy_perform(curl);
544 if(err == CURLE_OK) { // get the title from the server
545 char* fwd = static_cast<char*>(control.m_pBuffer);
546 sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
548 aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8);
549 // the buffer now contains the name of the file;
550 // analyze the output:
551 // Format of current working directory:
552 // 257 "/bla/bla" is current directory
553 sal_Int32 index1 = aNetTitle.lastIndexOf("257");
554 index1 = aNetTitle.indexOf('"', index1 + std::strlen("257")) + 1;
555 sal_Int32 index2 = aNetTitle.indexOf('"', index1);
556 aNetTitle = index2 > index1
557 ? aNetTitle.copy(index1, index2 - index1) : OUString();
558 if( aNetTitle != "/" ) {
559 index1 = aNetTitle.lastIndexOf('/');
560 aNetTitle = aNetTitle.copy(1+index1);
562 try_more = false;
563 } else if(err == CURLE_BAD_PASSWORD_ENTERED)
564 // the client should retry after getting the correct
565 // username + password
566 throw curl_exception(err);
567 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
568 else if(err == CURLE_LOGIN_DENIED)
569 // the client should retry after getting the correct
570 // username + password
571 throw curl_exception(err);
572 #endif
573 else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
574 // We were either denied access when trying to login to
575 // an FTP server or when trying to change working directory
576 // to the one given in the URL.
577 if(!m_aPathSegmentVec.empty())
578 // determine title form url
579 aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
580 else
581 // must be root
582 aNetTitle = "/";
583 try_more = false;
586 if(try_more)
587 try_more = false;
588 else
589 break;
592 curl_slist_free_all(slist);
593 return aNetTitle;
597 FTPDirentry FTPURL::direntry() const
598 throw (curl_exception, malformed_exception)
600 OUString nettitle = net_title();
601 FTPDirentry aDirentry;
603 aDirentry.m_aName = nettitle; // init aDirentry
604 if( nettitle == "/" || nettitle == ".." )
605 aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
606 else
607 aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
609 aDirentry.m_nSize = 0;
611 if( nettitle != "/" ) {
612 // try to open the parent directory
613 FTPURL aURL(parent(),m_pFCP);
615 std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
617 for(unsigned i = 0; i < aList.size(); ++i) {
618 if(aList[i].m_aName == nettitle) { // the relevant file is found
619 aDirentry = aList[i];
620 break;
624 return aDirentry;
628 extern "C" {
630 size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
632 sal_Int32 nRequested = sal_Int32(size*nmemb);
633 CurlInput *curlInput = static_cast<CurlInput*>(stream);
634 if(curlInput)
635 return size_t(curlInput->read(static_cast<sal_Int8*>(ptr),nRequested));
636 else
637 return 0;
643 void FTPURL::insert(bool replaceExisting,void* stream) const
644 throw(curl_exception)
646 if(!replaceExisting) {
647 // FTPDirentry aDirentry(direntry());
648 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
649 // throw curl_exception(FILE_EXIST_DURING_INSERT);
650 throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
651 } // else
652 // overwrite is default in libcurl
654 CURL *curl = m_pFCP->handle();
656 SET_CONTROL_CONTAINER;
657 curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
658 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
659 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
660 curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
661 curl_easy_setopt(curl,CURLOPT_READDATA,stream);
662 curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
664 OUString url(ident(false,true));
665 SET_URL(url);
667 CURLcode err = curl_easy_perform(curl);
668 curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
670 if(err != CURLE_OK)
671 throw curl_exception(err);
676 void FTPURL::mkdir(bool ReplaceExisting) const
677 throw (curl_exception, malformed_exception)
679 OString title;
680 if(!m_aPathSegmentVec.empty()) {
681 OUString titleOU = m_aPathSegmentVec.back();
682 titleOU = decodePathSegment(titleOU);
683 title = OString(titleOU.getStr(),
684 titleOU.getLength(),
685 RTL_TEXTENCODING_UTF8);
687 else
688 // will give an error
689 title = OString("/");
691 OString aDel("del "); aDel += title;
692 OString mkd("mkd "); mkd += title;
694 struct curl_slist *slist = 0;
696 FTPDirentry aDirentry(direntry());
697 if(!ReplaceExisting) {
698 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
699 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
700 throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
701 } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
702 slist = curl_slist_append(slist,aDel.getStr());
704 slist = curl_slist_append(slist,mkd.getStr());
706 CURL *curl = m_pFCP->handle();
707 SET_CONTROL_CONTAINER;
708 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
709 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
711 // post request
712 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
714 OUString url(parent(true));
715 if(!url.endsWith("/"))
716 url += "/";
717 SET_URL(url);
719 CURLcode err = curl_easy_perform(curl);
720 curl_slist_free_all(slist);
721 if(err != CURLE_OK)
722 throw curl_exception(err);
726 OUString FTPURL::ren(const OUString& NewTitle)
727 throw(curl_exception)
729 CURL *curl = m_pFCP->handle();
731 // post request
732 OString renamefrom("RNFR ");
733 OUString OldTitle = net_title();
734 renamefrom +=
735 OString(OldTitle.getStr(),
736 OldTitle.getLength(),
737 RTL_TEXTENCODING_UTF8);
739 OString renameto("RNTO ");
740 renameto +=
741 OString(NewTitle.getStr(),
742 NewTitle.getLength(),
743 RTL_TEXTENCODING_UTF8);
745 struct curl_slist *slist = 0;
746 slist = curl_slist_append(slist,renamefrom.getStr());
747 slist = curl_slist_append(slist,renameto.getStr());
748 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
750 SET_CONTROL_CONTAINER;
751 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
752 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
754 OUString url(parent(true));
755 if(!url.endsWith("/"))
756 url += "/";
757 SET_URL(url);
759 CURLcode err = curl_easy_perform(curl);
760 curl_slist_free_all(slist);
761 if(err != CURLE_OK)
762 throw curl_exception(err);
763 else if( m_aPathSegmentVec.size() && m_aPathSegmentVec.back() != ".." )
764 m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
765 return OldTitle;
770 void FTPURL::del() const
771 throw(curl_exception, malformed_exception)
773 FTPDirentry aDirentry(direntry());
775 OString dele(aDirentry.m_aName.getStr(),
776 aDirentry.m_aName.getLength(),
777 RTL_TEXTENCODING_UTF8);
779 if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
780 std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
781 for( unsigned int i = 0; i < vec.size(); ++i )
782 try {
783 FTPURL url(vec[i].m_aURL,m_pFCP);
784 url.del();
785 } catch(const curl_exception&) {
787 dele = OString("RMD ") + dele;
789 else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
790 dele = OString("DELE ") + dele;
791 else
792 return;
794 // post request
795 CURL *curl = m_pFCP->handle();
796 struct curl_slist *slist = 0;
797 slist = curl_slist_append(slist,dele.getStr());
798 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
800 SET_CONTROL_CONTAINER;
801 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
802 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
804 OUString url(parent(true));
805 if(!url.endsWith("/"))
806 url += "/";
807 SET_URL(url);
809 CURLcode err = curl_easy_perform(curl);
810 curl_slist_free_all(slist);
811 if(err != CURLE_OK)
812 throw curl_exception(err);
815 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */