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 48 const OUString StrTitle::operator () () 49 { 50 return OUSTR("Title"); 51 } 52 53 //============================================================================== 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 //============================================================================== 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 //============================================================================== 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 //============================================================================== 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 //============================================================================== 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 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