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