Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / desktop / source / deployment / misc / dp_ucb.cxx
blob35be6bb909181efa06a2d151bd4d0bce49857373
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
24 #include <dp_misc.h>
25 #include <dp_ucb.h>
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;
41 namespace dp_misc
45 bool create_ucb_content(
46 ::ucbhelper::Content * ret_ucbContent, OUString const & url,
47 Reference<XCommandEnvironment> const & xCmdEnv,
48 bool throw_exc )
50 try {
51 // Existence check...
52 // content ctor/isFolder() will throw exception in case the resource
53 // does not exist.
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;
69 return true;
71 catch (const RuntimeException &) {
72 throw;
74 catch (const Exception &) {
75 if (throw_exc)
76 throw;
78 return false;
82 bool create_folder(
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;
93 return true;
97 OUString url( url_ );
98 // xxx todo: find parent
99 sal_Int32 slash = url.lastIndexOf( '/' );
100 if (slash < 0) {
101 // fallback:
102 url = expandUnoRcUrl( url );
103 slash = url.lastIndexOf( '/' );
105 if (slash < 0) {
106 // invalid: has to be at least "auth:/..."
107 if (throw_exc)
108 throw ContentCreationException(
109 "Cannot create folder (invalid path): '" + url + "'",
110 Reference<XInterface>(), ContentCreationError_UNKNOWN );
111 return false;
113 ::ucbhelper::Content parentContent;
114 if (! create_folder(
115 &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc ))
116 return false;
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 )
124 // look KIND_FOLDER:
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" )
131 continue;
133 try {
134 if (parentContent.insertNewContent(
135 info.Type,
136 StrTitle::getTitleSequence(),
137 Sequence<Any>( &title, 1 ),
138 ucb_content )) {
139 if (ret_ucb_content != nullptr)
140 *ret_ucb_content = ucb_content;
141 return true;
144 catch (const RuntimeException &) {
145 throw;
147 catch (const CommandFailedException &) {
148 // Interaction Handler already handled the error
149 // that has occurred...
151 catch (const Exception &) {
152 if (throw_exc)
153 throw;
154 return false;
158 if (throw_exc)
159 throw ContentCreationException(
160 "Cannot create folder: '" + url + "'",
161 Reference<XInterface>(), ContentCreationError_UNKNOWN );
162 return false;
166 bool erase_path( OUString const & url,
167 Reference<XCommandEnvironment> const & xCmdEnv,
168 bool throw_exc )
170 ::ucbhelper::Content ucb_content;
171 if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
173 try {
174 ucb_content.executeCommand(
175 "delete", Any( true /* delete physically */ ) );
177 catch (const RuntimeException &) {
178 throw;
180 catch (const Exception &) {
181 if (throw_exc)
182 throw;
183 return false;
186 return true;
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!",
198 nullptr );
199 return bytes;
203 bool readLine( OUString * res, OUString const & startingWith,
204 ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
206 // read whole file:
207 std::vector<sal_Int8> bytes( readFile( ucb_content ) );
208 OUString file( reinterpret_cast<sal_Char const *>(bytes.data()),
209 bytes.size(), textenc );
210 sal_Int32 pos = 0;
211 for (;;)
213 if (file.match( startingWith, pos ))
215 OUStringBuffer buf;
216 sal_Int32 start = pos;
217 pos += startingWith.getLength();
218 for (;;)
220 pos = file.indexOf( LF, pos );
221 if (pos < 0) { // EOF
222 buf.append( std::u16string_view(file).substr(start) );
224 else
226 if (pos > 0 && file[ pos - 1 ] == CR)
228 // consume extra CR
229 buf.append( std::u16string_view(file).substr(start, pos - start - 1) );
230 ++pos;
232 else
233 buf.append( std::u16string_view(file).substr(start, pos - start) );
234 ++pos; // consume LF
235 // check next line:
236 if (pos < file.getLength() &&
237 (file[ pos ] == ' ' || file[ pos ] == '\t'))
239 buf.append( ' ' );
240 ++pos;
241 start = pos;
242 continue;
245 break;
247 *res = buf.makeStringAndClear();
248 return true;
250 // next line:
251 sal_Int32 next_lf = file.indexOf( LF, pos );
252 if (next_lf < 0) // EOF
253 break;
254 pos = next_lf + 1;
256 return false;
259 bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
260 ::ucbhelper::Content & ucb_content )
262 // read whole file:
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);
266 sal_Int32 pos = 0;
268 for (;;)
271 OUStringBuffer buf;
272 sal_Int32 start = pos;
274 bool bEOF = false;
275 pos = file.indexOf( LF, pos );
276 if (pos < 0) { // EOF
277 buf.append( std::u16string_view(file).substr(start) );
278 bEOF = true;
280 else
282 if (pos > 0 && file[ pos - 1 ] == CR)
283 // consume extra CR
284 buf.append( std::u16string_view(file).substr(start, pos - start - 1) );
285 else
286 buf.append( std::u16string_view(file).substr(start, pos - start) );
287 pos++;
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);
299 if (bEOF)
300 break;
302 return false;
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */