LibreOffice Module desktop (master) 1
dp_ucb.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
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>
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>
34
35using namespace ::com::sun::star;
36using namespace ::com::sun::star::uno;
37using namespace ::com::sun::star::ucb;
38
39namespace dp_misc
40{
41
42
44 ::ucbhelper::Content * ret_ucbContent, OUString const & url,
45 Reference<XCommandEnvironment> const & xCmdEnv,
46 bool throw_exc )
47{
48 try {
49 // Existence check...
50 // content ctor/isFolder() will throw exception in case the resource
51 // does not exist.
52
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>(),
59
60 ucbContent.isFolder();
61
62 if (ret_ucbContent != nullptr)
63 {
64 ucbContent.setCommandEnvironment( xCmdEnv );
65 *ret_ucbContent = ucbContent;
66 }
67 return true;
68 }
69 catch (const RuntimeException &) {
70 throw;
71 }
72 catch (const Exception &) {
73 if (throw_exc)
74 throw;
75 }
76 return false;
77}
78
79
81 ::ucbhelper::Content * ret_ucb_content, OUString const & url_,
82 Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc )
83{
84 ::ucbhelper::Content ucb_content;
86 &ucb_content, url_, xCmdEnv, false /* no throw */ ))
87 {
88 if (ucb_content.isFolder()) {
89 if (ret_ucb_content != nullptr)
90 *ret_ucb_content = ucb_content;
91 return true;
92 }
93 }
94
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( '/' );
102 }
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;
110 }
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 )
121 {
122 // look KIND_FOLDER:
123 if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
124 {
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;
129
130 try {
131 if (parentContent.insertNewContent(
132 info.Type,
134 Sequence<Any>( &title, 1 ),
135 ucb_content )) {
136 if (ret_ucb_content != nullptr)
137 *ret_ucb_content = ucb_content;
138 return true;
139 }
140 }
141 catch (const RuntimeException &) {
142 throw;
143 }
144 catch (const CommandFailedException &) {
145 // Interaction Handler already handled the error
146 // that has occurred...
147 }
148 catch (const Exception &) {
149 if (throw_exc)
150 throw;
151 return false;
152 }
153 }
154 }
155 if (throw_exc)
156 throw ContentCreationException(
157 "Cannot create folder: '" + url + "'",
158 Reference<XInterface>(), ContentCreationError_UNKNOWN );
159 return false;
160}
161
162
163bool erase_path( OUString const & url,
164 Reference<XCommandEnvironment> const & xCmdEnv,
165 bool throw_exc )
166{
167 ::ucbhelper::Content ucb_content;
168 if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
169 {
170 try {
171 ucb_content.executeCommand(
172 "delete", Any( true /* delete physically */ ) );
173 }
174 catch (const RuntimeException &) {
175 throw;
176 }
177 catch (const Exception &) {
178 if (throw_exc)
179 throw;
180 return false;
181 }
182 }
183 return true;
184}
185
186
187std::vector<sal_Int8> readFile( ::ucbhelper::Content & ucb_content )
188{
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 "::ucbhelper::Content::openStream( XOutputStream ) failed!",
195 nullptr );
196 return bytes;
197}
198
199
200bool readLine( OUString * res, std::u16string_view startingWith,
201 ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
202{
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 (;;)
209 {
210 if (file.match( startingWith, pos ))
211 {
212 OUStringBuffer buf;
213 sal_Int32 start = pos;
214 pos += startingWith.size();
215 for (;;)
216 {
217 pos = file.indexOf( LF, pos );
218 if (pos < 0) { // EOF
219 buf.append( file.subView(start) );
220 }
221 else
222 {
223 if (pos > 0 && file[ pos - 1 ] == CR)
224 {
225 // consume extra CR
226 buf.append( file.subView(start, pos - start - 1) );
227 ++pos;
228 }
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'))
235 {
236 buf.append( ' ' );
237 ++pos;
238 start = pos;
239 continue;
240 }
241 }
242 break;
243 }
244 *res = buf.makeStringAndClear();
245 return true;
246 }
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;
252 }
253 return false;
254}
255
256bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
257 ::ucbhelper::Content & ucb_content )
258{
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;
264
265 for (;;)
266 {
267
268 OUStringBuffer buf;
269 sal_Int32 start = pos;
270
271 bool bEOF = false;
272 pos = file.indexOf( LF, pos );
273 if (pos < 0) { // EOF
274 buf.append( file.subView(start) );
275 bEOF = true;
276 }
277 else
278 {
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++;
285 }
286 OUString aLine = buf.makeStringAndClear();
287
288 sal_Int32 posEqual = aLine.indexOf('=');
289 if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
290 {
291 OUString name = aLine.copy(0, posEqual);
292 OUString value = aLine.copy(posEqual + 1);
293 out_result.emplace_back(name, value);
294 }
295
296 if (bEOF)
297 break;
298 }
299 return false;
300}
301
302}
303
304/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XInputStream > xStream
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
bool insertNewContent(const OUString &rContentType, const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rPropertyValues, Content &rNewContent)
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
css::uno::Reference< css::io::XInputStream > openStream()
void setCommandEnvironment(const css::uno::Reference< css::ucb::XCommandEnvironment > &xNewEnv)
Any value
OUString url_
const char * name
@ Exception
Reference< XComponentContext > getProcessComponentContext()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_folder(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
OUString expandUnoRcUrl(OUString const &url)
Definition: dp_misc.cxx:315
const char CR
Definition: dp_misc.h:34
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readProperties(std::vector< std::pair< OUString, OUString > > &out_result, ::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:256
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path(OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readLine(OUString *res, std::u16string_view startingWith, ::ucbhelper::Content &ucb_content, rtl_TextEncoding textenc)
Definition: dp_ucb.cxx:200
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC std::vector< sal_Int8 > readFile(::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:187
const char LF
Definition: dp_misc.h:35
std::vector< sal_uInt8 > bytes
static css::uno::Sequence< OUString > getTitleSequence()
Definition: dp_ucb.h:37
size_t pos