1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
24 #include <rtl/uri.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <ucbhelper/content.hxx>
27 #include <xmlscript/xml_helper.hxx>
28 #include <com/sun/star/io/XOutputStream.hpp>
29 #include <com/sun/star/ucb/CommandFailedException.hpp>
30 #include <com/sun/star/ucb/ContentInfo.hpp>
31 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
32 #include <com/sun/star/ucb/ContentCreationException.hpp>
33 #include <comphelper/processfactory.hxx>
35 using namespace ::com::sun::star
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::ucb
;
43 bool create_ucb_content(
44 ::ucbhelper::Content
* ret_ucbContent
, OUString
const & url
,
45 Reference
<XCommandEnvironment
> const & xCmdEnv
,
50 // content ctor/isFolder() will throw exception in case the resource
53 // dilemma: no chance to use the given handler here, because it would
54 // raise no such file dialogs, else no interaction for
55 // passwords, ...? xxx todo
56 ::ucbhelper::Content
ucbContent(
57 url
, Reference
<XCommandEnvironment
>(),
58 comphelper::getProcessComponentContext() );
60 ucbContent
.isFolder();
62 if (ret_ucbContent
!= nullptr)
64 ucbContent
.setCommandEnvironment( xCmdEnv
);
65 *ret_ucbContent
= std::move(ucbContent
);
69 catch (const RuntimeException
&) {
72 catch (const Exception
&) {
81 ::ucbhelper::Content
* ret_ucb_content
, OUString
const & url_
,
82 Reference
<XCommandEnvironment
> const & xCmdEnv
, bool throw_exc
)
84 ::ucbhelper::Content ucb_content
;
85 if (create_ucb_content(
86 &ucb_content
, url_
, xCmdEnv
, false /* no throw */ ))
88 if (ucb_content
.isFolder()) {
89 if (ret_ucb_content
!= nullptr)
90 *ret_ucb_content
= ucb_content
;
96 // xxx todo: find parent
97 sal_Int32 slash
= url
.lastIndexOf( '/' );
100 url
= expandUnoRcUrl( url
);
101 slash
= url
.lastIndexOf( '/' );
104 // invalid: has to be at least "auth:/..."
106 throw ContentCreationException(
107 "Cannot create folder (invalid path): '" + url
+ "'",
108 Reference
<XInterface
>(), ContentCreationError_UNKNOWN
);
111 ::ucbhelper::Content parentContent
;
113 &parentContent
, url
.copy( 0, slash
), xCmdEnv
, throw_exc
))
115 const Any
title( ::rtl::Uri::decode( url
.copy( slash
+ 1 ),
116 rtl_UriDecodeWithCharset
,
117 RTL_TEXTENCODING_UTF8
) );
118 const Sequence
<ContentInfo
> infos(
119 parentContent
.queryCreatableContentsInfo() );
120 for ( ContentInfo
const & info
: infos
)
123 if ((info
.Attributes
& ContentInfoAttribute::KIND_FOLDER
) != 0)
125 // make sure the only required bootstrap property is "Title":
126 Sequence
<beans::Property
> const & rProps
= info
.Properties
;
127 if ( rProps
.getLength() != 1 || rProps
[ 0 ].Name
!= "Title" )
131 if (parentContent
.insertNewContent(
133 StrTitle::getTitleSequence(),
134 Sequence
<Any
>( &title
, 1 ),
136 if (ret_ucb_content
!= nullptr)
137 *ret_ucb_content
= ucb_content
;
141 catch (const RuntimeException
&) {
144 catch (const CommandFailedException
&) {
145 // Interaction Handler already handled the error
146 // that has occurred...
148 catch (const Exception
&) {
156 throw ContentCreationException(
157 "Cannot create folder: '" + url
+ "'",
158 Reference
<XInterface
>(), ContentCreationError_UNKNOWN
);
163 bool erase_path( OUString
const & url
,
164 Reference
<XCommandEnvironment
> const & xCmdEnv
,
167 ::ucbhelper::Content ucb_content
;
168 if (create_ucb_content( &ucb_content
, url
, xCmdEnv
, false /* no throw */ ))
171 ucb_content
.executeCommand(
172 u
"delete"_ustr
, Any( true /* delete physically */ ) );
174 catch (const RuntimeException
&) {
177 catch (const Exception
&) {
187 std::vector
<sal_Int8
> readFile( ::ucbhelper::Content
& ucb_content
)
189 std::vector
<sal_Int8
> bytes
;
190 Reference
<io::XOutputStream
> xStream(
191 ::xmlscript::createOutputStream( &bytes
) );
192 if (! ucb_content
.openStream( xStream
))
193 throw RuntimeException(
194 u
"::ucbhelper::Content::openStream( XOutputStream ) failed!"_ustr
,
200 bool readLine( OUString
* res
, std::u16string_view startingWith
,
201 ::ucbhelper::Content
& ucb_content
, rtl_TextEncoding textenc
)
204 std::vector
<sal_Int8
> bytes( readFile( ucb_content
) );
205 OUString
file( reinterpret_cast<char const *>(bytes
.data()),
206 bytes
.size(), textenc
);
210 if (file
.match( startingWith
, pos
))
213 sal_Int32 start
= pos
;
214 pos
+= startingWith
.size();
217 pos
= file
.indexOf( LF
, pos
);
218 if (pos
< 0) { // EOF
219 buf
.append( file
.subView(start
) );
223 if (pos
> 0 && file
[ pos
- 1 ] == CR
)
226 buf
.append( file
.subView(start
, pos
- start
- 1) );
230 buf
.append( file
.subView(start
, pos
- start
) );
233 if (pos
< file
.getLength() &&
234 (file
[ pos
] == ' ' || file
[ pos
] == '\t'))
244 *res
= buf
.makeStringAndClear();
248 sal_Int32 next_lf
= file
.indexOf( LF
, pos
);
249 if (next_lf
< 0) // EOF
256 bool readProperties( std::vector
< std::pair
< OUString
, OUString
> > & out_result
,
257 ::ucbhelper::Content
& ucb_content
)
260 std::vector
<sal_Int8
> bytes( readFile( ucb_content
) );
261 OUString
file( reinterpret_cast<char const *>(bytes
.data()),
262 bytes
.size(), RTL_TEXTENCODING_UTF8
);
269 sal_Int32 start
= pos
;
272 pos
= file
.indexOf( LF
, pos
);
273 if (pos
< 0) { // EOF
274 buf
.append( file
.subView(start
) );
279 if (pos
> 0 && file
[ pos
- 1 ] == CR
)
281 buf
.append( file
.subView(start
, pos
- start
- 1) );
283 buf
.append( file
.subView(start
, pos
- start
) );
286 OUString aLine
= buf
.makeStringAndClear();
288 sal_Int32 posEqual
= aLine
.indexOf('=');
289 if (posEqual
> 0 && (posEqual
+ 1) < aLine
.getLength())
291 OUString name
= aLine
.copy(0, posEqual
);
292 OUString value
= aLine
.copy(posEqual
+ 1);
293 out_result
.emplace_back(name
, value
);
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */