Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / ftp / ftpurl.cxx
blob39f2a65686fa287f33488967fce16657098ff951
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 /**************************************************************************
30 TODO
31 **************************************************************************
33 *************************************************************************/
35 #include <memory>
36 #include <rtl/ustrbuf.hxx>
37 #include <com/sun/star/ucb/OpenMode.hpp>
38 #include <string.h>
39 #include <rtl/uri.hxx>
41 #include "ftpstrcont.hxx"
42 #include "ftpurl.hxx"
43 #include "ftphandleprovider.hxx"
44 #include "ftpcfunc.hxx"
45 #include "ftpcontainer.hxx"
47 using namespace ftp;
48 using namespace com::sun::star::ucb;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::io;
52 namespace {
54 rtl::OUString encodePathSegment(rtl::OUString const & decoded) {
55 return rtl::Uri::encode(
56 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
57 RTL_TEXTENCODING_UTF8);
60 rtl::OUString decodePathSegment(rtl::OUString const & encoded) {
61 return rtl::Uri::decode(
62 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
67 MemoryContainer::MemoryContainer()
68 : m_nLen(0),
69 m_nWritePos(0),
70 m_pBuffer(0)
74 MemoryContainer::~MemoryContainer()
76 rtl_freeMemory(m_pBuffer);
80 int MemoryContainer::append(
81 const void* pBuffer,
82 size_t size,
83 size_t nmemb
84 ) throw()
86 sal_uInt32 nLen = size*nmemb;
87 sal_uInt32 tmp(nLen + m_nWritePos);
89 if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
90 do {
91 m_nLen+=1024;
92 } while(m_nLen < tmp);
94 m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen);
97 rtl_copyMemory(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
98 pBuffer,nLen);
99 m_nWritePos = tmp;
100 return nLen;
104 extern "C" {
106 int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
108 MemoryContainer *_stream =
109 reinterpret_cast<MemoryContainer*>(stream);
111 if(!_stream)
112 return 0;
114 return _stream->append(buffer,size,nmemb);
120 FTPURL::FTPURL(const FTPURL& r)
121 : m_mutex(),
122 m_pFCP(r.m_pFCP),
123 m_aUsername(r.m_aUsername),
124 m_bShowPassword(r.m_bShowPassword),
125 m_aHost(r.m_aHost),
126 m_aPort(r.m_aPort),
127 m_aPathSegmentVec(r.m_aPathSegmentVec)
133 FTPURL::FTPURL(const rtl::OUString& url,
134 FTPHandleProvider* pFCP)
135 throw(
136 malformed_exception
138 : m_pFCP(pFCP),
139 m_aUsername("anonymous"),
140 m_bShowPassword(false),
141 m_aPort("21")
143 parse(url); // can reset m_bShowPassword
147 FTPURL::~FTPURL()
152 void FTPURL::parse(const rtl::OUString& url)
153 throw(
154 malformed_exception
157 rtl::OUString aPassword,aAccount;
158 rtl::OString aIdent(url.getStr(),
159 url.getLength(),
160 RTL_TEXTENCODING_UTF8);
162 rtl::OString lower = aIdent.toAsciiLowerCase();
163 if(lower.getLength() < 6 ||
164 strncmp("ftp://",lower.getStr(),6))
165 throw malformed_exception();
167 char *buffer = new char[1+aIdent.getLength()];
168 const char* p2 = aIdent.getStr();
169 p2 += 6;
171 char ch;
172 char *p1 = buffer; // determine "username:password@host:port"
173 while((ch = *p2++) != '/' && ch)
174 *p1++ = ch;
175 *p1 = 0;
177 rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer),
178 RTL_TEXTENCODING_UTF8));
180 sal_Int32 l = aExpr.indexOf(sal_Unicode('@'));
181 m_aHost = aExpr.copy(1+l);
183 if(l != -1) {
184 // Now username and password.
185 aExpr = aExpr.copy(0,l);
186 l = aExpr.indexOf(sal_Unicode(':'));
187 if(l != -1) {
188 aPassword = aExpr.copy(1+l);
189 if(!aPassword.isEmpty())
190 m_bShowPassword = true;
192 if(l > 0)
193 // Overwritte only if the username is not empty.
194 m_aUsername = aExpr.copy(0,l);
195 else if(!aExpr.isEmpty())
196 m_aUsername = aExpr;
199 l = m_aHost.lastIndexOf(sal_Unicode(':'));
200 sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']'));
201 if((ipv6Back == -1 && l != -1) // not ipv6, but a port
203 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
206 if(1+l<m_aHost.getLength())
207 m_aPort = m_aHost.copy(1+l);
208 m_aHost = m_aHost.copy(0,l);
211 while(ch) { // now determine the pathsegments ...
212 p1 = buffer;
213 while((ch = *p2++) != '/' && ch)
214 *p1++ = ch;
215 *p1 = 0;
217 if(buffer[0]) {
218 if( strcmp(buffer,"..") == 0 && m_aPathSegmentVec.size() && m_aPathSegmentVec.back() != ".." )
219 m_aPathSegmentVec.pop_back();
220 else if(strcmp(buffer,".") == 0)
221 ; // Ignore
222 else
223 // This is a legal name.
224 m_aPathSegmentVec.push_back(
225 rtl::OUString(buffer,
226 strlen(buffer),
227 RTL_TEXTENCODING_UTF8));
231 delete[] buffer;
233 if(m_bShowPassword)
234 m_pFCP->setHost(m_aHost,
235 m_aPort,
236 m_aUsername,
237 aPassword,
238 aAccount);
240 // now check for something like ";type=i" at end of url
241 if(m_aPathSegmentVec.size() &&
242 (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) {
243 m_aType = m_aPathSegmentVec.back().copy(l);
244 m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
249 rtl::OUString FTPURL::ident(bool withslash,bool internal) const
251 // rebuild the url as one without ellipses,
252 // and more important, as one without username and
253 // password. ( These are set together with the command. )
255 rtl::OUStringBuffer bff;
256 bff.appendAscii("ftp://");
258 if( m_aUsername != "anonymous" ) {
259 bff.append(m_aUsername);
261 rtl::OUString aPassword,aAccount;
262 m_pFCP->forHost(m_aHost,
263 m_aPort,
264 m_aUsername,
265 aPassword,
266 aAccount);
268 if((m_bShowPassword || internal) &&
269 !aPassword.isEmpty() )
270 bff.append(sal_Unicode(':'))
271 .append(aPassword);
273 bff.append(sal_Unicode('@'));
275 bff.append(m_aHost);
277 if( m_aPort != "21" )
278 bff.append(sal_Unicode(':'))
279 .append(m_aPort)
280 .append(sal_Unicode('/'));
281 else
282 bff.append(sal_Unicode('/'));
284 for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i)
285 if(i == 0)
286 bff.append(m_aPathSegmentVec[i]);
287 else
288 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
289 if(withslash)
290 if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/'))
291 bff.append(sal_Unicode('/'));
293 bff.append(m_aType);
294 return bff.makeStringAndClear();
298 rtl::OUString FTPURL::parent(bool internal) const
300 rtl::OUStringBuffer bff;
302 bff.appendAscii("ftp://");
304 if( m_aUsername != "anonymous" ) {
305 bff.append(m_aUsername);
307 rtl::OUString aPassword,aAccount;
308 m_pFCP->forHost(m_aHost,
309 m_aPort,
310 m_aUsername,
311 aPassword,
312 aAccount);
314 if((internal || m_bShowPassword) && !aPassword.isEmpty())
315 bff.append(sal_Unicode(':'))
316 .append(aPassword);
318 bff.append(sal_Unicode('@'));
321 bff.append(m_aHost);
323 if( m_aPort != "21" )
324 bff.append(sal_Unicode(':'))
325 .append(m_aPort)
326 .append(sal_Unicode('/'));
327 else
328 bff.append(sal_Unicode('/'));
330 rtl::OUString last;
332 for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i)
333 if(1+i == m_aPathSegmentVec.size())
334 last = m_aPathSegmentVec[i];
335 else if(i == 0)
336 bff.append(m_aPathSegmentVec[i]);
337 else
338 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
340 if(last.isEmpty())
341 bff.appendAscii("..");
342 else if ( last == ".." )
343 bff.append(last).appendAscii("/..");
345 bff.append(m_aType);
346 return bff.makeStringAndClear();
350 void FTPURL::child(const rtl::OUString& title)
352 m_aPathSegmentVec.push_back(encodePathSegment(title));
356 rtl::OUString FTPURL::child() const
358 return
359 m_aPathSegmentVec.size() ?
360 decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString();
365 /** Listing of a directory.
368 namespace ftp {
370 enum OS {
371 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
377 #define SET_CONTROL_CONTAINER \
378 MemoryContainer control; \
379 curl_easy_setopt(curl, \
380 CURLOPT_HEADERFUNCTION, \
381 memory_write); \
382 curl_easy_setopt(curl, \
383 CURLOPT_WRITEHEADER, \
384 &control)
387 #define SET_DATA_CONTAINER \
388 curl_easy_setopt(curl,CURLOPT_NOBODY,false); \
389 MemoryContainer data; \
390 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \
391 curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data)
393 #define SET_URL(url) \
394 rtl::OString urlParAscii(url.getStr(), \
395 url.getLength(), \
396 RTL_TEXTENCODING_UTF8); \
397 curl_easy_setopt(curl, \
398 CURLOPT_URL, \
399 urlParAscii.getStr());
401 // Setting username:password
402 #define SET_USER_PASSWORD(username,password) \
403 rtl::OUString combi(username + \
404 rtl::OUString(":") + \
405 password); \
406 rtl::OString aUserPsswd(combi.getStr(), \
407 combi.getLength(), \
408 RTL_TEXTENCODING_UTF8); \
409 curl_easy_setopt(curl, \
410 CURLOPT_USERPWD, \
411 aUserPsswd.getStr())
415 FILE* FTPURL::open()
416 throw(curl_exception)
418 if(m_aPathSegmentVec.empty())
419 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
421 CURL *curl = m_pFCP->handle();
423 SET_CONTROL_CONTAINER;
424 rtl::OUString url(ident(false,true));
425 SET_URL(url);
426 FILE *res = tmpfile();
427 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
428 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
430 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
431 CURLcode err = curl_easy_perform(curl);
433 if(err == CURLE_OK)
434 rewind(res);
435 else {
436 fclose(res),res = 0;
437 throw curl_exception(err);
440 return res;
444 std::vector<FTPDirentry> FTPURL::list(
445 sal_Int16 nMode
446 ) const
447 throw(
448 curl_exception
451 CURL *curl = m_pFCP->handle();
453 SET_CONTROL_CONTAINER;
454 SET_DATA_CONTAINER;
455 rtl::OUString url(ident(true,true));
456 SET_URL(url);
457 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
459 CURLcode err = curl_easy_perform(curl);
460 if(err != CURLE_OK)
461 throw curl_exception(err);
463 // now evaluate the error messages
465 sal_uInt32 len = data.m_nWritePos;
466 char* fwd = (char*) data.m_pBuffer;
467 rtl::OString str(fwd,len);
468 char *p1, *p2;
469 p1 = p2 = fwd;
471 OS osKind(FTP_UNKNOWN);
472 std::vector<FTPDirentry> resvec;
473 FTPDirentry aDirEntry;
474 // ensure slash at the end
475 rtl::OUString viewurl(ident(true,false));
477 while(true) {
478 while(p2-fwd < int(len) && *p2 != '\n') ++p2;
479 if(p2-fwd == int(len)) break;
481 *p2 = 0;
482 switch(osKind) {
483 // While FTP knows the 'system'-command,
484 // which returns the operating system type,
485 // this is not usable here: There are Windows-server
486 // formatting the output like UNIX-ls command.
487 case FTP_DOS:
488 FTPDirectoryParser::parseDOS(aDirEntry,p1);
489 break;
490 case FTP_UNIX:
491 FTPDirectoryParser::parseUNIX(aDirEntry,p1);
492 break;
493 case FTP_VMS:
494 FTPDirectoryParser::parseVMS(aDirEntry,p1);
495 break;
496 default:
497 if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
498 osKind = FTP_UNIX;
499 else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
500 osKind = FTP_DOS;
501 else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
502 osKind = FTP_VMS;
504 aDirEntry.m_aName = aDirEntry.m_aName.trim();
505 if( osKind != int(FTP_UNKNOWN) && aDirEntry.m_aName != ".." && aDirEntry.m_aName != "." ) {
506 aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
508 sal_Bool isDir =
509 sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR);
510 switch(nMode) {
511 case OpenMode::DOCUMENTS:
512 if(!isDir)
513 resvec.push_back(aDirEntry);
514 break;
515 case OpenMode::FOLDERS:
516 if(isDir)
517 resvec.push_back(aDirEntry);
518 break;
519 default:
520 resvec.push_back(aDirEntry);
523 aDirEntry.clear();
524 p1 = p2 + 1;
527 return resvec;
531 rtl::OUString FTPURL::net_title() const
532 throw(curl_exception)
534 CURL *curl = m_pFCP->handle();
536 SET_CONTROL_CONTAINER;
537 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
538 struct curl_slist *slist = 0;
539 // post request
540 slist = curl_slist_append(slist,"PWD");
541 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
543 bool try_more(true);
544 CURLcode err;
545 rtl::OUString aNetTitle;
547 while(true) {
548 rtl::OUString url(ident(false,true));
550 if(try_more &&
551 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
552 url += rtl::OUString("/"); // add end-slash
553 else if(!try_more &&
554 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength())
555 url = url.copy(0,url.getLength()-1); // remove end-slash
557 SET_URL(url);
558 err = curl_easy_perform(curl);
560 if(err == CURLE_OK) { // get the title from the server
561 char* fwd = (char*) control.m_pBuffer;
562 sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
564 aNetTitle = rtl::OUString(fwd,len,RTL_TEXTENCODING_UTF8);
565 // the buffer now contains the name of the file;
566 // analyze the output:
567 // Format of current working directory:
568 // 257 "/bla/bla" is current directory
569 sal_Int32 index1 = aNetTitle.lastIndexOf(
570 rtl::OUString("257"));
571 index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1);
572 sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1);
573 aNetTitle = aNetTitle.copy(index1,index2-index1);
574 if( aNetTitle != "/" ) {
575 index1 = aNetTitle.lastIndexOf(sal_Unicode('/'));
576 aNetTitle = aNetTitle.copy(1+index1);
578 try_more = false;
579 } else if(err == CURLE_BAD_PASSWORD_ENTERED)
580 // the client should retry after getting the correct
581 // username + password
582 throw curl_exception(err);
583 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
584 else if(err == CURLE_LOGIN_DENIED)
585 // the client should retry after getting the correct
586 // username + password
587 throw curl_exception(err);
588 #endif
589 else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
590 // We were either denied access when trying to login to
591 // an FTP server or when trying to change working directory
592 // to the one given in the URL.
593 if(!m_aPathSegmentVec.empty())
594 // determine title form url
595 aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
596 else
597 // must be root
598 aNetTitle = rtl::OUString("/");
599 try_more = false;
602 if(try_more)
603 try_more = false;
604 else
605 break;
608 curl_slist_free_all(slist);
609 return aNetTitle;
613 FTPDirentry FTPURL::direntry() const
614 throw(curl_exception)
616 rtl::OUString nettitle = net_title();
617 FTPDirentry aDirentry;
619 aDirentry.m_aName = nettitle; // init aDirentry
620 if( nettitle == "/" || nettitle == ".." )
621 aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
622 else
623 aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
625 aDirentry.m_nSize = 0;
627 if( nettitle != "/" ) {
628 // try to open the parent directory
629 FTPURL aURL(parent(),m_pFCP);
631 std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
633 for(unsigned i = 0; i < aList.size(); ++i) {
634 if(aList[i].m_aName == nettitle) { // the relevant file is found
635 aDirentry = aList[i];
636 break;
640 return aDirentry;
644 extern "C" {
646 size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
648 sal_Int32 nRequested = sal_Int32(size*nmemb);
649 CurlInput *curlInput = static_cast<CurlInput*>(stream);
650 if(curlInput)
651 return size_t(curlInput->read(((sal_Int8*)ptr),nRequested));
652 else
653 return 0;
659 void FTPURL::insert(bool replaceExisting,void* stream) const
660 throw(curl_exception)
662 if(!replaceExisting) {
663 // FTPDirentry aDirentry(direntry());
664 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
665 // throw curl_exception(FILE_EXIST_DURING_INSERT);
666 throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
667 } // else
668 // overwrite is default in libcurl
670 CURL *curl = m_pFCP->handle();
672 SET_CONTROL_CONTAINER;
673 curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
674 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
675 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
676 curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
677 curl_easy_setopt(curl,CURLOPT_READDATA,stream);
678 curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
680 rtl::OUString url(ident(false,true));
681 SET_URL(url);
683 CURLcode err = curl_easy_perform(curl);
684 curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
686 if(err != CURLE_OK)
687 throw curl_exception(err);
692 void FTPURL::mkdir(bool ReplaceExisting) const
693 throw(curl_exception)
695 rtl::OString title;
696 if(!m_aPathSegmentVec.empty()) {
697 rtl::OUString titleOU = m_aPathSegmentVec.back();
698 titleOU = decodePathSegment(titleOU);
699 title = rtl::OString(titleOU.getStr(),
700 titleOU.getLength(),
701 RTL_TEXTENCODING_UTF8);
703 else
704 // will give an error
705 title = rtl::OString("/");
707 rtl::OString aDel("del "); aDel += title;
708 rtl::OString mkd("mkd "); mkd += title;
710 struct curl_slist *slist = 0;
712 FTPDirentry aDirentry(direntry());
713 if(!ReplaceExisting) {
714 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
715 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
716 throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
717 } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
718 slist = curl_slist_append(slist,aDel.getStr());
720 slist = curl_slist_append(slist,mkd.getStr());
722 CURL *curl = m_pFCP->handle();
723 SET_CONTROL_CONTAINER;
724 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
725 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
727 // post request
728 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
730 rtl::OUString url(parent(true));
731 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
732 url += rtl::OUString("/");
733 SET_URL(url);
735 CURLcode err = curl_easy_perform(curl);
736 curl_slist_free_all(slist);
737 if(err != CURLE_OK)
738 throw curl_exception(err);
742 rtl::OUString FTPURL::ren(const rtl::OUString& NewTitle)
743 throw(curl_exception)
745 CURL *curl = m_pFCP->handle();
747 // post request
748 rtl::OString renamefrom("RNFR ");
749 rtl::OUString OldTitle = net_title();
750 renamefrom +=
751 rtl::OString(OldTitle.getStr(),
752 OldTitle.getLength(),
753 RTL_TEXTENCODING_UTF8);
755 rtl::OString renameto("RNTO ");
756 renameto +=
757 rtl::OString(NewTitle.getStr(),
758 NewTitle.getLength(),
759 RTL_TEXTENCODING_UTF8);
761 struct curl_slist *slist = 0;
762 slist = curl_slist_append(slist,renamefrom.getStr());
763 slist = curl_slist_append(slist,renameto.getStr());
764 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
766 SET_CONTROL_CONTAINER;
767 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
768 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
770 rtl::OUString url(parent(true));
771 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
772 url += rtl::OUString("/");
773 SET_URL(url);
775 CURLcode err = curl_easy_perform(curl);
776 curl_slist_free_all(slist);
777 if(err != CURLE_OK)
778 throw curl_exception(err);
779 else if( m_aPathSegmentVec.size() && m_aPathSegmentVec.back() != ".." )
780 m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
781 return OldTitle;
786 void FTPURL::del() const
787 throw(curl_exception)
789 FTPDirentry aDirentry(direntry());
791 rtl::OString dele(aDirentry.m_aName.getStr(),
792 aDirentry.m_aName.getLength(),
793 RTL_TEXTENCODING_UTF8);
795 if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
796 std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
797 for( unsigned int i = 0; i < vec.size(); ++i )
798 try {
799 FTPURL url(vec[i].m_aURL,m_pFCP);
800 url.del();
801 } catch(const curl_exception&) {
803 dele = rtl::OString("RMD ") + dele;
805 else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
806 dele = rtl::OString("DELE ") + dele;
807 else
808 return;
810 // post request
811 CURL *curl = m_pFCP->handle();
812 struct curl_slist *slist = 0;
813 slist = curl_slist_append(slist,dele.getStr());
814 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
816 SET_CONTROL_CONTAINER;
817 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
818 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
820 rtl::OUString url(parent(true));
821 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
822 url += rtl::OUString("/");
823 SET_URL(url);
825 CURLcode err = curl_easy_perform(curl);
826 curl_slist_free_all(slist);
827 if(err != CURLE_OK)
828 throw curl_exception(err);
831 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */