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_ucb.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 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 58 rtl::OUString decodePathSegment(rtl::OUString const & encoded) { 59 return rtl::Uri::decode( 60 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); 61 } 62 63 } 64 65 MemoryContainer::MemoryContainer() 66 : m_nLen(0), 67 m_nWritePos(0), 68 m_pBuffer(0) 69 { 70 } 71 72 MemoryContainer::~MemoryContainer() 73 { 74 rtl_freeMemory(m_pBuffer); 75 } 76 77 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 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 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 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 145 FTPURL::~FTPURL() 146 { 147 } 148 149 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 249 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 298 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 350 void FTPURL::child(const rtl::OUString& title) 351 { 352 m_aPathSegmentVec.push_back(encodePathSegment(title)); 353 } 354 355 356 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 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 448 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 537 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 619 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 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 666 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 699 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 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 794 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