1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26
27 #include "dp_misc.hrc"
28 #include "dp_misc.h"
29 #include "dp_ucb.h"
30 #include "rtl/uri.hxx"
31 #include "rtl/ustrbuf.hxx"
32 #include "ucbhelper/content.hxx"
33 #include "xmlscript/xml_helper.hxx"
34 #include "com/sun/star/io/XInputStream.hpp"
35 #include "com/sun/star/ucb/CommandFailedException.hpp"
36 #include "com/sun/star/ucb/ContentInfo.hpp"
37 #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
38
39
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::ucb;
43 using ::rtl::OUString;
44
45 namespace dp_misc
46 {
47
operator ()()48 const OUString StrTitle::operator () ()
49 {
50 return OUSTR("Title");
51 }
52
53 //==============================================================================
create_ucb_content(::ucbhelper::Content * ret_ucbContent,OUString const & url,Reference<XCommandEnvironment> const & xCmdEnv,bool throw_exc)54 bool create_ucb_content(
55 ::ucbhelper::Content * ret_ucbContent, OUString const & url,
56 Reference<XCommandEnvironment> const & xCmdEnv,
57 bool throw_exc )
58 {
59 try {
60 // Existense check...
61 // content ctor/isFolder() will throw exception in case the resource
62 // does not exist.
63
64 // dilemma: no chance to use the given iahandler here, because it would
65 // raise no such file dialogs, else no interaction for
66 // passwords, ...? xxx todo
67 ::ucbhelper::Content ucbContent(
68 url, Reference<XCommandEnvironment>() );
69
70 ucbContent.isFolder();
71
72 if (ret_ucbContent != 0)
73 {
74 ucbContent.setCommandEnvironment( xCmdEnv );
75 *ret_ucbContent = ucbContent;
76 }
77 return true;
78 }
79 catch (RuntimeException &) {
80 throw;
81 }
82 catch (Exception &) {
83 if (throw_exc)
84 throw;
85 }
86 return false;
87 }
88
89 //==============================================================================
create_folder(::ucbhelper::Content * ret_ucb_content,OUString const & url_,Reference<XCommandEnvironment> const & xCmdEnv,bool throw_exc)90 bool create_folder(
91 ::ucbhelper::Content * ret_ucb_content, OUString const & url_,
92 Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc )
93 {
94 ::ucbhelper::Content ucb_content;
95 if (create_ucb_content(
96 &ucb_content, url_, xCmdEnv, false /* no throw */ ))
97 {
98 if (ucb_content.isFolder()) {
99 if (ret_ucb_content != 0)
100 *ret_ucb_content = ucb_content;
101 return true;
102 }
103 }
104
105 OUString url( url_ );
106 // xxx todo: find parent
107 sal_Int32 slash = url.lastIndexOf( '/' );
108 if (slash < 0) {
109 // fallback:
110 url = expandUnoRcUrl( url );
111 slash = url.lastIndexOf( '/' );
112 }
113 if (slash < 0) {
114 // invalid: has to be at least "auth:/..."
115 if (throw_exc)
116 throw ContentCreationException(
117 OUSTR("Cannot create folder (invalid path): ") + url,
118 Reference<XInterface>(), ContentCreationError_UNKNOWN );
119 return false;
120 }
121 ::ucbhelper::Content parentContent;
122 if (! create_folder(
123 &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc ))
124 return false;
125 const Any title( ::rtl::Uri::decode( url.copy( slash + 1 ),
126 rtl_UriDecodeWithCharset,
127 RTL_TEXTENCODING_UTF8 ) );
128 const Sequence<ContentInfo> infos(
129 parentContent.queryCreatableContentsInfo() );
130 for ( sal_Int32 pos = 0; pos < infos.getLength(); ++pos )
131 {
132 // look KIND_FOLDER:
133 ContentInfo const & info = infos[ pos ];
134 if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0)
135 {
136 // make sure the only required bootstrap property is "Title":
137 Sequence<beans::Property> const & rProps = info.Properties;
138 if (rProps.getLength() != 1 ||
139 !rProps[ 0 ].Name.equalsAsciiL(
140 RTL_CONSTASCII_STRINGPARAM("Title") ))
141 continue;
142
143 try {
144 if (parentContent.insertNewContent(
145 info.Type,
146 Sequence<OUString>( &StrTitle::get(), 1 ),
147 Sequence<Any>( &title, 1 ),
148 ucb_content )) {
149 if (ret_ucb_content != 0)
150 *ret_ucb_content = ucb_content;
151 return true;
152 }
153 }
154 catch (RuntimeException &) {
155 throw;
156 }
157 catch (CommandFailedException &) {
158 // Interaction Handler already handled the error
159 // that has occurred...
160 }
161 catch (Exception &) {
162 if (throw_exc)
163 throw;
164 return false;
165 }
166 }
167 }
168 if (throw_exc)
169 throw ContentCreationException(
170 OUSTR("Cannot create folder: ") + url,
171 Reference<XInterface>(), ContentCreationError_UNKNOWN );
172 return false;
173 }
174
175 //==============================================================================
erase_path(OUString const & url,Reference<XCommandEnvironment> const & xCmdEnv,bool throw_exc)176 bool erase_path( OUString const & url,
177 Reference<XCommandEnvironment> const & xCmdEnv,
178 bool throw_exc )
179 {
180 ::ucbhelper::Content ucb_content;
181 if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ ))
182 {
183 try {
184 ucb_content.executeCommand(
185 OUSTR("delete"), Any( true /* delete physically */ ) );
186 }
187 catch (RuntimeException &) {
188 throw;
189 }
190 catch (Exception &) {
191 if (throw_exc)
192 throw;
193 return false;
194 }
195 }
196 return true;
197 }
198
199 //==============================================================================
readFile(::ucbhelper::Content & ucb_content)200 ::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content )
201 {
202 ::rtl::ByteSequence bytes;
203 Reference<io::XOutputStream> xStream(
204 ::xmlscript::createOutputStream( &bytes ) );
205 if (! ucb_content.openStream( xStream ))
206 throw RuntimeException(
207 OUSTR(
208 "::ucbhelper::Content::openStream( XOutputStream ) failed!"),
209 0 );
210 return bytes;
211 }
212
213 //==============================================================================
readLine(OUString * res,OUString const & startingWith,::ucbhelper::Content & ucb_content,rtl_TextEncoding textenc)214 bool readLine( OUString * res, OUString const & startingWith,
215 ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc )
216 {
217 // read whole file:
218 ::rtl::ByteSequence bytes( readFile( ucb_content ) );
219 OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()),
220 bytes.getLength(), textenc );
221 sal_Int32 pos = 0;
222 for (;;)
223 {
224 if (file.match( startingWith, pos ))
225 {
226 ::rtl::OUStringBuffer buf;
227 sal_Int32 start = pos;
228 pos += startingWith.getLength();
229 for (;;)
230 {
231 pos = file.indexOf( LF, pos );
232 if (pos < 0) { // EOF
233 buf.append( file.copy( start ) );
234 }
235 else
236 {
237 if (pos > 0 && file[ pos - 1 ] == CR)
238 {
239 // consume extra CR
240 buf.append( file.copy( start, pos - start - 1 ) );
241 ++pos;
242 }
243 else
244 buf.append( file.copy( start, pos - start ) );
245 ++pos; // consume LF
246 // check next line:
247 if (pos < file.getLength() &&
248 (file[ pos ] == ' ' || file[ pos ] == '\t'))
249 {
250 buf.append( static_cast<sal_Unicode>(' ') );
251 ++pos;
252 start = pos;
253 continue;
254 }
255 }
256 break;
257 }
258 *res = buf.makeStringAndClear();
259 return true;
260 }
261 // next line:
262 sal_Int32 next_lf = file.indexOf( LF, pos );
263 if (next_lf < 0) // EOF
264 break;
265 pos = next_lf + 1;
266 }
267 return false;
268 }
269
readProperties(::std::list<::std::pair<::rtl::OUString,::rtl::OUString>> & out_result,::ucbhelper::Content & ucb_content)270 bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result,
271 ::ucbhelper::Content & ucb_content )
272 {
273 // read whole file:
274 ::rtl::ByteSequence bytes( readFile( ucb_content ) );
275 OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()),
276 bytes.getLength(), RTL_TEXTENCODING_UTF8);
277 sal_Int32 pos = 0;
278
279 for (;;)
280 {
281
282 ::rtl::OUStringBuffer buf;
283 sal_Int32 start = pos;
284
285 bool bEOF = false;
286 pos = file.indexOf( LF, pos );
287 if (pos < 0) { // EOF
288 buf.append( file.copy( start ) );
289 bEOF = true;
290 }
291 else
292 {
293 if (pos > 0 && file[ pos - 1 ] == CR)
294 // consume extra CR
295 buf.append( file.copy( start, pos - start - 1 ) );
296 else
297 buf.append( file.copy( start, pos - start ) );
298 pos++;
299 }
300 OUString aLine = buf.makeStringAndClear();
301
302 sal_Int32 posEqual = aLine.indexOf('=');
303 if (posEqual > 0 && (posEqual + 1) < aLine.getLength())
304 {
305 OUString name = aLine.copy(0, posEqual);
306 OUString value = aLine.copy(posEqual + 1);
307 out_result.push_back(::std::make_pair(name, value));
308 }
309
310 if (bEOF)
311 break;
312 }
313 return false;
314 }
315
316 }
317