use insert function instead of for loop
[LibreOffice.git] / desktop / source / deployment / misc / dp_ucb.cxx
blobcb92c8bd76a599368cab8228af85a5c40a6c3d66
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 <dp_misc.h>
23 #include <dp_ucb.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;
39 namespace dp_misc
43 bool create_ucb_content(
44 ::ucbhelper::Content * ret_ucbContent, OUString const & url,
45 Reference<XCommandEnvironment> const & xCmdEnv,
46 bool throw_exc )
48 try {
49 // Existence check...
50 // content ctor/isFolder() will throw exception in case the resource
51 // does not exist.
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);
67 return true;
69 catch (const RuntimeException &) {
70 throw;
72 catch (const Exception &) {
73 if (throw_exc)
74 throw;
76 return false;
80 bool create_folder(
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;
91 return true;
95 OUString url( url_ );
96 // xxx todo: find parent
97 sal_Int32 slash = url.lastIndexOf( '/' );
98 if (slash < 0) {
99 // fallback:
100 url = expandUnoRcUrl( url );
101 slash = url.lastIndexOf( '/' );
103 if (slash < 0) {
104 // invalid: has to be at least "auth:/..."
105 if (throw_exc)
106 throw ContentCreationException(
107 "Cannot create folder (invalid path): '" + url + "'",
108 Reference<XInterface>(), ContentCreationError_UNKNOWN );
109 return false;
111 ::ucbhelper::Content parentContent;
112 if (! create_folder(
113 &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc ))
114 return false;
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 )
122 // look KIND_FOLDER:
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" )
128 continue;
130 try {
131 if (parentContent.insertNewContent(
132 info.Type,
133 StrTitle::getTitleSequence(),
134 Sequence<Any>( &title, 1 ),
135 ucb_content )) {
136 if (ret_ucb_content != nullptr)
137 *ret_ucb_content = ucb_content;
138 return true;
141 catch (const RuntimeException &) {
142 throw;
144 catch (const CommandFailedException &) {
145 // Interaction Handler already handled the error
146 // that has occurred...
148 catch (const Exception &) {
149 if (throw_exc)
150 throw;
151 return false;
155 if (throw_exc)
156 throw ContentCreationException(
157 "Cannot create folder: '" + url + "'",
158 Reference<XInterface>(), ContentCreationError_UNKNOWN );
159 return false;
163 bool erase_path( OUString const & url,
164 Reference<XCommandEnvironment> const & xCmdEnv,
165 bool throw_exc )
167 ::ucbhelper::Content ucb_content;
168 if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
170 try {
171 ucb_content.executeCommand(
172 u"delete"_ustr, Any( true /* delete physically */ ) );
174 catch (const RuntimeException &) {
175 throw;
177 catch (const Exception &) {
178 if (throw_exc)
179 throw;
180 return false;
183 return true;
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,
195 nullptr );
196 return bytes;
200 bool readLine( OUString * res, std::u16string_view startingWith,
201 ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
203 // read whole file:
204 std::vector<sal_Int8> bytes( readFile( ucb_content ) );
205 OUString file( reinterpret_cast<char const *>(bytes.data()),
206 bytes.size(), textenc );
207 sal_Int32 pos = 0;
208 for (;;)
210 if (file.match( startingWith, pos ))
212 OUStringBuffer buf;
213 sal_Int32 start = pos;
214 pos += startingWith.size();
215 for (;;)
217 pos = file.indexOf( LF, pos );
218 if (pos < 0) { // EOF
219 buf.append( file.subView(start) );
221 else
223 if (pos > 0 && file[ pos - 1 ] == CR)
225 // consume extra CR
226 buf.append( file.subView(start, pos - start - 1) );
227 ++pos;
229 else
230 buf.append( file.subView(start, pos - start) );
231 ++pos; // consume LF
232 // check next line:
233 if (pos < file.getLength() &&
234 (file[ pos ] == ' ' || file[ pos ] == '\t'))
236 buf.append( ' ' );
237 ++pos;
238 start = pos;
239 continue;
242 break;
244 *res = buf.makeStringAndClear();
245 return true;
247 // next line:
248 sal_Int32 next_lf = file.indexOf( LF, pos );
249 if (next_lf < 0) // EOF
250 break;
251 pos = next_lf + 1;
253 return false;
256 bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
257 ::ucbhelper::Content & ucb_content )
259 // read whole file:
260 std::vector<sal_Int8> bytes( readFile( ucb_content ) );
261 OUString file( reinterpret_cast<char const *>(bytes.data()),
262 bytes.size(), RTL_TEXTENCODING_UTF8);
263 sal_Int32 pos = 0;
265 for (;;)
268 OUStringBuffer buf;
269 sal_Int32 start = pos;
271 bool bEOF = false;
272 pos = file.indexOf( LF, pos );
273 if (pos < 0) { // EOF
274 buf.append( file.subView(start) );
275 bEOF = true;
277 else
279 if (pos > 0 && file[ pos - 1 ] == CR)
280 // consume extra CR
281 buf.append( file.subView(start, pos - start - 1) );
282 else
283 buf.append( file.subView(start, pos - start) );
284 pos++;
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);
296 if (bEOF)
297 break;
299 return false;
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */