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 occured...
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