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/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>
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 ( sal_Int32 pos = 0; pos < infos.getLength(); ++pos )
123  {
124  // look KIND_FOLDER:
125  ContentInfo const & info = infos[ pos ];
126  if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
127  {
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;
132 
133  try {
134  if (parentContent.insertNewContent(
135  info.Type,
137  Sequence<Any>( &title, 1 ),
138  ucb_content )) {
139  if (ret_ucb_content != nullptr)
140  *ret_ucb_content = ucb_content;
141  return true;
142  }
143  }
144  catch (const RuntimeException &) {
145  throw;
146  }
147  catch (const CommandFailedException &) {
148  // Interaction Handler already handled the error
149  // that has occurred...
150  }
151  catch (const Exception &) {
152  if (throw_exc)
153  throw;
154  return false;
155  }
156  }
157  }
158  if (throw_exc)
159  throw ContentCreationException(
160  "Cannot create folder: '" + url + "'",
161  Reference<XInterface>(), ContentCreationError_UNKNOWN );
162  return false;
163 }
164 
165 
166 bool erase_path( OUString const & url,
167  Reference<XCommandEnvironment> const & xCmdEnv,
168  bool throw_exc )
169 {
170  ::ucbhelper::Content ucb_content;
171  if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
172  {
173  try {
174  ucb_content.executeCommand(
175  "delete", Any( true /* delete physically */ ) );
176  }
177  catch (const RuntimeException &) {
178  throw;
179  }
180  catch (const Exception &) {
181  if (throw_exc)
182  throw;
183  return false;
184  }
185  }
186  return true;
187 }
188 
189 
190 std::vector<sal_Int8> readFile( ::ucbhelper::Content & ucb_content )
191 {
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;
200 }
201 
202 
203 bool readLine( OUString * res, OUString const & startingWith,
204  ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
205 {
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 (;;)
212  {
213  if (file.match( startingWith, pos ))
214  {
215  OUStringBuffer buf;
216  sal_Int32 start = pos;
217  pos += startingWith.getLength();
218  for (;;)
219  {
220  pos = file.indexOf( LF, pos );
221  if (pos < 0) { // EOF
222  buf.append( std::u16string_view(file).substr(start) );
223  }
224  else
225  {
226  if (pos > 0 && file[ pos - 1 ] == CR)
227  {
228  // consume extra CR
229  buf.append( std::u16string_view(file).substr(start, pos - start - 1) );
230  ++pos;
231  }
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'))
238  {
239  buf.append( ' ' );
240  ++pos;
241  start = pos;
242  continue;
243  }
244  }
245  break;
246  }
247  *res = buf.makeStringAndClear();
248  return true;
249  }
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;
255  }
256  return false;
257 }
258 
259 bool readProperties( std::vector< std::pair< OUString, OUString> > & out_result,
260  ::ucbhelper::Content & ucb_content )
261 {
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;
267 
268  for (;;)
269  {
270 
271  OUStringBuffer buf;
272  sal_Int32 start = pos;
273 
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;
279  }
280  else
281  {
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++;
288  }
289  OUString aLine = buf.makeStringAndClear();
290 
291  sal_Int32 posEqual = aLine.indexOf('=');
292  if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
293  {
294  OUString name = aLine.copy(0, posEqual);
295  OUString value = aLine.copy(posEqual + 1);
296  out_result.emplace_back(name, value);
297  }
298 
299  if (bEOF)
300  break;
301  }
302  return false;
303 }
304 
305 }
306 
307 /* 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:259
IJScriptValueObject VARIANT value
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
const sal_Char LF
Definition: dp_misc.h:38
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC std::vector< sal_Int8 > readFile(::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:190
Reference< XInputStream > xStream
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readLine(OUString *res, OUString const &startingWith,::ucbhelper::Content &ucb_content, rtl_TextEncoding textenc)
Definition: dp_ucb.cxx:203
void setCommandEnvironment(const css::uno::Reference< css::ucb::XCommandEnvironment > &xNewEnv)
const sal_Char CR
Definition: dp_misc.h:37
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:330
css::uno::Reference< css::io::XInputStream > openStream()
static css::uno::Sequence< OUString > getTitleSequence()
Definition: dp_ucb.h:40
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)
Reference< io::XOutputStream > createOutputStream(std::vector< sal_Int8 > *pOutData)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
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)