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>
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>
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::ucb;
38 
39 namespace 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(
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 
163 bool 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 
187 std::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 
200 bool readLine( OUString * res, OUString const & 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.getLength();
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 
256 bool 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: */
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool readProperties(std::vector< std::pair< OUString, OUString > > &out_result,::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:256
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
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC std::vector< sal_Int8 > readFile(::ucbhelper::Content &ucb_content)
Definition: dp_ucb.cxx:187
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:200
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:314
css::uno::Reference< css::io::XInputStream > openStream()
static css::uno::Sequence< OUString > getTitleSequence()
Definition: dp_ucb.h:37
const char LF
Definition: dp_misc.h:35
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:34
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)