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