1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_ucb.hxx" 30 /************************************************************************** 31 TODO 32 ************************************************************************** 33 34 *************************************************************************/ 35 36 #include <memory> 37 #include <rtl/ustrbuf.hxx> 38 #include <com/sun/star/ucb/OpenMode.hpp> 39 #include <string.h> 40 #include <rtl/uri.hxx> 41 42 #include "ftpstrcont.hxx" 43 #include "ftpurl.hxx" 44 #include "ftphandleprovider.hxx" 45 #include "ftpinpstr.hxx" 46 #include "ftpcfunc.hxx" 47 #include "ftpcontainer.hxx" 48 49 using namespace ftp; 50 using namespace com::sun::star::ucb; 51 using namespace com::sun::star::uno; 52 using namespace com::sun::star::io; 53 54 namespace { 55 56 rtl::OUString encodePathSegment(rtl::OUString const & decoded) { 57 return rtl::Uri::encode( 58 decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, 59 RTL_TEXTENCODING_UTF8); 60 } 61 62 rtl::OUString decodePathSegment(rtl::OUString const & encoded) { 63 return rtl::Uri::decode( 64 encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); 65 } 66 67 } 68 69 MemoryContainer::MemoryContainer() 70 : m_nLen(0), 71 m_nWritePos(0), 72 m_pBuffer(0) 73 { 74 } 75 76 MemoryContainer::~MemoryContainer() 77 { 78 rtl_freeMemory(m_pBuffer); 79 } 80 81 82 int MemoryContainer::append( 83 const void* pBuffer, 84 size_t size, 85 size_t nmemb 86 ) throw() 87 { 88 sal_uInt32 nLen = size*nmemb; 89 sal_uInt32 tmp(nLen + m_nWritePos); 90 91 if(m_nLen < tmp) { // enlarge in steps of multiples of 1K 92 do { 93 m_nLen+=1024; 94 } while(m_nLen < tmp); 95 96 m_pBuffer = rtl_reallocateMemory(m_pBuffer,m_nLen); 97 } 98 99 rtl_copyMemory(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos, 100 pBuffer,nLen); 101 m_nWritePos = tmp; 102 return nLen; 103 } 104 105 106 extern "C" { 107 108 int memory_write(void *buffer,size_t size,size_t nmemb,void *stream) 109 { 110 MemoryContainer *_stream = 111 reinterpret_cast<MemoryContainer*>(stream); 112 113 if(!_stream) 114 return 0; 115 116 return _stream->append(buffer,size,nmemb); 117 } 118 119 } 120 121 122 FTPURL::FTPURL(const FTPURL& r) 123 : m_mutex(), 124 m_pFCP(r.m_pFCP), 125 m_aUsername(r.m_aUsername), 126 m_bShowPassword(r.m_bShowPassword), 127 m_aHost(r.m_aHost), 128 m_aPort(r.m_aPort), 129 m_aPathSegmentVec(r.m_aPathSegmentVec) 130 131 { 132 } 133 134 135 FTPURL::FTPURL(const rtl::OUString& url, 136 FTPHandleProvider* pFCP) 137 throw( 138 malformed_exception 139 ) 140 : m_pFCP(pFCP), 141 m_aUsername(rtl::OUString::createFromAscii("anonymous")), 142 m_bShowPassword(false), 143 m_aPort(rtl::OUString::createFromAscii("21")) 144 { 145 parse(url); // can reset m_bShowPassword 146 } 147 148 149 FTPURL::~FTPURL() 150 { 151 } 152 153 154 void FTPURL::parse(const rtl::OUString& url) 155 throw( 156 malformed_exception 157 ) 158 { 159 rtl::OUString aPassword,aAccount; 160 rtl::OString aIdent(url.getStr(), 161 url.getLength(), 162 RTL_TEXTENCODING_UTF8); 163 164 rtl::OString lower = aIdent.toAsciiLowerCase(); 165 if(lower.getLength() < 6 || 166 strncmp("ftp://",lower.getStr(),6)) 167 throw malformed_exception(); 168 169 char *buffer = new char[1+aIdent.getLength()]; 170 const char* p2 = aIdent.getStr(); 171 p2 += 6; 172 173 char ch; 174 char *p1 = buffer; // determine "username:password@host:port" 175 while((ch = *p2++) != '/' && ch) 176 *p1++ = ch; 177 *p1 = 0; 178 179 rtl::OUString aExpr(rtl::OUString(buffer,strlen(buffer), 180 RTL_TEXTENCODING_UTF8)); 181 182 sal_Int32 l = aExpr.indexOf(sal_Unicode('@')); 183 m_aHost = aExpr.copy(1+l); 184 185 if(l != -1) { 186 // Now username and password. 187 aExpr = aExpr.copy(0,l); 188 l = aExpr.indexOf(sal_Unicode(':')); 189 if(l != -1) { 190 aPassword = aExpr.copy(1+l); 191 if(aPassword.getLength()) 192 m_bShowPassword = true; 193 } 194 if(l > 0) 195 // Overwritte only if the username is not empty. 196 m_aUsername = aExpr.copy(0,l); 197 else if(aExpr.getLength()) 198 m_aUsername = aExpr; 199 } 200 201 l = m_aHost.lastIndexOf(sal_Unicode(':')); 202 sal_Int32 ipv6Back = m_aHost.lastIndexOf(sal_Unicode(']')); 203 if((ipv6Back == -1 && l != -1) // not ipv6, but a port 204 || 205 (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port 206 ) 207 { 208 if(1+l<m_aHost.getLength()) 209 m_aPort = m_aHost.copy(1+l); 210 m_aHost = m_aHost.copy(0,l); 211 } 212 213 while(ch) { // now determine the pathsegments ... 214 p1 = buffer; 215 while((ch = *p2++) != '/' && ch) 216 *p1++ = ch; 217 *p1 = 0; 218 219 if(buffer[0]) { 220 if(strcmp(buffer,"..") == 0 && 221 m_aPathSegmentVec.size() && 222 ! m_aPathSegmentVec.back().equalsAscii("..")) 223 m_aPathSegmentVec.pop_back(); 224 else if(strcmp(buffer,".") == 0) 225 ; // Ignore 226 else 227 // This is a legal name. 228 m_aPathSegmentVec.push_back( 229 rtl::OUString(buffer, 230 strlen(buffer), 231 RTL_TEXTENCODING_UTF8)); 232 } 233 } 234 235 delete[] buffer; 236 237 if(m_bShowPassword) 238 m_pFCP->setHost(m_aHost, 239 m_aPort, 240 m_aUsername, 241 aPassword, 242 aAccount); 243 244 // now check for something like ";type=i" at end of url 245 if(m_aPathSegmentVec.size() && 246 (l = m_aPathSegmentVec.back().indexOf(sal_Unicode(';'))) != -1) { 247 m_aType = m_aPathSegmentVec.back().copy(l); 248 m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l); 249 } 250 } 251 252 253 rtl::OUString FTPURL::ident(bool withslash,bool internal) const 254 { 255 // rebuild the url as one without ellipses, 256 // and more important, as one without username and 257 // password. ( These are set together with the command. ) 258 259 rtl::OUStringBuffer bff; 260 bff.appendAscii("ftp://"); 261 262 if(!m_aUsername.equalsAscii("anonymous")) { 263 bff.append(m_aUsername); 264 265 rtl::OUString aPassword,aAccount; 266 m_pFCP->forHost(m_aHost, 267 m_aPort, 268 m_aUsername, 269 aPassword, 270 aAccount); 271 272 if((m_bShowPassword || internal) && 273 aPassword.getLength() ) 274 bff.append(sal_Unicode(':')) 275 .append(aPassword); 276 277 bff.append(sal_Unicode('@')); 278 } 279 bff.append(m_aHost); 280 281 if(!m_aPort.equalsAscii("21")) 282 bff.append(sal_Unicode(':')) 283 .append(m_aPort) 284 .append(sal_Unicode('/')); 285 else 286 bff.append(sal_Unicode('/')); 287 288 for(unsigned i = 0; i < m_aPathSegmentVec.size(); ++i) 289 if(i == 0) 290 bff.append(m_aPathSegmentVec[i]); 291 else 292 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]); 293 if(withslash) 294 if(bff.getLength() && bff[bff.getLength()-1] != sal_Unicode('/')) 295 bff.append(sal_Unicode('/')); 296 297 bff.append(m_aType); 298 return bff.makeStringAndClear(); 299 } 300 301 302 rtl::OUString FTPURL::parent(bool internal) const 303 { 304 rtl::OUStringBuffer bff; 305 306 bff.appendAscii("ftp://"); 307 308 if(!m_aUsername.equalsAscii("anonymous")) { 309 bff.append(m_aUsername); 310 311 rtl::OUString aPassword,aAccount; 312 m_pFCP->forHost(m_aHost, 313 m_aPort, 314 m_aUsername, 315 aPassword, 316 aAccount); 317 318 if((internal || m_bShowPassword) && aPassword.getLength()) 319 bff.append(sal_Unicode(':')) 320 .append(aPassword); 321 322 bff.append(sal_Unicode('@')); 323 } 324 325 bff.append(m_aHost); 326 327 if(!m_aPort.equalsAscii("21")) 328 bff.append(sal_Unicode(':')) 329 .append(m_aPort) 330 .append(sal_Unicode('/')); 331 else 332 bff.append(sal_Unicode('/')); 333 334 rtl::OUString last; 335 336 for(unsigned int i = 0; i < m_aPathSegmentVec.size(); ++i) 337 if(1+i == m_aPathSegmentVec.size()) 338 last = m_aPathSegmentVec[i]; 339 else if(i == 0) 340 bff.append(m_aPathSegmentVec[i]); 341 else 342 bff.append(sal_Unicode('/')).append(m_aPathSegmentVec[i]); 343 344 if(!last.getLength()) 345 bff.appendAscii(".."); 346 else if(last.equalsAscii("..")) 347 bff.append(last).appendAscii("/.."); 348 349 bff.append(m_aType); 350 return bff.makeStringAndClear(); 351 } 352 353 354 void FTPURL::child(const rtl::OUString& title) 355 { 356 m_aPathSegmentVec.push_back(encodePathSegment(title)); 357 } 358 359 360 rtl::OUString FTPURL::child() const 361 { 362 return 363 m_aPathSegmentVec.size() ? 364 decodePathSegment(m_aPathSegmentVec.back()) : rtl::OUString(); 365 } 366 367 368 369 /** Listing of a directory. 370 */ 371 372 namespace ftp { 373 374 enum OS { 375 FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN 376 }; 377 378 } 379 380 381 #define SET_CONTROL_CONTAINER \ 382 MemoryContainer control; \ 383 curl_easy_setopt(curl, \ 384 CURLOPT_HEADERFUNCTION, \ 385 memory_write); \ 386 curl_easy_setopt(curl, \ 387 CURLOPT_WRITEHEADER, \ 388 &control) 389 390 391 #define SET_DATA_CONTAINER \ 392 curl_easy_setopt(curl,CURLOPT_NOBODY,false); \ 393 MemoryContainer data; \ 394 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); \ 395 curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data) 396 397 #define SET_URL(url) \ 398 rtl::OString urlParAscii(url.getStr(), \ 399 url.getLength(), \ 400 RTL_TEXTENCODING_UTF8); \ 401 curl_easy_setopt(curl, \ 402 CURLOPT_URL, \ 403 urlParAscii.getStr()); 404 405 // Setting username:password 406 #define SET_USER_PASSWORD(username,password) \ 407 rtl::OUString combi(username + \ 408 rtl::OUString::createFromAscii(":") + \ 409 password); \ 410 rtl::OString aUserPsswd(combi.getStr(), \ 411 combi.getLength(), \ 412 RTL_TEXTENCODING_UTF8); \ 413 curl_easy_setopt(curl, \ 414 CURLOPT_USERPWD, \ 415 aUserPsswd.getStr()) 416 417 418 419 FILE* FTPURL::open() 420 throw(curl_exception) 421 { 422 if(!m_aPathSegmentVec.size()) 423 throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE); 424 425 CURL *curl = m_pFCP->handle(); 426 427 SET_CONTROL_CONTAINER; 428 rtl::OUString url(ident(false,true)); 429 SET_URL(url); 430 FILE *res = tmpfile(); 431 curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write); 432 curl_easy_setopt(curl,CURLOPT_WRITEDATA,res); 433 434 curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); 435 CURLcode err = curl_easy_perform(curl); 436 437 if(err == CURLE_OK) 438 rewind(res); 439 else { 440 fclose(res),res = 0; 441 throw curl_exception(err); 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