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 throw(
134 malformed_exception
135 )
136 : m_pFCP(pFCP),
137 m_aUsername(rtl::OUString::createFromAscii("anonymous")),
138 m_bShowPassword(false),
139 m_aPort(rtl::OUString::createFromAscii("21"))
140 {
141 parse(url); // can reset m_bShowPassword
142 }
143
144
~FTPURL()145 FTPURL::~FTPURL()
146 {
147 }
148
149
parse(const rtl::OUString & url)150 void FTPURL::parse(const rtl::OUString& url)
151 throw(
152 malformed_exception
153 )
154 {
155 rtl::OUString aPassword,aAccount;
156 rtl::OString aIdent(url.getStr(),
157 url.getLength(),
158 RTL_TEXTENCODING_UTF8);
159
160 rtl::OString lower = aIdent.toAsciiLowerCase();
161 if(lower.getLength() < 6 ||
162 strncmp("ftp://",lower.getStr(),6))
163 throw malformed_exception();
164
165 char *buffer = new char[1+aIdent.getLength()];
166 const char* p2 = aIdent.getStr();
167 p2 += 6;
168
169 char ch;
170 char *p1 = buffer; // determine "username:password@host:port"
171 while((ch = *p2++) != '/' && ch)
172 *p1++ = ch;
173 *p1 = 0;
174
175 rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer),
176 RTL_TEXTENCODING_UTF8));
177
178 sal_Int32 l = aExpr.indexOf(sal_Unicode('@'));
179 m_aHost = aExpr.copy(1+l);
180
181 if(l != -1) {
182 // Now username and password.
183 aExpr = aExpr.copy(0,l);
184 l = aExpr.indexOf(sal_Unicode(':'));
185 if(l != -1) {
186 aPassword = aExpr.copy(1+l);
187 if(aPassword.getLength())
188 m_bShowPassword = true;
189 }
190 if(l > 0)
191 // Overwritte only if the username is not empty.
192 m_aUsername = aExpr.copy(0,l);
193 else if(aExpr.getLength())
194 m_aUsername = aExpr;
195 }
196
197 l = m_aHost.lastIndexOf(sal_Unicode(':'));
198 sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']'));
199 if((ipv6Back == -1 && l != -1) // not ipv6, but a port
200 ||
201 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
202 )
203 {
204 if(1+l<m_aHost.getLength())
205 m_aPort = m_aHost.copy(1+l);
206 m_aHost = m_aHost.copy(0,l);
207 }
208
209 while(ch) { // now determine the pathsegments ...
210 p1 = buffer;
211 while((ch = *p2++) != '/' && ch)
212 *p1++ = ch;
213 *p1 = 0;
214
215 if(buffer[0]) {
216 if(strcmp(buffer,"..") == 0 &&
217 m_aPathSegmentVec.size() &&
218 ! m_aPathSegmentVec.back().equalsAscii(".."))
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));
228 }
229 }
230
231 delete[] buffer;
232
233 if(m_bShowPassword)
234 m_pFCP->setHost(m_aHost,
235 m_aPort,
236 m_aUsername,
237 aPassword,
238 aAccount);
239
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);
245 }
246 }
247
248
ident(bool withslash,bool internal) const249 rtl::OUString FTPURL::ident(bool withslash,bool internal) const
250 {
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. )
254
255 rtl::OUStringBuffer bff;
256 bff.appendAscii("ftp://");
257
258 if(!m_aUsername.equalsAscii("anonymous")) {
259 bff.append(m_aUsername);
260
261 rtl::OUString aPassword,aAccount;
262 m_pFCP->forHost(m_aHost,
263 m_aPort,
264 m_aUsername,
265 aPassword,
266 aAccount);
267
268 if((m_bShowPassword || internal) &&
269 aPassword.getLength() )
270 bff.append(sal_Unicode(':'))
271 .append(aPassword);
272
273 bff.append(sal_Unicode('@'));
274 }
275 bff.append(m_aHost);
276
277 if(!m_aPort.equalsAscii("21"))
278 bff.append(sal_Unicode(':'))
279 .append(m_aPort)
280 .append(sal_Unicode('/'));
281 else
282 bff.append(sal_Unicode('/'));
283
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('/'));
292
293 bff.append(m_aType);
294 return bff.makeStringAndClear();
295 }
296
297
parent(bool internal) const298 rtl::OUString FTPURL::parent(bool internal) const
299 {
300 rtl::OUStringBuffer bff;
301
302 bff.appendAscii("ftp://");
303
304 if(!m_aUsername.equalsAscii("anonymous")) {
305 bff.append(m_aUsername);
306
307 rtl::OUString aPassword,aAccount;
308 m_pFCP->forHost(m_aHost,
309 m_aPort,
310 m_aUsername,
311 aPassword,
312 aAccount);
313
314 if((internal || m_bShowPassword) && aPassword.getLength())
315 bff.append(sal_Unicode(':'))
316 .append(aPassword);
317
318 bff.append(sal_Unicode('@'));
319 }
320
321 bff.append(m_aHost);
322
323 if(!m_aPort.equalsAscii("21"))
324 bff.append(sal_Unicode(':'))
325 .append(m_aPort)
326 .append(sal_Unicode('/'));
327 else
328 bff.append(sal_Unicode('/'));
329
330 rtl::OUString last;
331
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]);
339
340 if(!last.getLength())
341 bff.appendAscii("..");
342 else if(last.equalsAscii(".."))
343 bff.append(last).appendAscii("/..");
344
345 bff.append(m_aType);
346 return bff.makeStringAndClear();
347 }
348
349
child(const rtl::OUString & title)350 void FTPURL::child(const rtl::OUString& title)
351 {
352 m_aPathSegmentVec.push_back(encodePathSegment(title));
353 }
354
355
child() const356 rtl::OUString FTPURL::child() const
357 {
358 return
359 m_aPathSegmentVec.size() ?
360 decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString();
361 }
362
363
364
365 /** Listing of a directory.
366 */
367
368 namespace ftp {
369
370 enum OS {
371 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN
372 };
373
374 }
375
376
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)
385
386
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)
392
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());
400
401 // Setting username:password
402 #define SET_USER_PASSWORD(username,password) \
403 rtl::OUString combi(username + \
404 rtl::OUString::createFromAscii(":") + \
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())
412
413
414
open()415 oslFileHandle FTPURL::open()
416 throw(curl_exception)
417 {
418 if(!m_aPathSegmentVec.size())
419 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
420
421 CURL *curl = m_pFCP->handle();
422
423 SET_CONTROL_CONTAINER;
424 rtl::OUString url(ident(false,true));
425 SET_URL(url);
426
427 oslFileHandle res( NULL );
428 if ( osl_createTempFile( NULL, &res, NULL ) == osl_File_E_None )
429 {
430 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
431 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
432
433 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
434 CURLcode err = curl_easy_perform(curl);
435
436 if(err == CURLE_OK)
437 osl_setFilePos( res, osl_Pos_Absolut, 0 );
438 else {
439 osl_closeFile(res),res = 0;
440 throw curl_exception(err);
441 }
442 }
443
444 return res;
445 }
446
447
list(sal_Int16 nMode) const448 std::vector<FTPDirentry> FTPURL::list(
449 sal_Int16 nMode
450 ) const
451 throw(
452 curl_exception
453 )
454 {
455 CURL *curl = m_pFCP->handle();
456
457 SET_CONTROL_CONTAINER;
458 SET_DATA_CONTAINER;
459 rtl::OUString url(ident(true,true));
460 SET_URL(url);
461 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
462
463 CURLcode err = curl_easy_perform(curl);
464 if(err != CURLE_OK)
465 throw curl_exception(err);
466
467 // now evaluate the error messages
468
469 sal_uInt32 len = data.m_nWritePos;
470 char* fwd = (char*) data.m_pBuffer;
471 rtl::OString str(fwd,len);
472 char *p1, *p2;
473 p1 = p2 = fwd;
474
475 OS osKind(FTP_UNKNOWN);
476 std::vector<FTPDirentry> resvec;
477 FTPDirentry aDirEntry;
478 // ensure slash at the end
479 rtl::OUString viewurl(ident(true,false));
480
481 while(true) {
482 while(p2-fwd < int(len) && *p2 != '\n') ++p2;
483 if(p2-fwd == int(len)) break;
484
485 *p2 = 0;
486 switch(osKind) {
487 // While FTP knows the 'system'-command,
488 // which returns the operating system type,
489 // this is not usable here: There are Windows-server
490 // formatting the output like UNIX-ls command.
491 case FTP_DOS:
492 FTPDirectoryParser::parseDOS(aDirEntry,p1);
493 break;
494 case FTP_UNIX:
495 FTPDirectoryParser::parseUNIX(aDirEntry,p1);
496 break;
497 case FTP_VMS:
498 FTPDirectoryParser::parseVMS(aDirEntry,p1);
499 break;
500 default:
501 if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
502 osKind = FTP_UNIX;
503 else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
504 osKind = FTP_DOS;
505 else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
506 osKind = FTP_VMS;
507 }
508 aDirEntry.m_aName = aDirEntry.m_aName.trim();
509 if(osKind != int(FTP_UNKNOWN) &&
510 !aDirEntry.m_aName.equalsAscii("..") &&
511 !aDirEntry.m_aName.equalsAscii(".")) {
512 aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
513
514 sal_Bool isDir =
515 sal_Bool(aDirEntry.m_nMode&INETCOREFTP_FILEMODE_ISDIR);
516 switch(nMode) {
517 case OpenMode::DOCUMENTS:
518 if(!isDir)
519 resvec.push_back(aDirEntry);
520 break;
521 case OpenMode::FOLDERS:
522 if(isDir)
523 resvec.push_back(aDirEntry);
524 break;
525 default:
526 resvec.push_back(aDirEntry);
527 };
528 }
529 aDirEntry.clear();
530 p1 = p2 + 1;
531 }
532
533 return resvec;
534 }
535
536
net_title() const537 rtl::OUString FTPURL::net_title() const
538 throw(curl_exception)
539 {
540 CURL *curl = m_pFCP->handle();
541
542 SET_CONTROL_CONTAINER;
543 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
544 struct curl_slist *slist = 0;
545 // post request
546 slist = curl_slist_append(slist,"PWD");
547 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
548
549 bool try_more(true);
550 CURLcode err;
551 rtl::OUString aNetTitle;
552
553 while(true) {
554 rtl::OUString url(ident(false,true));
555
556 if(try_more &&
557 1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
558 url += rtl::OUString::createFromAscii("/"); // add end-slash
559 else if(!try_more &&
560 1+url.lastIndexOf(sal_Unicode('/')) == url.getLength())
561 url = url.copy(0,url.getLength()-1); // remove end-slash
562
563 SET_URL(url);
564 err = curl_easy_perform(curl);
565
566 if(err == CURLE_OK) { // get the title from the server
567 char* fwd = (char*) control.m_pBuffer;
568 sal_uInt32 len = (sal_uInt32) control.m_nWritePos;
569
570 aNetTitle = rtl::OUString(fwd,len,RTL_TEXTENCODING_UTF8);
571 // the buffer now contains the name of the file;
572 // analyze the output:
573 // Format of current working directory:
574 // 257 "/bla/bla" is current directory
575 sal_Int32 index1 = aNetTitle.lastIndexOf(
576 rtl::OUString::createFromAscii("257"));
577 index1 = 1+aNetTitle.indexOf(sal_Unicode('"'),index1);
578 sal_Int32 index2 = aNetTitle.indexOf(sal_Unicode('"'),index1);
579 aNetTitle = aNetTitle.copy(index1,index2-index1);
580 if(!aNetTitle.equalsAscii("/")) {
581 index1 = aNetTitle.lastIndexOf(sal_Unicode('/'));
582 aNetTitle = aNetTitle.copy(1+index1);
583 }
584 try_more = false;
585 } else if(err == CURLE_BAD_PASSWORD_ENTERED)
586 // the client should retry after getting the correct
587 // username + password
588 throw curl_exception(err);
589 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
590 else if(err == CURLE_LOGIN_DENIED)
591 // the client should retry after getting the correct
592 // username + password
593 throw curl_exception(err);
594 #endif
595 else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
596 // We were either denied access when trying to login to
597 // an FTP server or when trying to change working directory
598 // to the one given in the URL.
599 if(m_aPathSegmentVec.size())
600 // determine title form url
601 aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
602 else
603 // must be root
604 aNetTitle = rtl::OUString::createFromAscii("/");
605 try_more = false;
606 }
607
608 if(try_more)
609 try_more = false;
610 else
611 break;
612 }
613
614 curl_slist_free_all(slist);
615 return aNetTitle;
616 }
617
618
direntry() const619 FTPDirentry FTPURL::direntry() const
620 throw(curl_exception)
621 {
622 rtl::OUString nettitle = net_title();
623 FTPDirentry aDirentry;
624
625 aDirentry.m_aName = nettitle; // init aDirentry
626 if(nettitle.equalsAscii("/") ||
627 nettitle.equalsAscii(".."))
628 aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR;
629 else
630 aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN;
631
632 aDirentry.m_nSize = 0;
633
634 if(!nettitle.equalsAscii("/")) {
635 // try to open the parent directory
636 FTPURL aURL(parent(),m_pFCP);
637
638 std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
639
640 for(unsigned i = 0; i < aList.size(); ++i) {
641 if(aList[i].m_aName == nettitle) { // the relevant file is found
642 aDirentry = aList[i];
643 break;
644 }
645 }
646 }
647 return aDirentry;
648 }
649
650
651 extern "C" {
652
memory_read(void * ptr,size_t size,size_t nmemb,void * stream)653 size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
654 {
655 sal_Int32 nRequested = sal_Int32(size*nmemb);
656 CurlInput *curlInput = static_cast<CurlInput*>(stream);
657 if(curlInput)
658 return size_t(curlInput->read(((sal_Int8*)ptr),nRequested));
659 else
660 return 0;
661 }
662
663 }
664
665
insert(bool replaceExisting,void * stream) const666 void FTPURL::insert(bool replaceExisting,void* stream) const
667 throw(curl_exception)
668 {
669 if(!replaceExisting) {
670 // FTPDirentry aDirentry(direntry());
671 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
672 // throw curl_exception(FILE_EXIST_DURING_INSERT);
673 throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT);
674 } // else
675 // overwrite is default in libcurl
676
677 CURL *curl = m_pFCP->handle();
678
679 SET_CONTROL_CONTAINER;
680 curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
681 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
682 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
683 curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
684 curl_easy_setopt(curl,CURLOPT_READDATA,stream);
685 curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
686
687 rtl::OUString url(ident(false,true));
688 SET_URL(url);
689
690 CURLcode err = curl_easy_perform(curl);
691 curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
692
693 if(err != CURLE_OK)
694 throw curl_exception(err);
695 }
696
697
698
mkdir(bool ReplaceExisting) const699 void FTPURL::mkdir(bool ReplaceExisting) const
700 throw(curl_exception)
701 {
702 rtl::OString title;
703 if(m_aPathSegmentVec.size()) {
704 rtl::OUString titleOU = m_aPathSegmentVec.back();
705 titleOU = decodePathSegment(titleOU);
706 title = rtl::OString(titleOU.getStr(),
707 titleOU.getLength(),
708 RTL_TEXTENCODING_UTF8);
709 }
710 else
711 // will give an error
712 title = rtl::OString("/");
713
714 rtl::OString aDel("del "); aDel += title;
715 rtl::OString mkd("mkd "); mkd += title;
716
717 struct curl_slist *slist = 0;
718
719 FTPDirentry aDirentry(direntry());
720 if(!ReplaceExisting) {
721 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
722 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
723 throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT);
724 } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
725 slist = curl_slist_append(slist,aDel.getStr());
726
727 slist = curl_slist_append(slist,mkd.getStr());
728
729 CURL *curl = m_pFCP->handle();
730 SET_CONTROL_CONTAINER;
731 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
732 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
733
734 // post request
735 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
736
737 rtl::OUString url(parent(true));
738 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
739 url += rtl::OUString::createFromAscii("/");
740 SET_URL(url);
741
742 CURLcode err = curl_easy_perform(curl);
743 curl_slist_free_all(slist);
744 if(err != CURLE_OK)
745 throw curl_exception(err);
746 }
747
748
ren(const rtl::OUString & NewTitle)749 rtl::OUString FTPURL::ren(const rtl::OUString& NewTitle)
750 throw(curl_exception)
751 {
752 CURL *curl = m_pFCP->handle();
753
754 // post request
755 rtl::OString renamefrom("RNFR ");
756 rtl::OUString OldTitle = net_title();
757 renamefrom +=
758 rtl::OString(OldTitle.getStr(),
759 OldTitle.getLength(),
760 RTL_TEXTENCODING_UTF8);
761
762 rtl::OString renameto("RNTO ");
763 renameto +=
764 rtl::OString(NewTitle.getStr(),
765 NewTitle.getLength(),
766 RTL_TEXTENCODING_UTF8);
767
768 struct curl_slist *slist = 0;
769 slist = curl_slist_append(slist,renamefrom.getStr());
770 slist = curl_slist_append(slist,renameto.getStr());
771 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
772
773 SET_CONTROL_CONTAINER;
774 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
775 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
776
777 rtl::OUString url(parent(true));
778 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
779 url += rtl::OUString::createFromAscii("/");
780 SET_URL(url);
781
782 CURLcode err = curl_easy_perform(curl);
783 curl_slist_free_all(slist);
784 if(err != CURLE_OK)
785 throw curl_exception(err);
786 else if(m_aPathSegmentVec.size() &&
787 !m_aPathSegmentVec.back().equalsAscii(".."))
788 m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
789 return OldTitle;
790 }
791
792
793
del() const794 void FTPURL::del() const
795 throw(curl_exception)
796 {
797 FTPDirentry aDirentry(direntry());
798
799 rtl::OString dele(aDirentry.m_aName.getStr(),
800 aDirentry.m_aName.getLength(),
801 RTL_TEXTENCODING_UTF8);
802
803 if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
804 std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
805 for( unsigned int i = 0; i < vec.size(); ++i )
806 try {
807 FTPURL url(vec[i].m_aURL,m_pFCP);
808 url.del();
809 } catch(const curl_exception&) {
810 }
811 dele = rtl::OString("RMD ") + dele;
812 }
813 else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
814 dele = rtl::OString("DELE ") + dele;
815 else
816 return;
817
818 // post request
819 CURL *curl = m_pFCP->handle();
820 struct curl_slist *slist = 0;
821 slist = curl_slist_append(slist,dele.getStr());
822 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
823
824 SET_CONTROL_CONTAINER;
825 curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
826 curl_easy_setopt(curl,CURLOPT_QUOTE,0);
827
828 rtl::OUString url(parent(true));
829 if(1+url.lastIndexOf(sal_Unicode('/')) != url.getLength())
830 url += rtl::OUString::createFromAscii("/");
831 SET_URL(url);
832
833 CURLcode err = curl_easy_perform(curl);
834 curl_slist_free_all(slist);
835 if(err != CURLE_OK)
836 throw curl_exception(err);
837 }
838
839