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 <cstring>
30 #include <vector>
31 
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/ucb/OpenMode.hpp>
34 #include <string.h>
35 #include <rtl/uri.hxx>
36 #include <rtl/strbuf.hxx>
37 
38 #include "ftpurl.hxx"
39 #include "ftpcontentprovider.hxx"
40 #include "ftpcfunc.hxx"
41 #include "ftpcontainer.hxx"
42 #include <memory>
43 
44 using namespace ftp;
45 using namespace com::sun::star::ucb;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::io;
48 
49 namespace {
50 
51 OUString encodePathSegment(OUString const & decoded) {
52  return rtl::Uri::encode(
53  decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes,
54  RTL_TEXTENCODING_UTF8);
55 }
56 
57 OUString decodePathSegment(OUString const & encoded) {
58  return rtl::Uri::decode(
59  encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
60 }
61 
62 }
63 
65  : m_nLen(0),
66  m_nWritePos(0),
67  m_pBuffer(nullptr)
68 {
69 }
70 
72 {
73  std::free(m_pBuffer);
74 }
75 
76 
78  const void* pBuffer,
79  size_t size,
80  size_t nmemb
81 ) throw()
82 {
83  sal_uInt32 nLen = size*nmemb;
84  sal_uInt32 tmp(nLen + m_nWritePos);
85 
86  if(m_nLen < tmp) { // enlarge in steps of multiples of 1K
87  do {
88  m_nLen+=1024;
89  } while(m_nLen < tmp);
90 
91  if (auto p = std::realloc(m_pBuffer, m_nLen))
92  m_pBuffer = p;
93  else
94  return 0;
95  }
96 
97  memcpy(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos,
98  pBuffer,nLen);
99  m_nWritePos = tmp;
100  return nLen;
101 }
102 
103 
104 extern "C" {
105 
106  int memory_write(void *buffer,size_t size,size_t nmemb,void *stream)
107  {
108  MemoryContainer *_stream =
109  static_cast<MemoryContainer*>(stream);
110 
111  if(!_stream)
112  return 0;
113 
114  return _stream->append(buffer,size,nmemb);
115  }
116 
117 }
118 
119 
121  : m_pFCP(r.m_pFCP),
122  m_aUsername(r.m_aUsername),
123  m_bShowPassword(r.m_bShowPassword),
124  m_aHost(r.m_aHost),
125  m_aPort(r.m_aPort),
126  m_aPathSegmentVec(r.m_aPathSegmentVec)
127 
128 {
129 }
130 
131 
132 FTPURL::FTPURL(const OUString& url,
133  FTPContentProvider* pFCP)
134  : m_pFCP(pFCP),
135  m_aUsername("anonymous"),
136  m_bShowPassword(false),
137  m_aPort("21")
138 {
139  parse(url); // can reset m_bShowPassword
140 }
141 
142 
144 {
145 }
146 
147 
148 void FTPURL::parse(const OUString& url)
149 {
150  OUString aPassword, urlRest;
151 
152  if(url.getLength() < 6 || !url.startsWithIgnoreAsciiCase("ftp://", &urlRest))
153  throw malformed_exception();
154 
155  // determine "username:password@host:port"
156  OUString aExpr;
157  sal_Int32 nIdx = urlRest.indexOf('/');
158  if (nIdx == -1)
159  {
160  aExpr = urlRest;
161  urlRest = "";
162  }
163  else
164  {
165  aExpr = urlRest.copy(0, nIdx);
166  urlRest = urlRest.copy(nIdx + 1);
167  }
168 
169  sal_Int32 l = aExpr.indexOf('@');
170  m_aHost = aExpr.copy(1+l);
171 
172  if(l != -1) {
173  // Now username and password.
174  aExpr = aExpr.copy(0,l);
175  l = aExpr.indexOf(':');
176  if(l != -1) {
177  aPassword = aExpr.copy(1+l);
178  if(!aPassword.isEmpty())
179  m_bShowPassword = true;
180  }
181  if(l > 0)
182  // Overwritten only if the username is not empty.
183  m_aUsername = aExpr.copy(0,l);
184  else if(!aExpr.isEmpty())
185  m_aUsername = aExpr;
186  }
187 
188  l = m_aHost.lastIndexOf(':');
189  sal_Int32 ipv6Back = m_aHost.lastIndexOf(']');
190  if((ipv6Back == -1 && l != -1) // not ipv6, but a port
191  ||
192  (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port
193  )
194  {
195  if(1+l<m_aHost.getLength())
196  m_aPort = m_aHost.copy(1+l);
197  m_aHost = m_aHost.copy(0,l);
198  }
199 
200  // now determine the pathsegments ...
201  while(!urlRest.isEmpty())
202  {
203  nIdx = urlRest.indexOf('/');
204  OUString segment;
205  if(nIdx == -1)
206  {
207  segment = urlRest;
208  urlRest = "";
209  }
210  else
211  {
212  segment = urlRest.copy(0, nIdx);
213  urlRest = urlRest.copy(nIdx + 1);
214  }
215  if( segment == ".." && !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." )
216  m_aPathSegmentVec.pop_back();
217  else if( segment == "." )
218  ; // Ignore
219  else
220  // This is a legal name.
221  m_aPathSegmentVec.push_back( segment );
222  }
223 
224  if(m_bShowPassword)
226  m_aPort,
227  m_aUsername,
228  aPassword,
229  ""/*aAccount*/);
230 
231  // now check for something like ";type=i" at end of url
232  if(!m_aPathSegmentVec.empty() &&
233  (l = m_aPathSegmentVec.back().indexOf(';')) != -1) {
234  m_aType = m_aPathSegmentVec.back().copy(l);
235  m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l);
236  }
237 }
238 
239 
240 OUString 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,
255  m_aUsername,
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 
289 OUString 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,
301  m_aUsername,
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())
325  last = m_aPathSegmentVec[i];
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).append("/..");
335 
336  bff.append(m_aType);
337  return bff.makeStringAndClear();
338 }
339 
340 
341 void FTPURL::child(const OUString& title)
342 {
343  m_aPathSegmentVec.push_back(encodePathSegment(title));
344 }
345 
346 
347 OUString FTPURL::child() const
348 {
349  return
350  !m_aPathSegmentVec.empty() ?
351  decodePathSegment(m_aPathSegmentVec.back()) : OUString();
352 }
353 
354 
358 namespace ftp {
359 
360  enum OS {
362  };
363 
364 }
365 
366 
367 #define SET_CONTROL_CONTAINER \
368  MemoryContainer control; \
369  curl_easy_setopt(curl, \
370  CURLOPT_HEADERFUNCTION, \
371  memory_write); \
372  curl_easy_setopt(curl, \
373  CURLOPT_WRITEHEADER, \
374  &control)
375 
376 
377 static void setCurlUrl(CURL* curl, OUString const & url)
378 {
379  OString urlParAscii(url.getStr(),
380  url.getLength(),
381  RTL_TEXTENCODING_UTF8);
382  curl_easy_setopt(curl,
383  CURLOPT_URL,
384  urlParAscii.getStr());
385 };
386 
387 oslFileHandle FTPURL::open()
388 {
389  if(m_aPathSegmentVec.empty())
390  throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE);
391 
392  CURL *curl = m_pFCP->handle();
393 
395  OUString url(ident(false,true));
396  setCurlUrl(curl, url);
397 
398  oslFileHandle res( nullptr );
399  if ( osl_createTempFile( nullptr, &res, nullptr ) == osl_File_E_None )
400  {
401  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write);
402  curl_easy_setopt(curl,CURLOPT_WRITEDATA,res);
403 
404  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
405  CURLcode err = curl_easy_perform(curl);
406 
407  if(err == CURLE_OK)
408  {
409  oslFileError rc = osl_setFilePos( res, osl_Pos_Absolut, 0 );
410  SAL_WARN_IF(rc != osl_File_E_None, "ucb.ucp.ftp",
411  "osl_setFilePos failed");
412  }
413  else {
414  osl_closeFile(res);
415  res = nullptr;
416  throw curl_exception(err);
417  }
418  }
419 
420  return res;
421 }
422 
423 
424 std::vector<FTPDirentry> FTPURL::list(
425  sal_Int16 nMode
426 ) const
427 {
428  CURL *curl = m_pFCP->handle();
429 
431  curl_easy_setopt(curl,CURLOPT_NOBODY,false);
432  MemoryContainer data;
433  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write);
434  curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data);
435 
436  OUString url(ident(true,true));
437  setCurlUrl(curl, url);
438  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
439 
440  CURLcode err = curl_easy_perform(curl);
441  if(err != CURLE_OK)
442  throw curl_exception(err);
443 
444  // now evaluate the error messages
445 
446  sal_uInt32 len = data.m_nWritePos;
447  char* fwd = static_cast<char*>(data.m_pBuffer);
448  char *p1, *p2;
449  p1 = p2 = fwd;
450 
451  OS osKind(FTP_UNKNOWN);
452  std::vector<FTPDirentry> resvec;
453  FTPDirentry aDirEntry;
454  // ensure slash at the end
455  OUString viewurl(ident(true,false));
456 
457  while(true) {
458  while(p2-fwd < int(len) && *p2 != '\n') ++p2;
459  if(p2-fwd == int(len)) break;
460 
461  *p2 = 0;
462  switch(osKind) {
463  // While FTP knows the 'system'-command,
464  // which returns the operating system type,
465  // this is not usable here: There are Windows-server
466  // formatting the output like UNIX-ls command.
467  case FTP_DOS:
468  FTPDirectoryParser::parseDOS(aDirEntry,p1);
469  break;
470  case FTP_UNIX:
471  FTPDirectoryParser::parseUNIX(aDirEntry,p1);
472  break;
473  case FTP_VMS:
474  FTPDirectoryParser::parseVMS(aDirEntry,p1);
475  break;
476  default:
477  if(FTPDirectoryParser::parseUNIX(aDirEntry,p1))
478  osKind = FTP_UNIX;
479  else if(FTPDirectoryParser::parseDOS(aDirEntry,p1))
480  osKind = FTP_DOS;
481  else if(FTPDirectoryParser::parseVMS(aDirEntry,p1))
482  osKind = FTP_VMS;
483  }
484  aDirEntry.m_aName = aDirEntry.m_aName.trim();
485  if( osKind != int(FTP_UNKNOWN) && aDirEntry.m_aName != ".." && aDirEntry.m_aName != "." ) {
486  aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName);
487 
488  bool isDir = (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR;
489  switch(nMode) {
490  case OpenMode::DOCUMENTS:
491  if(!isDir)
492  resvec.push_back(aDirEntry);
493  break;
494  case OpenMode::FOLDERS:
495  if(isDir)
496  resvec.push_back(aDirEntry);
497  break;
498  default:
499  resvec.push_back(aDirEntry);
500  };
501  }
502  aDirEntry.clear();
503  p1 = p2 + 1;
504  }
505 
506  return resvec;
507 }
508 
509 
510 OUString FTPURL::net_title() const
511 {
512  CURL *curl = m_pFCP->handle();
513 
515  curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
516  struct curl_slist *slist = nullptr;
517  // post request
518  slist = curl_slist_append(slist,"PWD");
519  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
520 
521  bool try_more(true);
522  CURLcode err;
523  OUString aNetTitle;
524 
525  while(true) {
526  OUString url(ident(false,true));
527 
528  if(try_more && !url.endsWith("/"))
529  url += "/"; // add end-slash
530  else if(!try_more && url.endsWith("/"))
531  url = url.copy(0,url.getLength()-1); // remove end-slash
532 
533  setCurlUrl(curl, url);
534  err = curl_easy_perform(curl);
535 
536  if(err == CURLE_OK) { // get the title from the server
537  char* fwd = static_cast<char*>(control.m_pBuffer);
538  sal_uInt32 len = control.m_nWritePos;
539 
540  aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8);
541  // the buffer now contains the name of the file;
542  // analyze the output:
543  // Format of current working directory:
544  // 257 "/bla/bla" is current directory
545  sal_Int32 index1 = aNetTitle.lastIndexOf("257");
546  index1 = aNetTitle.indexOf('"', index1 + std::strlen("257")) + 1;
547  sal_Int32 index2 = aNetTitle.indexOf('"', index1);
548  aNetTitle = index2 > index1
549  ? aNetTitle.copy(index1, index2 - index1) : OUString();
550  if( aNetTitle != "/" ) {
551  index1 = aNetTitle.lastIndexOf('/');
552  aNetTitle = aNetTitle.copy(1+index1);
553  }
554  try_more = false;
555  } else if(err == CURLE_BAD_PASSWORD_ENTERED)
556  // the client should retry after getting the correct
557  // username + password
558  throw curl_exception(err);
559 #if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */
560  else if(err == CURLE_LOGIN_DENIED)
561  // the client should retry after getting the correct
562  // username + password
563  throw curl_exception(err);
564 #endif
565  else if(try_more && err == CURLE_FTP_ACCESS_DENIED) {
566  // We were either denied access when trying to login to
567  // an FTP server or when trying to change working directory
568  // to the one given in the URL.
569  if(!m_aPathSegmentVec.empty())
570  // determine title form url
571  aNetTitle = decodePathSegment(m_aPathSegmentVec.back());
572  else
573  // must be root
574  aNetTitle = "/";
575  try_more = false;
576  }
577 
578  if(try_more)
579  try_more = false;
580  else
581  break;
582  }
583 
584  curl_slist_free_all(slist);
585  return aNetTitle;
586 }
587 
588 
590 {
591  OUString nettitle = net_title();
592  FTPDirentry aDirentry;
593 
594  aDirentry.m_aName = nettitle; // init aDirentry
595  if( nettitle == "/" || nettitle == ".." )
597  else
599 
600  aDirentry.m_nSize = 0;
601 
602  if( nettitle != "/" ) {
603  // try to open the parent directory
604  FTPURL aURL(parent(),m_pFCP);
605 
606  std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL);
607 
608  for(FTPDirentry & d : aList) {
609  if(d.m_aName == nettitle) { // the relevant file is found
610  aDirentry = d;
611  break;
612  }
613  }
614  }
615  return aDirentry;
616 }
617 
618 
619 extern "C" {
620 
621  static size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream)
622  {
623  sal_Int32 nRequested = sal_Int32(size*nmemb);
624  CurlInput *curlInput = static_cast<CurlInput*>(stream);
625  if(curlInput)
626  return size_t(curlInput->read(static_cast<sal_Int8*>(ptr),nRequested));
627  else
628  return 0;
629  }
630 
631 }
632 
633 
634 void FTPURL::insert(bool replaceExisting,void* stream) const
635 {
636  if(!replaceExisting) {
637 // FTPDirentry aDirentry(direntry());
638 // if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN)
639  // throw curl_exception(FILE_EXIST_DURING_INSERT);
641  } // else
642  // overwrite is default in libcurl
643 
644  CURL *curl = m_pFCP->handle();
645 
647  curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer
648  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0);
649  curl_easy_setopt(curl,CURLOPT_QUOTE,0);
650  curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read);
651  curl_easy_setopt(curl,CURLOPT_READDATA,stream);
652  curl_easy_setopt(curl, CURLOPT_UPLOAD,1);
653 
654  OUString url(ident(false,true));
655  setCurlUrl(curl, url);
656 
657  CURLcode err = curl_easy_perform(curl);
658  curl_easy_setopt(curl, CURLOPT_UPLOAD,false);
659 
660  if(err != CURLE_OK)
661  throw curl_exception(err);
662 }
663 
664 
665 void FTPURL::mkdir(bool ReplaceExisting) const
666 {
667  OString title;
668  if(!m_aPathSegmentVec.empty()) {
669  OUString titleOU = m_aPathSegmentVec.back();
670  titleOU = decodePathSegment(titleOU);
671  title = OString(titleOU.getStr(),
672  titleOU.getLength(),
673  RTL_TEXTENCODING_UTF8);
674  }
675  else
676  // will give an error
677  title = OString("/");
678 
679  OString aDel("del "); aDel += title;
680  OString mkd("mkd "); mkd += title;
681 
682  struct curl_slist *slist = nullptr;
683 
684  FTPDirentry aDirentry(direntry());
685  if(!ReplaceExisting) {
686 // if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
687 // throw curl_exception(FOLDER_EXIST_DURING_INSERT);
689  } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
690  slist = curl_slist_append(slist,aDel.getStr());
691 
692  slist = curl_slist_append(slist,mkd.getStr());
693 
694  CURL *curl = m_pFCP->handle();
696  curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
697  curl_easy_setopt(curl,CURLOPT_QUOTE,0);
698 
699  // post request
700  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
701 
702  OUString url(parent(true));
703  if(!url.endsWith("/"))
704  url += "/";
705  setCurlUrl(curl, url);
706 
707  CURLcode err = curl_easy_perform(curl);
708  curl_slist_free_all(slist);
709  if(err != CURLE_OK)
710  throw curl_exception(err);
711 }
712 
713 
714 OUString FTPURL::ren(const OUString& NewTitle)
715 {
716  CURL *curl = m_pFCP->handle();
717 
718  // post request
719  OString renamefrom("RNFR ");
720  OUString OldTitle = net_title();
721  renamefrom +=
722  OString(OldTitle.getStr(),
723  OldTitle.getLength(),
724  RTL_TEXTENCODING_UTF8);
725 
726  OString renameto("RNTO ");
727  renameto +=
728  OString(NewTitle.getStr(),
729  NewTitle.getLength(),
730  RTL_TEXTENCODING_UTF8);
731 
732  struct curl_slist *slist = nullptr;
733  slist = curl_slist_append(slist,renamefrom.getStr());
734  slist = curl_slist_append(slist,renameto.getStr());
735  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
736 
738  curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
739  curl_easy_setopt(curl,CURLOPT_QUOTE,0);
740 
741  OUString url(parent(true));
742  if(!url.endsWith("/"))
743  url += "/";
744  setCurlUrl(curl, url);
745 
746  CURLcode err = curl_easy_perform(curl);
747  curl_slist_free_all(slist);
748  if(err != CURLE_OK)
749  throw curl_exception(err);
750  else if( !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." )
751  m_aPathSegmentVec.back() = encodePathSegment(NewTitle);
752  return OldTitle;
753 }
754 
755 
756 void FTPURL::del() const
757 {
758  FTPDirentry aDirentry(direntry());
759 
760  OString dele(aDirentry.m_aName.getStr(),
761  aDirentry.m_aName.getLength(),
762  RTL_TEXTENCODING_UTF8);
763 
764  if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) {
765  std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL));
766  for(const FTPDirentry & i : vec)
767  {
768  try {
769  FTPURL url(i.m_aURL,m_pFCP);
770  url.del();
771  } catch(const curl_exception&) {
772  }
773  }
774  dele = OString("RMD ") + dele;
775  }
776  else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN)
777  dele = OString("DELE ") + dele;
778  else
779  return;
780 
781  // post request
782  CURL *curl = m_pFCP->handle();
783  struct curl_slist *slist = nullptr;
784  slist = curl_slist_append(slist,dele.getStr());
785  curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist);
786 
788  curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer
789  curl_easy_setopt(curl,CURLOPT_QUOTE,0);
790 
791  OUString url(parent(true));
792  if(!url.endsWith("/"))
793  url += "/";
794  setCurlUrl(curl, url);
795 
796  CURLcode err = curl_easy_perform(curl);
797  curl_slist_free_all(slist);
798  if(err != CURLE_OK)
799  throw curl_exception(err);
800 }
801 
802 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
int memory_write(void *buffer, size_t size, size_t nmemb, void *stream)
Definition: ftpurl.cxx:106
void parse(const OUString &url)
Definition: ftpurl.cxx:148
FTPURL(const OUString &aIdent, FTPContentProvider *pFCP)
Definition: ftpurl.cxx:132
bool setHost(const OUString &host, const OUString &port, const OUString &username, const OUString &password, const OUString &account)
OUString net_title() const
Definition: ftpurl.cxx:510
OUString child() const
returns the unencoded title
Definition: ftpurl.cxx:347
static bool parseUNIX(FTPDirentry &rEntry, const sal_Char *pBuffer)
Definition: ftpdirp.cxx:843
void mkdir(bool ReplaceExisting) const
Definition: ftpurl.cxx:665
static void setCurlUrl(CURL *curl, OUString const &url)
Definition: ftpurl.cxx:377
OUString parent(bool internal=false) const
returns the parent url.
Definition: ftpurl.cxx:289
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:34
std::vector< FTPDirentry > list(sal_Int16 nMode) const
Definition: ftpurl.cxx:424
sal_uInt32 m_nMode
Definition: ftpdirp.hxx:77
FTPContentProvider * m_pFCP
Definition: ftpurl.hxx:143
FTPDirentry direntry() const
Definition: ftpurl.cxx:589
OUString m_aHost
Definition: ftpurl.hxx:147
err
OUString ren(const OUString &NewTitle)
Definition: ftpurl.cxx:714
void del() const
Definition: ftpurl.cxx:756
void insert(bool ReplaceExisting, void *stream) const
Definition: ftpurl.cxx:634
bool m_bShowPassword
Definition: ftpurl.hxx:146
int i
static bool parseDOS(FTPDirentry &rEntry, const sal_Char *pBuffer)
Definition: ftpdirp.cxx:59
Definition of ftpcontentprovider.
size
static size_t memory_read(void *ptr, size_t size, size_t nmemb, void *stream)
Definition: ftpurl.cxx:621
OS
Definition: ftpurl.cxx:360
OUString m_aURL
Definition: ftpdirp.hxx:74
virtual sal_Int32 read(sal_Int8 *dest, sal_Int32 nBytesRequested)=0
#define SAL_WARN_IF(condition, area, stream)
OUString m_aUsername
Definition: ftpurl.hxx:145
void forHost(const OUString &host, const OUString &port, const OUString &username, OUString &password, OUString &account)
host is in the form host:port.
sal_uInt32 m_nSize
Definition: ftpdirp.hxx:78
OUString m_aPort
Definition: ftpurl.hxx:148
oslFileHandle open()
Definition: ftpurl.cxx:387
OUString m_aType
Definition: ftpurl.hxx:149
OUString ident(bool withslash, bool internal) const
This returns the URL, but cleaned from unnessary ellipses.
Definition: ftpurl.cxx:240
OUString m_aName
Definition: ftpdirp.hxx:75
#define SET_CONTROL_CONTAINER
Definition: ftpurl.cxx:367
int append(const void *pBuffer, size_t size, size_t nmemb)
Definition: ftpurl.cxx:77
std::vector< OUString > m_aPathSegmentVec
Contains the encoded pathsegments of the url.
Definition: ftpurl.hxx:153
void SAL_CALL last(const css::awt::SpinEvent &rEvent) override
static bool parseVMS(FTPDirentry &rEntry, const sal_Char *pBuffer)
Definition: ftpdirp.cxx:556