Line data Source code
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 :
21 : #include "deployment.hrc"
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/XInputStream.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 "comphelper/processfactory.hxx"
33 :
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::uno;
36 : using namespace ::com::sun::star::ucb;
37 :
38 : namespace dp_misc
39 : {
40 :
41 :
42 0 : bool create_ucb_content(
43 : ::ucbhelper::Content * ret_ucbContent, OUString const & url,
44 : Reference<XCommandEnvironment> const & xCmdEnv,
45 : bool throw_exc )
46 : {
47 : try {
48 : // Existense check...
49 : // content ctor/isFolder() will throw exception in case the resource
50 : // does not exist.
51 :
52 : // dilemma: no chance to use the given iahandler here, because it would
53 : // raise no such file dialogs, else no interaction for
54 : // passwords, ...? xxx todo
55 : ::ucbhelper::Content ucbContent(
56 : url, Reference<XCommandEnvironment>(),
57 0 : comphelper::getProcessComponentContext() );
58 :
59 0 : ucbContent.isFolder();
60 :
61 0 : if (ret_ucbContent != 0)
62 : {
63 0 : ucbContent.setCommandEnvironment( xCmdEnv );
64 0 : *ret_ucbContent = ucbContent;
65 : }
66 0 : return true;
67 : }
68 0 : catch (const RuntimeException &) {
69 0 : throw;
70 : }
71 0 : catch (const Exception &) {
72 0 : if (throw_exc)
73 0 : throw;
74 : }
75 0 : return false;
76 : }
77 :
78 :
79 0 : bool create_folder(
80 : ::ucbhelper::Content * ret_ucb_content, OUString const & url_,
81 : Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc )
82 : {
83 0 : ::ucbhelper::Content ucb_content;
84 0 : if (create_ucb_content(
85 : &ucb_content, url_, xCmdEnv, false /* no throw */ ))
86 : {
87 0 : if (ucb_content.isFolder()) {
88 0 : if (ret_ucb_content != 0)
89 0 : *ret_ucb_content = ucb_content;
90 0 : return true;
91 : }
92 : }
93 :
94 0 : OUString url( url_ );
95 : // xxx todo: find parent
96 0 : sal_Int32 slash = url.lastIndexOf( '/' );
97 0 : if (slash < 0) {
98 : // fallback:
99 0 : url = expandUnoRcUrl( url );
100 0 : slash = url.lastIndexOf( '/' );
101 : }
102 0 : if (slash < 0) {
103 : // invalid: has to be at least "auth:/..."
104 0 : if (throw_exc)
105 : throw ContentCreationException(
106 0 : "Cannot create folder (invalid path): " + url,
107 0 : Reference<XInterface>(), ContentCreationError_UNKNOWN );
108 0 : return false;
109 : }
110 0 : ::ucbhelper::Content parentContent;
111 0 : if (! create_folder(
112 0 : &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc ))
113 0 : return false;
114 : const Any title( ::rtl::Uri::decode( url.copy( slash + 1 ),
115 : rtl_UriDecodeWithCharset,
116 0 : RTL_TEXTENCODING_UTF8 ) );
117 : const Sequence<ContentInfo> infos(
118 0 : parentContent.queryCreatableContentsInfo() );
119 0 : for ( sal_Int32 pos = 0; pos < infos.getLength(); ++pos )
120 : {
121 : // look KIND_FOLDER:
122 0 : ContentInfo const & info = infos[ pos ];
123 0 : if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
124 : {
125 : // make sure the only required bootstrap property is "Title":
126 0 : Sequence<beans::Property> const & rProps = info.Properties;
127 0 : if ( rProps.getLength() != 1 || rProps[ 0 ].Name != "Title" )
128 0 : continue;
129 :
130 : try {
131 0 : if (parentContent.insertNewContent(
132 : info.Type,
133 : StrTitle::getTitleSequence(),
134 : Sequence<Any>( &title, 1 ),
135 0 : ucb_content )) {
136 0 : if (ret_ucb_content != 0)
137 0 : *ret_ucb_content = ucb_content;
138 0 : return true;
139 : }
140 : }
141 0 : catch (const RuntimeException &) {
142 0 : throw;
143 : }
144 0 : catch (const CommandFailedException &) {
145 : // Interaction Handler already handled the error
146 : // that has occurred...
147 : }
148 0 : catch (const Exception &) {
149 0 : if (throw_exc)
150 0 : throw;
151 0 : return false;
152 : }
153 : }
154 : }
155 0 : if (throw_exc)
156 : throw ContentCreationException(
157 0 : "Cannot create folder: " + url,
158 0 : Reference<XInterface>(), ContentCreationError_UNKNOWN );
159 0 : return false;
160 : }
161 :
162 :
163 0 : bool erase_path( OUString const & url,
164 : Reference<XCommandEnvironment> const & xCmdEnv,
165 : bool throw_exc )
166 : {
167 0 : ::ucbhelper::Content ucb_content;
168 0 : if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
169 : {
170 : try {
171 : ucb_content.executeCommand(
172 0 : "delete", Any( true /* delete physically */ ) );
173 : }
174 0 : catch (const RuntimeException &) {
175 0 : throw;
176 : }
177 0 : catch (const Exception &) {
178 0 : if (throw_exc)
179 0 : throw;
180 0 : return false;
181 : }
182 : }
183 0 : return true;
184 : }
185 :
186 :
187 0 : ::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content )
188 : {
189 0 : ::rtl::ByteSequence bytes;
190 : Reference<io::XOutputStream> xStream(
191 0 : ::xmlscript::createOutputStream( &bytes ) );
192 0 : if (! ucb_content.openStream( xStream ))
193 : throw RuntimeException(
194 : "::ucbhelper::Content::openStream( XOutputStream ) failed!",
195 0 : 0 );
196 0 : return bytes;
197 : }
198 :
199 :
200 0 : bool readLine( OUString * res, OUString const & startingWith,
201 : ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
202 : {
203 : // read whole file:
204 0 : ::rtl::ByteSequence bytes( readFile( ucb_content ) );
205 0 : OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()),
206 0 : bytes.getLength(), textenc );
207 0 : sal_Int32 pos = 0;
208 : for (;;)
209 : {
210 0 : if (file.match( startingWith, pos ))
211 : {
212 0 : OUStringBuffer buf;
213 0 : sal_Int32 start = pos;
214 0 : pos += startingWith.getLength();
215 : for (;;)
216 : {
217 0 : pos = file.indexOf( LF, pos );
218 0 : if (pos < 0) { // EOF
219 0 : buf.append( file.copy( start ) );
220 : }
221 : else
222 : {
223 0 : if (pos > 0 && file[ pos - 1 ] == CR)
224 : {
225 : // consume extra CR
226 0 : buf.append( file.copy( start, pos - start - 1 ) );
227 0 : ++pos;
228 : }
229 : else
230 0 : buf.append( file.copy( start, pos - start ) );
231 0 : ++pos; // consume LF
232 : // check next line:
233 0 : if (pos < file.getLength() &&
234 0 : (file[ pos ] == ' ' || file[ pos ] == '\t'))
235 : {
236 0 : buf.append( ' ' );
237 0 : ++pos;
238 0 : start = pos;
239 0 : continue;
240 : }
241 : }
242 0 : break;
243 : }
244 0 : *res = buf.makeStringAndClear();
245 0 : return true;
246 : }
247 : // next line:
248 0 : sal_Int32 next_lf = file.indexOf( LF, pos );
249 0 : if (next_lf < 0) // EOF
250 0 : break;
251 0 : pos = next_lf + 1;
252 0 : }
253 0 : return false;
254 : }
255 :
256 0 : bool readProperties( ::std::list< ::std::pair< OUString, OUString> > & out_result,
257 : ::ucbhelper::Content & ucb_content )
258 : {
259 : // read whole file:
260 0 : ::rtl::ByteSequence bytes( readFile( ucb_content ) );
261 0 : OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()),
262 0 : bytes.getLength(), RTL_TEXTENCODING_UTF8);
263 0 : sal_Int32 pos = 0;
264 :
265 : for (;;)
266 : {
267 :
268 0 : OUStringBuffer buf;
269 0 : sal_Int32 start = pos;
270 :
271 0 : bool bEOF = false;
272 0 : pos = file.indexOf( LF, pos );
273 0 : if (pos < 0) { // EOF
274 0 : buf.append( file.copy( start ) );
275 0 : bEOF = true;
276 : }
277 : else
278 : {
279 0 : if (pos > 0 && file[ pos - 1 ] == CR)
280 : // consume extra CR
281 0 : buf.append( file.copy( start, pos - start - 1 ) );
282 : else
283 0 : buf.append( file.copy( start, pos - start ) );
284 0 : pos++;
285 : }
286 0 : OUString aLine = buf.makeStringAndClear();
287 :
288 0 : sal_Int32 posEqual = aLine.indexOf('=');
289 0 : if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
290 : {
291 0 : OUString name = aLine.copy(0, posEqual);
292 0 : OUString value = aLine.copy(posEqual + 1);
293 0 : out_result.push_back(::std::make_pair(name, value));
294 : }
295 :
296 0 : if (bEOF)
297 0 : break;
298 0 : }
299 0 : return false;
300 : }
301 :
302 : }
303 :
304 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|