fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / ucb / source / ucp / ftp / ftpurl.cxx
blobecee9edbcffeafe224743747ea2d28b0ad8c8167
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 <memory>
27 #include <rtl/ustrbuf.hxx>
28 #include <com/sun/star/ucb/OpenMode.hpp>
29 #include <string.h>
30 #include <rtl/uri.hxx>
32 #include "ftpstrcont.hxx"
33 #include "ftpurl.hxx"
34 #include "ftphandleprovider.hxx"
35 #include "ftpcfunc.hxx"
36 #include "ftpcontainer.hxx"
38 using namespace ftp;
39 using namespace com::sun::star::ucb;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::io;
43 namespace {
45 OUString encodePathSegment(OUString const & decoded) {
46 return rtl::Uri::encode(
47 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
48 RTL_TEXTENCODING_UTF8);
51 OUString decodePathSegment(OUString const & encoded) {
52 return rtl::Uri::decode(
53 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
58 MemoryContainer::MemoryContainer()
59 : m_nLen(0),
60 m_nWritePos(0),
61 m_pBuffer(0)
65 MemoryContainer::~MemoryContainer()
67 rtl_freeMemory(m_pBuffer);
71 int MemoryContainer::append(
72 const void* pBuffer,
73 size_t size,
74 size_t nmemb
75 ) throw()
77 sal_uInt32 nLen = size*nmemb;
78 sal_uInt32 tmp(nLen + m_nWritePos);
80 if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
81 do {
82 m_nLen+=1024;
83 } while(m_nLen < tmp);
85 m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen);
88 memcpy(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
89 pBuffer,nLen);
90 m_nWritePos = tmp;
91 return nLen;
95 extern "C" {
97 int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
99 MemoryContainer *_stream =
100 reinterpret_cast<MemoryContainer*>(stream);
102 if(!_stream)
103 return 0;
105 return _stream->append(buffer,size,nmemb);
111 FTPURL::FTPURL(const FTPURL& r)
112 : m_mutex(),
113 m_pFCP(r.m_pFCP),
114 m_aUsername(r.m_aUsername),
115 m_bShowPassword(r.m_bShowPassword),
116 m_aHost(r.m_aHost),
117 m_aPort(r.m_aPort),
118 m_aPathSegmentVec(r.m_aPathSegmentVec)
124 FTPURL::FTPURL(const OUString& url,
125 FTPHandleProvider* pFCP)
126 throw(
127 malformed_exception
129 : m_pFCP(pFCP),
130 m_aUsername("anonymous"),
131 m_bShowPassword(false),
132 m_aPort("21")
134 parse(url); // can reset m_bShowPassword
138 FTPURL::~FTPURL()
143 void FTPURL::parse(const OUString& url)
144 throw(
145 malformed_exception
148 OUString aPassword,aAccount;
149 OString aIdent(url.getStr(),
150 url.getLength(),
151 RTL_TEXTENCODING_UTF8);
153 OString lower = aIdent.toAsciiLowerCase();
154 if(lower.getLength() < 6 ||
155 strncmp("ftp://",lower.getStr(),6))
156 throw malformed_exception();
158 char *buffer = new char[1+aIdent.getLength()];
159 const char* p2 = aIdent.getStr();
160 p2 += 6;
162 char ch;
163 char *p1 = buffer; // determine "username:password@host:port"
164 while((ch = *p2++) != '/' && ch)
165 *p1++ = ch;
166 *p1 = 0;
168 OUString aExpr(OUString(buffer,strlen(buffer),
169 RTL_TEXTENCODING_UTF8));
171 sal_Int32 l = aExpr.indexOf(sal_Unicode('@'));
172 m_aHost = aExpr.copy(1+l);
174 if(l != -1) {
175 // Now username and password.
176 aExpr = aExpr.copy(0,l);
177 l = aExpr.indexOf(sal_Unicode(':'));
178 if(l != -1) {
179 aPassword = aExpr.copy(1+l);
180 if(!aPassword.isEmpty())
181 m_bShowPassword = true;
183 if(l > 0)
184 // Overwritte only if the username is not empty.
185 m_aUsername = aExpr.copy(0,l);
186 else if(!aExpr.isEmpty())
187 m_aUsername = aExpr;
190 l = m_aHost.lastIndexOf(sal_Unicode(':'));
191 sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']'));
192 if((ipv6Back == -1 && l != -1) // not ipv6, but a port
194 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
197 if(1+l<m_aHost.getLength())
198 m_aPort = m_aHost.copy(1+l);
199 m_aHost = m_aHost.copy(0,l);
202 while(ch) { // now determine the pathsegments ...
203 p1 = buffer;
204 while((ch = *p2++) != '/' && ch)
205 *p1++ = ch;
206 *p1 = 0;
208 if(buffer[0]) {
209 if( strcmp(buffer,"..") == 0 && !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." )
210 m_aPathSegmentVec.pop_back();
211 else if(strcmp(buffer,".") == 0)
212 ; // Ignore
213 else
214 // This is a legal name.
215 m_aPathSegmentVec.push_back(
216 OUString(buffer,
217 strlen(buffer),
218 RTL_TEXTENCODING_UTF8));
222 delete[] buffer;
224 if(m_bShowPassword)
225 m_pFCP->setHost(m_aHost,
226 m_aPort,
227 m_aUsername,
228 aPassword,
229 aAccount);
231 // now check for something like ";type=i" at end of url
232 if(m_aPathSegmentVec.size() &&
233 (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) {
234 m_aType = m_aPathSegmentVec.back().copy(l);
235 m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
240 OUString FTPURL::ident(bool withslash,bool internal) const
242 // rebuild the url as one without ellipses,
243 // and more important, as one without username and
244 // password. ( These are set together with the command. )
246 OUStringBuffer bff;
247 bff.appendAscii("ftp://");
249 if( m_aUsername != "anonymous" ) {
250 bff.append(m_aUsername);
252 OUString aPassword,aAccount;
253 m_pFCP->forHost(m_aHost,
254 m_aPort,
255 m_aUsername,
256 aPassword,
257 aAccount);
259 if((m_bShowPassword || internal) &&
260 !aPassword.isEmpty() )
261 bff.append(sal_Unicode(':'))
262 .append(aPassword);
264 bff.append(sal_Unicode('@'));
266 bff.append(m_aHost);
268 if( m_aPort != "21" )
269 bff.append(sal_Unicode(':'))
270 .append(m_aPort)
271 .append(sal_Unicode('/'));
272 else
273 bff.append(sal_Unicode('/'));
275 for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i)
276 if(i == 0)
277 bff.append(m_aPathSegmentVec[i]);
278 else
279 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
280 if(withslash)
281 if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/'))
282 bff.append(sal_Unicode('/'));
284 bff.append(m_aType);
285 return bff.makeStringAndClear();
289 OUString FTPURL::parent(bool internal) const
291 OUStringBuffer bff;
293 bff.appendAscii("ftp://");
295 if( m_aUsername != "anonymous" ) {
296 bff.append(m_aUsername);
298 OUString aPassword,aAccount;
299 m_pFCP->forHost(m_aHost,
300 m_aPort,
301 m_aUsername,
302 aPassword,
303 aAccount);
305 if((internal || m_bShowPassword) && !aPassword.isEmpty())
306 bff.append(sal_Unicode(':'))
307 .append(aPassword);
309 bff.append(sal_Unicode('@'));
312 bff.append(m_aHost);
314 if( m_aPort != "21" )
315 bff.append(sal_Unicode(':'))
316 .append(m_aPort)
317 .append(sal_Unicode('/'));
318 else
319 bff.append(sal_Unicode('/'));
321 OUString last;
323 for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i)
324 if(1+i == m_aPathSegmentVec.size())
325 last = m_aPathSegmentVec[i];
326 else if(i == 0)
327 bff.append(m_aPathSegmentVec[i]);
328 else
329 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
331 if(last.isEmpty())
332 bff.appendAscii("..");
333 else if ( last == ".." )
334 bff.append(last).appendAscii("/..");
336 bff.append(m_aType);
337 return bff.makeStringAndClear();
341 void FTPURL::child(const OUString& title)
343 m_aPathSegmentVec.push_back(encodePathSegment(title));
347 OUString FTPURL::child() const
349 return
350 m_aPathSegmentVec.size() ?
351 decodePathSegment(m_aPathSegmentVec.back()) : OUString();
356 /** Listing of a directory.
359 namespace ftp {
361 enum OS {
362 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
368 #define SET_CONTROL_CONTAINER \
369 MemoryContainer control; \
370 curl_easy_setopt(curl, \
371 CURLOPT_HEADERFUNCTION, \
372 memory_write); \
373 curl_easy_setopt(curl, \
374 CURLOPT_WRITEHEADER, \
375 &control)
378 #define SET_DATA_CONTAINER \
379 curl_easy_setopt(curl,CURLOPT_NOBODY,false); \
380 MemoryContainer data; \
381 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \
382 curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data)
384 #define SET_URL(url) \
385 OString urlParAscii(url.getStr(), \
386 url.getLength(), \
387 RTL_TEXTENCODING_UTF8); \
388 curl_easy_setopt(curl, \
389 CURLOPT_URL, \
390 urlParAscii.getStr());
392 FILE* FTPURL::open()
393 throw(curl_exception)
395 if(m_aPathSegmentVec.empty())
396 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
398 CURL *curl = m_pFCP->handle();
400 SET_CONTROL_CONTAINER;
401 OUString url(ident(false,true));
402 SET_URL(url);
403 FILE *res = tmpfile();
404 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
405 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
407 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
408 CURLcode err = curl_easy_perform(curl);
410 if(err == CURLE_OK)
411 rewind(res);
412 else {
413 fclose(res),res = 0;
414 throw curl_exception(err);
417 return res;
421 std::vector<FTPDirentry> FTPURL::list(
422 sal_Int16 nMode
423 ) const
424 throw(
425 curl_exception
428 CURL *curl = m_pFCP->handle();
430 SET_CONTROL_CONTAINER;
431 SET_DATA_CONTAINER;
432 OUString url(ident(true,true));
433 SET_URL(url);
434 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
436 CURLcode err = curl_easy_perform(curl);
437 if(err != CURLE_OK)
438 throw curl_exception(err);
440 // now evaluate the error messages
442 sal_uInt32 len = data.m_nWritePos;
443 char* fwd = (char*) data.m_pBuffer;
444 char *p1, *p2;
445 p1 = p2 = fwd;
447 OS osKind(FTP_UNKNOWN);
448 std::vector<FTPDirentry> resvec;
449 FTPDirentry aDirEntry;
450 // ensure slash at the end
451 OUString viewurl(ident(true,false));
453 while(true) {
454 while(p2-fwd < int(len) && *p2 != '\n') ++p2;
455 if(p2-fwd == int(len)) break;
457 *p2 = 0;
458 switch(osKind) {
459 // While FTP knows the 'system'-command,
460 // which returns the operating system type,
461 // this is not usable here: There are Windows-server
462 // formatting the output like UNIX-ls command.
463 case FTP_DOS:
464 FTPDirectoryParser::parseDOS(aDirEntry,p1);
465 break;
466 case FTP_UNIX:
467 FTPDirectoryParser::parseUNIX(aDirEntry,p1);
468 break;
469 case FTP_VMS:
470 FTPDirectoryParser::parseVMS(aDirEntry,p1);
471 break;
472 default:
473 if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
474 osKind = FTP_UNIX;
475 else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
476 osKind = FTP_DOS;
477 else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
478 osKind = FTP_VMS;
480 aDirEntry.m_aName = aDirEntry.m_aName.trim();
481 if( osKind != int(FTP_UNKNOWN) && aDirEntry.m_aName != ".." && aDirEntry.m_aName != "." ) {
482 aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
484 sal_Bool isDir =
485 sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR);
486 switch(nMode) {
487 case OpenMode::DOCUMENTS:
488 if(!isDir)
489 resvec.push_back(aDirEntry);
490 break;
491 case OpenMode::FOLDERS:
492 if(isDir)
493 resvec.push_back(aDirEntry);
494 break;
495 default:
496 resvec.push_back(aDirEntry);
499 aDirEntry.clear();
500 p1 = p2 + 1;
503 return resvec;
507 OUString FTPURL::net_title() const
508 throw(curl_exception)
510 CURL *curl = m_pFCP->handle();
512 SET_CONTROL_CONTAINER;
513 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
514 struct curl_slist *slist = 0;
515 // post request
516 slist = curl_slist_append(slist,"PWD");
517 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
519 bool try_more(true);
520 CURLcode err;
521 OUString aNetTitle;
523 while(true) {
524 OUString url(ident(false,true));
526 if(try_more &&
527 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
528 url += OUString("/"); // add end-slash
529 else if(!try_more &&
530 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength())
531 url = url.copy(0,url.getLength()-1); // remove end-slash
533 SET_URL(url);
534 err = curl_easy_perform(curl);
536 if(err == CURLE_OK) { // get the title from the server
537 char* fwd = (char*) control.m_pBuffer;
538 sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
540 aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8);
541 // the buffer now contains the name of the file;
542 // analyze the output:
543 // Format of current working directory:
544 // 257 "/bla/bla" is current directory
545 sal_Int32 index1 = aNetTitle.lastIndexOf(
546 OUString("257"));
547 index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1);
548 sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1);
549 aNetTitle = aNetTitle.copy(index1,index2-index1);
550 if( aNetTitle != "/" ) {
551 index1 = aNetTitle.lastIndexOf(sal_Unicode('/'));
552 aNetTitle = aNetTitle.copy(1+index1);
554 try_more = false;
555 } else if(err == CURLE_BAD_PASSWORD_ENTERED)
556 // the client should retry after getting the correct
557 // username + password
558 throw curl_exception(err);
559 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
560 else if(err == CURLE_LOGIN_DENIED)
561 // the client should retry after getting the correct
562 // username + password
563 throw curl_exception(err);
564 #endif
565 else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
566 // We were either denied access when trying to login to
567 // an FTP server or when trying to change working directory
568 // to the one given in the URL.
569 if(!m_aPathSegmentVec.empty())
570 // determine title form url
571 aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
572 else
573 // must be root
574 aNetTitle = OUString("/");
575 try_more = false;
578 if(try_more)
579 try_more = false;
580 else
581 break;
584 curl_slist_free_all(slist);
585 return aNetTitle;
589 FTPDirentry FTPURL::direntry() const
590 throw(curl_exception)
592 OUString nettitle = net_title();
593 FTPDirentry aDirentry;
595 aDirentry.m_aName = nettitle; // init aDirentry
596 if( nettitle == "/" || nettitle == ".." )
597 aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
598 else
599 aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
601 aDirentry.m_nSize = 0;
603 if( nettitle != "/" ) {
604 // try to open the parent directory
605 FTPURL aURL(parent(),m_pFCP);
607 std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
609 for(unsigned i = 0; i < aList.size(); ++i) {
610 if(aList[i].m_aName == nettitle) { // the relevant file is found
611 aDirentry = aList[i];
612 break;
616 return aDirentry;
620 extern "C" {
622 size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
624 sal_Int32 nRequested = sal_Int32(size*nmemb);
625 CurlInput *curlInput = static_cast<CurlInput*>(stream);
626 if(curlInput)
627 return size_t(curlInput->read(((sal_Int8*)ptr),nRequested));
628 else
629 return 0;
635 void FTPURL::insert(bool replaceExisting,void* stream) const
636 throw(curl_exception)
638 if(!replaceExisting) {
639 // FTPDirentry aDirentry(direntry());
640 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
641 // throw curl_exception(FILE_EXIST_DURING_INSERT);
642 throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
643 } // else
644 // overwrite is default in libcurl
646 CURL *curl = m_pFCP->handle();
648 SET_CONTROL_CONTAINER;
649 curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
650 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
651 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
652 curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
653 curl_easy_setopt(curl,CURLOPT_READDATA,stream);
654 curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
656 OUString url(ident(false,true));
657 SET_URL(url);
659 CURLcode err = curl_easy_perform(curl);
660 curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
662 if(err != CURLE_OK)
663 throw curl_exception(err);
668 void FTPURL::mkdir(bool ReplaceExisting) const
669 throw(curl_exception)
671 OString title;
672 if(!m_aPathSegmentVec.empty()) {
673 OUString titleOU = m_aPathSegmentVec.back();
674 titleOU = decodePathSegment(titleOU);
675 title = OString(titleOU.getStr(),
676 titleOU.getLength(),
677 RTL_TEXTENCODING_UTF8);
679 else
680 // will give an error
681 title = OString("/");
683 OString aDel("del "); aDel += title;
684 OString mkd("mkd "); mkd += title;
686 struct curl_slist *slist = 0;
688 FTPDirentry aDirentry(direntry());
689 if(!ReplaceExisting) {
690 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
691 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
692 throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
693 } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
694 slist = curl_slist_append(slist,aDel.getStr());
696 slist = curl_slist_append(slist,mkd.getStr());
698 CURL *curl = m_pFCP->handle();
699 SET_CONTROL_CONTAINER;
700 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
701 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
703 // post request
704 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
706 OUString url(parent(true));
707 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
708 url += OUString("/");
709 SET_URL(url);
711 CURLcode err = curl_easy_perform(curl);
712 curl_slist_free_all(slist);
713 if(err != CURLE_OK)
714 throw curl_exception(err);
718 OUString FTPURL::ren(const OUString& NewTitle)
719 throw(curl_exception)
721 CURL *curl = m_pFCP->handle();
723 // post request
724 OString renamefrom("RNFR ");
725 OUString OldTitle = net_title();
726 renamefrom +=
727 OString(OldTitle.getStr(),
728 OldTitle.getLength(),
729 RTL_TEXTENCODING_UTF8);
731 OString renameto("RNTO ");
732 renameto +=
733 OString(NewTitle.getStr(),
734 NewTitle.getLength(),
735 RTL_TEXTENCODING_UTF8);
737 struct curl_slist *slist = 0;
738 slist = curl_slist_append(slist,renamefrom.getStr());
739 slist = curl_slist_append(slist,renameto.getStr());
740 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
742 SET_CONTROL_CONTAINER;
743 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
744 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
746 OUString url(parent(true));
747 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
748 url += OUString("/");
749 SET_URL(url);
751 CURLcode err = curl_easy_perform(curl);
752 curl_slist_free_all(slist);
753 if(err != CURLE_OK)
754 throw curl_exception(err);
755 else if( m_aPathSegmentVec.size() && m_aPathSegmentVec.back() != ".." )
756 m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
757 return OldTitle;
762 void FTPURL::del() const
763 throw(curl_exception)
765 FTPDirentry aDirentry(direntry());
767 OString dele(aDirentry.m_aName.getStr(),
768 aDirentry.m_aName.getLength(),
769 RTL_TEXTENCODING_UTF8);
771 if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
772 std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
773 for( unsigned int i = 0; i < vec.size(); ++i )
774 try {
775 FTPURL url(vec[i].m_aURL,m_pFCP);
776 url.del();
777 } catch(const curl_exception&) {
779 dele = OString("RMD ") + dele;
781 else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
782 dele = OString("DELE ") + dele;
783 else
784 return;
786 // post request
787 CURL *curl = m_pFCP->handle();
788 struct curl_slist *slist = 0;
789 slist = curl_slist_append(slist,dele.getStr());
790 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
792 SET_CONTROL_CONTAINER;
793 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
794 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
796 OUString url(parent(true));
797 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
798 url += OUString("/");
799 SET_URL(url);
801 CURLcode err = curl_easy_perform(curl);
802 curl_slist_free_all(slist);
803 if(err != CURLE_OK)
804 throw curl_exception(err);
807 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */