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