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 <string_view>
23 
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/XOutputStream.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>
36 
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::ucb;
40 
41 namespace dp_misc
42 {
43 
44 
46  ::ucbhelper::Content * ret_ucbContent, OUString const & url,
47  Reference<XCommandEnvironment> const & xCmdEnv,
48  bool throw_exc )
49 {
50  try {
51  // Existence check...
52  // content ctor/isFolder() will throw exception in case the resource
53  // does not exist.
54 
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(
61 
62  ucbContent.isFolder();
63 
64  if (ret_ucbContent != nullptr)
65  {
66  ucbContent.setCommandEnvironment( xCmdEnv );
67  *ret_ucbContent = ucbContent;
68  }
69  return true;
70  }
71  catch (const RuntimeException &) {
72  throw;
73  }
74  catch (const Exception &) {
75  if (throw_exc)
76  throw;
77  }
78  return false;
79 }
80 
81 
83  ::ucbhelper::Content * ret_ucb_content, OUString const & url_,
84  Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc )
85 {
86  ::ucbhelper::Content ucb_content;
88  &ucb_content, url_, xCmdEnv, false /* no throw */ ))
89  {
90  if (ucb_content.isFolder()) {
91  if (ret_ucb_content != nullptr)
92  *ret_ucb_content = ucb_content;
93  return true;
94  }
95  }
96 
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( '/' );
104  }
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;
112  }
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 ( ContentInfo const & info : infos )
123  {
124  // look KIND_FOLDER:
125  if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
126  {
127  // make sure the only required bootstrap property is "Title":
128  Sequence<beans::Property> const & rProps = info.Properties;
129  if ( rProps.getLength() != 1 || rProps[ 0 ].Name != "Title" )
130  continue;
131 
132  try {
133  if (parentContent.insertNewContent(
134  info.Type,
136  Sequence<Any>( &title, 1 ),
137  ucb_content )) {
138  if (ret_ucb_content != nullptr)
139  *ret_ucb_content = ucb_content;
140  return true;
141  }
142  }
143  catch (const RuntimeException &) {
144  throw;
145  }
146  catch (const CommandFailedException &) {
147  // Interaction Handler already handled the error
148  // that has occurred...
149  }
150  catch (const Exception &) {
151  if (throw_exc)
152  throw;
153  return false;
154  }
155  }
156  }
157  if (throw_exc)
158  throw ContentCreationException(
159  "Cannot create folder: '" + url + "'",
160  Reference<XInterface>(), ContentCreationError_UNKNOWN );
161  return false;
162 }
163 
164 
165 bool erase_path( OUString const & url,
166  Reference<XCommandEnvironment> const & xCmdEnv,
167  bool throw_exc )
168 {
169  ::ucbhelper::Content ucb_content;
170  if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
171  {
172  try {
173  ucb_content.executeCommand(
174  "delete", Any( true /* delete physically */ ) );
175  }
176  catch (const RuntimeException &) {
177  throw;
178  }
179  catch (const Exception &) {
180  if (throw_exc)
181  throw;
182  return false;
183  }
184  }
185  return true;
186 }
187 
188 
189 std::vector<sal_Int8> readFile( ::ucbhelper::Content & ucb_content )
190 {
191  std::vector<sal_Int8> bytes;
192  Reference<io::XOutputStream> xStream(
193  ::xmlscript::createOutputStream( &bytes ) );
194  if (! ucb_content.openStream( xStream ))
195  throw RuntimeException(
196  "::ucbhelper::Content::openStream( XOutputStream ) failed!",
197  nullptr );
198  return bytes;
199 }
200 
201 
202 bool readLine( OUString * res, OUString const & startingWith,
203  ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
204 {
205  // read whole file:
206  std::vector<sal_Int8> bytes( readFile( ucb_content ) );
207  OUString file( reinterpret_cast<char const *>(bytes.data()),
208  bytes.size(), textenc );
209  sal_Int32 pos = 0;
210  for (;;)
211  {
212  if (file.match( startingWith, pos ))
213  {
214  OUStringBuffer buf;
215  sal_Int32 start = pos;
216  pos += startingWith.getLength();
217  for (;;)
218  {
219  pos = file.indexOf( LF, pos );
220  if (pos < 0) { // EOF
221  buf.append( std::u16string_view(file).substr(start) );
222  }
223  else
224  {
225  if (pos > 0 && file[ pos - 1 ] == CR)
226  {
227  // consume extra CR
228  buf.append( std::u16string_view(file).substr(start, pos - start - 1) );
229  ++pos;
230  }
231  else
232  buf.append( std::u16string_view(file).substr(start, pos - start) );
233  ++pos; // consume LF
234  // check next line:
235  if (pos < file.getLength() &&
236  (file[ pos ] == ' ' || file[ pos ] == '\t'))
237  {
238  buf.append( ' ' );
239  ++pos;
240  start = pos;
241  continue;
242  }
243  }
244  break;
245  }
246  *res = buf.makeStringAndClear();
247  return true;
248  }
249  // next line:
250  sal_Int32 next_lf = file.indexOf( LF, pos );
251  if (next_lf < 0) // EOF
252  break;
253  pos = next_lf + 1;
254  }
255  return false;
256 }
257 
258 bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
259  ::ucbhelper::Content & ucb_content )
260 {
261  // read whole file:
262  std::vector<sal_Int8> bytes( readFile( ucb_content ) );
263  OUString file( reinterpret_cast<char const *>(bytes.data()),
264  bytes.size(), RTL_TEXTENCODING_UTF8);
265  sal_Int32 pos = 0;
266 
267  for (;;)
268  {
269 
270  OUStringBuffer buf;
271  sal_Int32 start = pos;
272 
273  bool bEOF = false;
274  pos = file.indexOf( LF, pos );
275  if (pos < 0) { // EOF
276  buf.append( std::u16string_view(file).substr(start) );
277  bEOF = true;
278  }
279  else
280  {
281  if (pos > 0 && file[ pos - 1 ] == CR)
282  // consume extra CR
283  buf.append( std::u16string_view(file).substr(start, pos - start - 1) );
284  else
285  buf.append( std::u16string_view(file).substr(start, pos - start) );
286  pos++;
287  }
288  OUString aLine = buf.makeStringAndClear();
289 
290  sal_Int32 posEqual = aLine.indexOf('=');
291  if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
292  {
293  OUString name = aLine.copy(0, posEqual);
294  OUString value = aLine.copy(posEqual + 1);
295  out_result.emplace_back(name, value);
296  }
297 
298  if (bEOF)
299  break;
300  }
301  return false;
302 }
303 
304 }
305 
306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readProperties(std::vector< std::pair< OUString, OUString > > &out_result,::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:258
bool insertNewContent(const OUString &rContentType, const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rPropertyValues, Content &rNewContent)
std::vector< sal_uInt8 > bytes
type_info_ info
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC std::vector< sal_Int8 > readFile(::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:189
Reference< XInputStream > xStream
size_t pos
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readLine(OUString *res, OUString const &startingWith,::ucbhelper::Content &ucb_content, rtl_TextEncoding textenc)
Definition: dp_ucb.cxx:202
void setCommandEnvironment(const css::uno::Reference< css::ucb::XCommandEnvironment > &xNewEnv)
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)
OUString expandUnoRcUrl(OUString const &url)
Definition: dp_misc.cxx:315
css::uno::Reference< css::io::XInputStream > openStream()
static css::uno::Sequence< OUString > getTitleSequence()
Definition: dp_ucb.h:38
const char LF
Definition: dp_misc.h:33
Reference< XComponentContext > getProcessComponentContext()
const char * name
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path(OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
Any value
Reference< io::XOutputStream > createOutputStream(std::vector< sal_Int8 > *pOutData)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
const char CR
Definition: dp_misc.h:32
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)