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