1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ftp.hxx"
26 /**************************************************************************
27 TODO
28 **************************************************************************
29
30 *************************************************************************/
31
32 #include <memory>
33 #include <rtl/ustrbuf.hxx>
34 #include <com/sun/star/ucb/OpenMode.hpp>
35 #include <string.h>
36 #include <rtl/uri.hxx>
37
38 #include "ftpstrcont.hxx"
39 #include "ftpurl.hxx"
40 #include "ftphandleprovider.hxx"
41 #include "ftpinpstr.hxx"
42 #include "ftpcfunc.hxx"
43 #include "ftpcontainer.hxx"
44
45 using namespace ftp;
46 using namespace com::sun::star::ucb;
47 using namespace com::sun::star::uno;
48 using namespace com::sun::star::io;
49
50 namespace {
51
encodePathSegment(rtl::OUString const & decoded)52 rtl::OUString encodePathSegment(rtl::OUString const & decoded) {
53 return rtl::Uri::encode(
54 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
55 RTL_TEXTENCODING_UTF8);
56 }
57
decodePathSegment(rtl::OUString const & encoded)58 rtl::OUString decodePathSegment(rtl::OUString const & encoded) {
59 return rtl::Uri::decode(
60 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
61 }
62
63 }
64
MemoryContainer()65 MemoryContainer::MemoryContainer()
66 : m_nLen(0),
67 m_nWritePos(0),
68 m_pBuffer(0)
69 {
70 }
71
~MemoryContainer()72 MemoryContainer::~MemoryContainer()
73 {
74 rtl_freeMemory(m_pBuffer);
75 }
76
77
append(const void * pBuffer,size_t size,size_t nmemb)78 int MemoryContainer::append(
79 const void* pBuffer,
80 size_t size,
81 size_t nmemb
82 ) throw()
83 {
84 sal_uInt32 nLen = size*nmemb;
85 sal_uInt32 tmp(nLen + m_nWritePos);
86
87 if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
88 do {
89 m_nLen+=1024;
90 } while(m_nLen < tmp);
91
92 m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen);
93 }
94
95 rtl_copyMemory(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
96 pBuffer,nLen);
97 m_nWritePos = tmp;
98 return nLen;
99 }
100
101
102 extern "C" {
103
memory_write(void * buffer,size_t size,size_t nmemb,void * stream)104 int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
105 {
106 MemoryContainer *_stream =
107 reinterpret_cast<MemoryContainer*>(stream);
108
109 if(!_stream)
110 return 0;
111
112 return _stream->append(buffer,size,nmemb);
113 }
114
115 }
116
117
FTPURL(const FTPURL & r)118 FTPURL::FTPURL(const FTPURL& r)
119 : m_mutex(),
120 m_pFCP(r.m_pFCP),
121 m_aUsername(r.m_aUsername),
122 m_bShowPassword(r.m_bShowPassword),
123 m_aHost(r.m_aHost),
124 m_aPort(r.m_aPort),
125 m_aPathSegmentVec(r.m_aPathSegmentVec)
126
127 {
128 }
129
130
FTPURL(const rtl::OUString & url,FTPHandleProvider * pFCP)131 FTPURL::FTPURL(const rtl::OUString& url,
132 FTPHandleProvider* pFCP)
133 : m_pFCP(pFCP),
134 m_aUsername(rtl::OUString::createFromAscii("anonymous")),
135 m_bShowPassword(false),
136 m_aPort(rtl::OUString::createFromAscii("21"))
137 {
138 parse(url); // can reset m_bShowPassword
139 }
140
141
~FTPURL()142 FTPURL::~FTPURL()
143 {
144 }
145
146
parse(const rtl::OUString & url)147 void FTPURL::parse(const rtl::OUString& url)
148 {
149 rtl::OUString aPassword,aAccount;
150 rtl::OString aIdent(url.getStr(),
151 url.getLength(),
152 RTL_TEXTENCODING_UTF8);
153
154 rtl::OString lower = aIdent.toAsciiLowerCase();
155 if(lower.getLength() < 6 ||
156 strncmp("ftp://",lower.getStr(),6))
157 throw malformed_exception();
158
159 char *buffer = new char[1+aIdent.getLength()];
160 const char* p2 = aIdent.getStr();
161 p2 += 6;
162
163 char ch;
164 char *p1 = buffer; // determine "username:password@host:port"
165 while((ch = *p2++) != '/' && ch)
166 *p1++ = ch;
167 *p1 = 0;
168
169 rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer),
170 RTL_TEXTENCODING_UTF8));
171
172 sal_Int32 l = aExpr.indexOf(sal_Unicode('@'));
173 m_aHost = aExpr.copy(1+l);
174
175 if(l != -1) {
176 // Now username and password.
177 aExpr = aExpr.copy(0,l);
178 l = aExpr.indexOf(sal_Unicode(':'));
179 if(l != -1) {
180 aPassword = aExpr.copy(1+l);
181 if(aPassword.getLength())
182 m_bShowPassword = true;
183 }
184 if(l > 0)
185 // Overwritte only if the username is not empty.
186 m_aUsername = aExpr.copy(0,l);
187 else if(aExpr.getLength())
188 m_aUsername = aExpr;
189 }
190
191 l = m_aHost.lastIndexOf(sal_Unicode(':'));
192 sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']'));
193 if((ipv6Back == -1 && l != -1) // not ipv6, but a port
194 ||
195 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
196 )
197 {
198 if(1+l<m_aHost.getLength())
199 m_aPort = m_aHost.copy(1+l);
200 m_aHost = m_aHost.copy(0,l);
201 }
202
203 while(ch) { // now determine the pathsegments ...
204 p1 = buffer;
205 while((ch = *p2++) != '/' && ch)
206 *p1++ = ch;
207 *p1 = 0;
208
209 if(buffer[0]) {
210 if(strcmp(buffer,"..") == 0 &&
211 m_aPathSegmentVec.size() &&
212 ! m_aPathSegmentVec.back().equalsAscii(".."))
213 m_aPathSegmentVec.pop_back();
214 else if(strcmp(buffer,".") == 0)
215 ; // Ignore
216 else
217 // This is a legal name.
218 m_aPathSegmentVec.push_back(
219 rtl::OUString(buffer,
220 strlen(buffer),
221 RTL_TEXTENCODING_UTF8));
222 }
223 }
224
225 delete[] buffer;
226
227 if(m_bShowPassword)
228 m_pFCP->setHost(m_aHost,
229 m_aPort,
230 m_aUsername,
231 aPassword,
232 aAccount);
233
234 // now check for something like ";type=i" at end of url
235 if(m_aPathSegmentVec.size() &&
236 (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) {
237 m_aType = m_aPathSegmentVec.back().copy(l);
238 m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
239 }
240 }
241
242
ident(bool withslash,bool internal) const243 rtl::OUString FTPURL::ident(bool withslash,bool internal) const
244 {
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. )
248
249 rtl::OUStringBuffer bff;
250 bff.appendAscii("ftp://");
251
252 if(!m_aUsername.equalsAscii("anonymous")) {
253 bff.append(m_aUsername);
254
255 rtl::OUString aPassword,aAccount;
256 m_pFCP->forHost(m_aHost,
257 m_aPort,
258 m_aUsername,
259 aPassword,
260 aAccount);
261
262 if((m_bShowPassword || internal) &&
263 aPassword.getLength() )
264 bff.append(sal_Unicode(':'))
265 .append(aPassword);
266
267 bff.append(sal_Unicode('@'));
268 }
269 bff.append(m_aHost);
270
271 if(!m_aPort.equalsAscii("21"))
272 bff.append(sal_Unicode(':'))
273 .append(m_aPort)
274 .append(sal_Unicode('/'));
275 else
276 bff.append(sal_Unicode('/'));
277
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(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
283 if(withslash)
284 if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/'))
285 bff.append(sal_Unicode('/'));
286
287 bff.append(m_aType);
288 return bff.makeStringAndClear();
289 }
290
291
parent(bool internal) const292 rtl::OUString FTPURL::parent(bool internal) const
293 {
294 rtl::OUStringBuffer bff;
295
296 bff.appendAscii("ftp://");
297
298 if(!m_aUsername.equalsAscii("anonymous")) {
299 bff.append(m_aUsername);
300
301 rtl::OUString aPassword,aAccount;
302 m_pFCP->forHost(m_aHost,
303 m_aPort,
304 m_aUsername,
305 aPassword,
306 aAccount);
307
308 if((internal || m_bShowPassword) && aPassword.getLength())
309 bff.append(sal_Unicode(':'))
310 .append(aPassword);
311
312 bff.append(sal_Unicode('@'));
313 }
314
315 bff.append(m_aHost);
316
317 if(!m_aPort.equalsAscii("21"))
318 bff.append(sal_Unicode(':'))
319 .append(m_aPort)
320 .append(sal_Unicode('/'));
321 else
322 bff.append(sal_Unicode('/'));
323
324 rtl::OUString last;
325
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(sal_Unicode('/')).append(m_aPathSegmentVec[i]);
333
334 if(!last.getLength())
335 bff.appendAscii("..");
336 else if(last.equalsAscii(".."))
337 bff.append(last).appendAscii("/..");
338
339 bff.append(m_aType);
340 return bff.makeStringAndClear();
341 }
342
343
child(const rtl::OUString & title)344 void FTPURL::child(const rtl::OUString& title)
345 {
346 m_aPathSegmentVec.push_back(encodePathSegment(title));
347 }
348
349
child() const350 rtl::OUString FTPURL::child() const
351 {
352 return
353 m_aPathSegmentVec.size() ?
354 decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString();
355 }
356
357
358
359 /** Listing of a directory.
360 */
361
362 namespace ftp {
363
364 enum OS {
365 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
366 };
367
368 }
369
370
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)
379
380
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)
386
387 #define SET_URL(url) \
388 rtl::OString urlParAscii(url.getStr(), \
389 url.getLength(), \
390 RTL_TEXTENCODING_UTF8); \
391 curl_easy_setopt(curl, \
392 CURLOPT_URL, \
393 urlParAscii.getStr());
394
395 // Setting username:password
396 #define SET_USER_PASSWORD(username,password) \
397 rtl::OUString combi(username + \
398 rtl::OUString::createFromAscii(":") + \
399 password); \
400 rtl::OString aUserPsswd(combi.getStr(), \
401 combi.getLength(), \
402 RTL_TEXTENCODING_UTF8); \
403 curl_easy_setopt(curl, \
404 CURLOPT_USERPWD, \
405 aUserPsswd.getStr())
406
407
408
open()409 oslFileHandle FTPURL::open()
410 {
411 if(!m_aPathSegmentVec.size())
412 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
413
414 CURL *curl = m_pFCP->handle();
415
416 SET_CONTROL_CONTAINER;
417 rtl::OUString url(ident(false,true));
418 SET_URL(url);
419
420 oslFileHandle res( NULL );
421 if ( osl_createTempFile( NULL, &res, NULL ) == osl_File_E_None )
422 {
423 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
424 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
425
426 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
427 CURLcode err = curl_easy_perform(curl);
428
429 if(err == CURLE_OK)
430 osl_setFilePos( res, osl_Pos_Absolut, 0 );
431 else {
432 osl_closeFile(res),res = 0;
433 throw curl_exception(err);
434 }
435 }
436
437 return res;
438 }
439
440
list(sal_Int16 nMode) const441 std::vector<FTPDirentry> FTPURL::list(
442 sal_Int16 nMode
443 ) const
444 {
445 CURL *curl = m_pFCP->handle();
446
447 SET_CONTROL_CONTAINER;
448 SET_DATA_CONTAINER;
449 rtl::OUString url(ident(true,true));
450 SET_URL(url);
451 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
452
453 CURLcode err = curl_easy_perform(curl);
454 if(err != CURLE_OK)
455 throw curl_exception(err);
456
457 // now evaluate the error messages
458
459 sal_uInt32 len = data.m_nWritePos;
460 char* fwd = (char*) data.m_pBuffer;
461 rtl::OString str(fwd,len);
462 char *p1, *p2;
463 p1 = p2 = fwd;
464
465 OS osKind(FTP_UNKNOWN);
466 std::vector<FTPDirentry> resvec;
467 FTPDirentry aDirEntry;
468 // ensure slash at the end
469 rtl::OUString viewurl(ident(true,false));
470
471 while(true) {
472 while(p2-fwd < int(len) && *p2 != '\n') ++p2;
473 if(p2-fwd == int(len)) break;
474
475 *p2 = 0;
476 switch(osKind) {
477 // While FTP knows the 'system'-command,
478 // which returns the operating system type,
479 // this is not usable here: There are Windows-server
480 // formatting the output like UNIX-ls command.
481 case FTP_DOS:
482 FTPDirectoryParser::parseDOS(aDirEntry,p1);
483 break;
484 case FTP_UNIX:
485 FTPDirectoryParser::parseUNIX(aDirEntry,p1);
486 break;
487 case FTP_VMS:
488 FTPDirectoryParser::parseVMS(aDirEntry,p1);
489 break;
490 default:
491 if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
492 osKind = FTP_UNIX;
493 else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
494 osKind = FTP_DOS;
495 else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
496 osKind = FTP_VMS;
497 }
498 aDirEntry.m_aName = aDirEntry.m_aName.trim();
499 if(osKind != int(FTP_UNKNOWN) &&
500 !aDirEntry.m_aName.equalsAscii("..") &&
501 !aDirEntry.m_aName.equalsAscii(".")) {
502 aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
503
504 sal_Bool isDir =
505 sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR);
506 switch(nMode) {
507 case OpenMode::DOCUMENTS:
508 if(!isDir)
509 resvec.push_back(aDirEntry);
510 break;
511 case OpenMode::FOLDERS:
512 if(isDir)
513 resvec.push_back(aDirEntry);
514 break;
515 default:
516 resvec.push_back(aDirEntry);
517 };
518 }
519 aDirEntry.clear();
520 p1 = p2 + 1;
521 }
522
523 return resvec;
524 }
525
526
net_title() const527 rtl::OUString FTPURL::net_title() const
528 {
529 CURL *curl = m_pFCP->handle();
530
531 SET_CONTROL_CONTAINER;
532 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
533 struct curl_slist *slist = 0;
534 // post request
535 slist = curl_slist_append(slist,"PWD");
536 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
537
538 bool try_more(true);
539 CURLcode err;
540 rtl::OUString aNetTitle;
541
542 while(true) {
543 rtl::OUString url(ident(false,true));
544
545 if(try_more &&
546 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
547 url += rtl::OUString::createFromAscii("/"); // add end-slash
548 else if(!try_more &&
549 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength())
550 url = url.copy(0,url.getLength()-1); // remove end-slash
551
552 SET_URL(url);
553 err = curl_easy_perform(curl);
554
555 if(err == CURLE_OK) { // get the title from the server
556 char* fwd = (char*) control.m_pBuffer;
557 sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
558
559 aNetTitle = rtl::OUString(fwd,len,RTL_TEXTENCODING_UTF8);
560 // the buffer now contains the name of the file;
561 // analyze the output:
562 // Format of current working directory:
563 // 257 "/bla/bla" is current directory
564 sal_Int32 index1 = aNetTitle.lastIndexOf(
565 rtl::OUString::createFromAscii("257"));
566 index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1);
567 sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1);
568 aNetTitle = aNetTitle.copy(index1,index2-index1);
569 if(!aNetTitle.equalsAscii("/")) {
570 index1 = aNetTitle.lastIndexOf(sal_Unicode('/'));
571 aNetTitle = aNetTitle.copy(1+index1);
572 }
573 try_more = false;
574 } else if(err == CURLE_BAD_PASSWORD_ENTERED)
575 // the client should retry after getting the correct
576 // username + password
577 throw curl_exception(err);
578 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
579 else if(err == CURLE_LOGIN_DENIED)
580 // the client should retry after getting the correct
581 // username + password
582 throw curl_exception(err);
583 #endif
584 else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
585 // We were either denied access when trying to login to
586 // an FTP server or when trying to change working directory
587 // to the one given in the URL.
588 if(m_aPathSegmentVec.size())
589 // determine title form url
590 aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
591 else
592 // must be root
593 aNetTitle = rtl::OUString::createFromAscii("/");
594 try_more = false;
595 }
596
597 if(try_more)
598 try_more = false;
599 else
600 break;
601 }
602
603 curl_slist_free_all(slist);
604 return aNetTitle;
605 }
606
607
direntry() const608 FTPDirentry FTPURL::direntry() const
609 {
610 rtl::OUString nettitle = net_title();
611 FTPDirentry aDirentry;
612
613 aDirentry.m_aName = nettitle; // init aDirentry
614 if(nettitle.equalsAscii("/") ||
615 nettitle.equalsAscii(".."))
616 aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
617 else
618 aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
619
620 aDirentry.m_nSize = 0;
621
622 if(!nettitle.equalsAscii("/")) {
623 // try to open the parent directory
624 FTPURL aURL(parent(),m_pFCP);
625
626 std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
627
628 for(unsigned i = 0; i < aList.size(); ++i) {
629 if(aList[i].m_aName == nettitle) { // the relevant file is found
630 aDirentry = aList[i];
631 break;
632 }
633 }
634 }
635 return aDirentry;
636 }
637
638
639 extern "C" {
640
memory_read(void * ptr,size_t size,size_t nmemb,void * stream)641 size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
642 {
643 sal_Int32 nRequested = sal_Int32(size*nmemb);
644 CurlInput *curlInput = static_cast<CurlInput*>(stream);
645 if(curlInput)
646 return size_t(curlInput->read(((sal_Int8*)ptr),nRequested));
647 else
648 return 0;
649 }
650
651 }
652
653
insert(bool replaceExisting,void * stream) const654 void FTPURL::insert(bool replaceExisting,void* stream) const
655 {
656 if(!replaceExisting) {
657 // FTPDirentry aDirentry(direntry());
658 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
659 // throw curl_exception(FILE_EXIST_DURING_INSERT);
660 throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
661 } // else
662 // overwrite is default in libcurl
663
664 CURL *curl = m_pFCP->handle();
665
666 SET_CONTROL_CONTAINER;
667 curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
668 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
669 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
670 curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
671 curl_easy_setopt(curl,CURLOPT_READDATA,stream);
672 curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
673
674 rtl::OUString url(ident(false,true));
675 SET_URL(url);
676
677 CURLcode err = curl_easy_perform(curl);
678 curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
679
680 if(err != CURLE_OK)
681 throw curl_exception(err);
682 }
683
684
685
mkdir(bool ReplaceExisting) const686 void FTPURL::mkdir(bool ReplaceExisting) const
687 {
688 rtl::OString title;
689 if(m_aPathSegmentVec.size()) {
690 rtl::OUString titleOU = m_aPathSegmentVec.back();
691 titleOU = decodePathSegment(titleOU);
692 title = rtl::OString(titleOU.getStr(),
693 titleOU.getLength(),
694 RTL_TEXTENCODING_UTF8);
695 }
696 else
697 // will give an error
698 title = rtl::OString("/");
699
700 rtl::OString aDel("del "); aDel += title;
701 rtl::OString mkd("mkd "); mkd += title;
702
703 struct curl_slist *slist = 0;
704
705 FTPDirentry aDirentry(direntry());
706 if(!ReplaceExisting) {
707 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
708 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
709 throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
710 } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
711 slist = curl_slist_append(slist,aDel.getStr());
712
713 slist = curl_slist_append(slist,mkd.getStr());
714
715 CURL *curl = m_pFCP->handle();
716 SET_CONTROL_CONTAINER;
717 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
718 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
719
720 // post request
721 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
722
723 rtl::OUString url(parent(true));
724 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
725 url += rtl::OUString::createFromAscii("/");
726 SET_URL(url);
727
728 CURLcode err = curl_easy_perform(curl);
729 curl_slist_free_all(slist);
730 if(err != CURLE_OK)
731 throw curl_exception(err);
732 }
733
734
ren(const rtl::OUString & NewTitle)735 rtl::OUString FTPURL::ren(const rtl::OUString& NewTitle)
736 {
737 CURL *curl = m_pFCP->handle();
738
739 // post request
740 rtl::OString renamefrom("RNFR ");
741 rtl::OUString OldTitle = net_title();
742 renamefrom +=
743 rtl::OString(OldTitle.getStr(),
744 OldTitle.getLength(),
745 RTL_TEXTENCODING_UTF8);
746
747 rtl::OString renameto("RNTO ");
748 renameto +=
749 rtl::OString(NewTitle.getStr(),
750 NewTitle.getLength(),
751 RTL_TEXTENCODING_UTF8);
752
753 struct curl_slist *slist = 0;
754 slist = curl_slist_append(slist,renamefrom.getStr());
755 slist = curl_slist_append(slist,renameto.getStr());
756 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
757
758 SET_CONTROL_CONTAINER;
759 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
760 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
761
762 rtl::OUString url(parent(true));
763 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
764 url += rtl::OUString::createFromAscii("/");
765 SET_URL(url);
766
767 CURLcode err = curl_easy_perform(curl);
768 curl_slist_free_all(slist);
769 if(err != CURLE_OK)
770 throw curl_exception(err);
771 else if(m_aPathSegmentVec.size() &&
772 !m_aPathSegmentVec.back().equalsAscii(".."))
773 m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
774 return OldTitle;
775 }
776
777
778
del() const779 void FTPURL::del() const
780 {
781 FTPDirentry aDirentry(direntry());
782
783 rtl::OString dele(aDirentry.m_aName.getStr(),
784 aDirentry.m_aName.getLength(),
785 RTL_TEXTENCODING_UTF8);
786
787 if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
788 std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
789 for( unsigned int i = 0; i < vec.size(); ++i )
790 try {
791 FTPURL url(vec[i].m_aURL,m_pFCP);
792 url.del();
793 } catch(const curl_exception&) {
794 }
795 dele = rtl::OString("RMD ") + dele;
796 }
797 else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
798 dele = rtl::OString("DELE ") + dele;
799 else
800 return;
801
802 // post request
803 CURL *curl = m_pFCP->handle();
804 struct curl_slist *slist = 0;
805 slist = curl_slist_append(slist,dele.getStr());
806 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
807
808 SET_CONTROL_CONTAINER;
809 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
810 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
811
812 rtl::OUString url(parent(true));
813 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
814 url += rtl::OUString::createFromAscii("/");
815 SET_URL(url);
816
817 CURLcode err = curl_easy_perform(curl);
818 curl_slist_free_all(slist);
819 if(err != CURLE_OK)
820 throw curl_exception(err);
821 }
822