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>
22 #include <string_view>
26 #include <rtl/uri.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <ucbhelper/content.hxx>
29 #include <xmlscript/xml_helper.hxx>
30 #include <com/sun/star/io/XInputStream.hpp>
31 #include <com/sun/star/ucb/CommandFailedException.hpp>
32 #include <com/sun/star/ucb/ContentInfo.hpp>
33 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
34 #include <com/sun/star/ucb/ContentCreationException.hpp>
35 #include <comphelper/processfactory.hxx>
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::ucb
;
45 bool create_ucb_content(
46 ::ucbhelper::Content
* ret_ucbContent
, OUString
const & url
,
47 Reference
<XCommandEnvironment
> const & xCmdEnv
,
52 // content ctor/isFolder() will throw exception in case the resource
55 // dilemma: no chance to use the given handler here, because it would
56 // raise no such file dialogs, else no interaction for
57 // passwords, ...? xxx todo
58 ::ucbhelper::Content
ucbContent(
59 url
, Reference
<XCommandEnvironment
>(),
60 comphelper::getProcessComponentContext() );
62 ucbContent
.isFolder();
64 if (ret_ucbContent
!= nullptr)
66 ucbContent
.setCommandEnvironment( xCmdEnv
);
67 *ret_ucbContent
= ucbContent
;
71 catch (const RuntimeException
&) {
74 catch (const Exception
&) {
83 ::ucbhelper::Content
* ret_ucb_content
, OUString
const & url_
,
84 Reference
<XCommandEnvironment
> const & xCmdEnv
, bool throw_exc
)
86 ::ucbhelper::Content ucb_content
;
87 if (create_ucb_content(
88 &ucb_content
, url_
, xCmdEnv
, false /* no throw */ ))
90 if (ucb_content
.isFolder()) {
91 if (ret_ucb_content
!= nullptr)
92 *ret_ucb_content
= ucb_content
;
98 // xxx todo: find parent
99 sal_Int32 slash
= url
.lastIndexOf( '/' );
102 url
= expandUnoRcUrl( url
);
103 slash
= url
.lastIndexOf( '/' );
106 // invalid: has to be at least "auth:/..."
108 throw ContentCreationException(
109 "Cannot create folder (invalid path): '" + url
+ "'",
110 Reference
<XInterface
>(), ContentCreationError_UNKNOWN
);
113 ::ucbhelper::Content parentContent
;
115 &parentContent
, url
.copy( 0, slash
), xCmdEnv
, throw_exc
))
117 const Any
title( ::rtl::Uri::decode( url
.copy( slash
+ 1 ),
118 rtl_UriDecodeWithCharset
,
119 RTL_TEXTENCODING_UTF8
) );
120 const Sequence
<ContentInfo
> infos(
121 parentContent
.queryCreatableContentsInfo() );
122 for ( sal_Int32 pos
= 0; pos
< infos
.getLength(); ++pos
)
125 ContentInfo
const & info
= infos
[ pos
];
126 if ((info
.Attributes
& ContentInfoAttribute::KIND_FOLDER
) != 0)
128 // make sure the only required bootstrap property is "Title":
129 Sequence
<beans::Property
> const & rProps
= info
.Properties
;
130 if ( rProps
.getLength() != 1 || rProps
[ 0 ].Name
!= "Title" )
134 if (parentContent
.insertNewContent(
136 StrTitle::getTitleSequence(),
137 Sequence
<Any
>( &title
, 1 ),
139 if (ret_ucb_content
!= nullptr)
140 *ret_ucb_content
= ucb_content
;
144 catch (const RuntimeException
&) {
147 catch (const CommandFailedException
&) {
148 // Interaction Handler already handled the error
149 // that has occurred...
151 catch (const Exception
&) {
159 throw ContentCreationException(
160 "Cannot create folder: '" + url
+ "'",
161 Reference
<XInterface
>(), ContentCreationError_UNKNOWN
);
166 bool erase_path( OUString
const & url
,
167 Reference
<XCommandEnvironment
> const & xCmdEnv
,
170 ::ucbhelper::Content ucb_content
;
171 if (create_ucb_content( &ucb_content
, url
, xCmdEnv
, false /* no throw */ ))
174 ucb_content
.executeCommand(
175 "delete", Any( true /* delete physically */ ) );
177 catch (const RuntimeException
&) {
180 catch (const Exception
&) {
190 std::vector
<sal_Int8
> readFile( ::ucbhelper::Content
& ucb_content
)
192 std::vector
<sal_Int8
> bytes
;
193 Reference
<io::XOutputStream
> xStream(
194 ::xmlscript::createOutputStream( &bytes
) );
195 if (! ucb_content
.openStream( xStream
))
196 throw RuntimeException(
197 "::ucbhelper::Content::openStream( XOutputStream ) failed!",
203 bool readLine( OUString
* res
, OUString
const & startingWith
,
204 ::ucbhelper::Content
& ucb_content
, rtl_TextEncoding textenc
)
207 std::vector
<sal_Int8
> bytes( readFile( ucb_content
) );
208 OUString
file( reinterpret_cast<sal_Char
const *>(bytes
.data()),
209 bytes
.size(), textenc
);
213 if (file
.match( startingWith
, pos
))
216 sal_Int32 start
= pos
;
217 pos
+= startingWith
.getLength();
220 pos
= file
.indexOf( LF
, pos
);
221 if (pos
< 0) { // EOF
222 buf
.append( std::u16string_view(file
).substr(start
) );
226 if (pos
> 0 && file
[ pos
- 1 ] == CR
)
229 buf
.append( std::u16string_view(file
).substr(start
, pos
- start
- 1) );
233 buf
.append( std::u16string_view(file
).substr(start
, pos
- start
) );
236 if (pos
< file
.getLength() &&
237 (file
[ pos
] == ' ' || file
[ pos
] == '\t'))
247 *res
= buf
.makeStringAndClear();
251 sal_Int32 next_lf
= file
.indexOf( LF
, pos
);
252 if (next_lf
< 0) // EOF
259 bool readProperties( std::vector
< std::pair
< OUString
, OUString
> > & out_result
,
260 ::ucbhelper::Content
& ucb_content
)
263 std::vector
<sal_Int8
> bytes( readFile( ucb_content
) );
264 OUString
file( reinterpret_cast<sal_Char
const *>(bytes
.data()),
265 bytes
.size(), RTL_TEXTENCODING_UTF8
);
272 sal_Int32 start
= pos
;
275 pos
= file
.indexOf( LF
, pos
);
276 if (pos
< 0) { // EOF
277 buf
.append( std::u16string_view(file
).substr(start
) );
282 if (pos
> 0 && file
[ pos
- 1 ] == CR
)
284 buf
.append( std::u16string_view(file
).substr(start
, pos
- start
- 1) );
286 buf
.append( std::u16string_view(file
).substr(start
, pos
- start
) );
289 OUString aLine
= buf
.makeStringAndClear();
291 sal_Int32 posEqual
= aLine
.indexOf('=');
292 if (posEqual
> 0 && (posEqual
+ 1) < aLine
.getLength())
294 OUString name
= aLine
.copy(0, posEqual
);
295 OUString value
= aLine
.copy(posEqual
+ 1);
296 out_result
.emplace_back(name
, value
);
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */