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 #include "oox/helper/attributelist.hxx" 29 30 #include <osl/diagnose.h> 31 #include <rtl/ustrbuf.hxx> 32 #include "oox/token/tokenmap.hxx" 33 34 namespace oox { 35 36 // ============================================================================ 37 38 using namespace ::com::sun::star::uno; 39 using namespace ::com::sun::star::util; 40 using namespace ::com::sun::star::xml::sax; 41 42 using ::rtl::OUString; 43 using ::rtl::OUStringBuffer; 44 45 // ============================================================================ 46 47 namespace { 48 49 const sal_Int32 XSTRING_ENCCHAR_LEN = 7; 50 51 bool lclAddHexDigit( sal_Unicode& orcChar, sal_Unicode cDigit, int nBitShift ) 52 { 53 if( ('0' <= cDigit) && (cDigit <= '9') ) { orcChar |= ((cDigit - '0') << nBitShift); return true; } 54 if( ('a' <= cDigit) && (cDigit <= 'f') ) { orcChar |= ((cDigit - 'a' + 10) << nBitShift); return true; } 55 if( ('A' <= cDigit) && (cDigit <= 'F') ) { orcChar |= ((cDigit - 'A' + 10) << nBitShift); return true; } 56 return false; 57 } 58 59 sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd ) 60 { 61 sal_Unicode cChar = 0; 62 if( (pcEnd - rpcStr >= XSTRING_ENCCHAR_LEN) && 63 (rpcStr[ 0 ] == '_') && 64 (rpcStr[ 1 ] == 'x') && 65 (rpcStr[ 6 ] == '_') && 66 lclAddHexDigit( cChar, rpcStr[ 2 ], 12 ) && 67 lclAddHexDigit( cChar, rpcStr[ 3 ], 8 ) && 68 lclAddHexDigit( cChar, rpcStr[ 4 ], 4 ) && 69 lclAddHexDigit( cChar, rpcStr[ 5 ], 0 ) ) 70 { 71 rpcStr += XSTRING_ENCCHAR_LEN; 72 return cChar; 73 } 74 return *rpcStr++; 75 } 76 77 } // namespace 78 79 // ---------------------------------------------------------------------------- 80 81 sal_Int32 AttributeConversion::decodeToken( const OUString& rValue ) 82 { 83 return StaticTokenMap::get().getTokenFromUnicode( rValue ); 84 } 85 86 OUString AttributeConversion::decodeXString( const OUString& rValue ) 87 { 88 // string shorter than one encoded character - no need to decode 89 if( rValue.getLength() < XSTRING_ENCCHAR_LEN ) 90 return rValue; 91 OUStringBuffer aBuffer; 92 const sal_Unicode* pcStr = rValue.getStr(); 93 const sal_Unicode* pcEnd = pcStr + rValue.getLength(); 94 while( pcStr < pcEnd ) 95 aBuffer.append( lclGetXChar( pcStr, pcEnd ) ); 96 return aBuffer.makeStringAndClear(); 97 } 98 99 double AttributeConversion::decodeDouble( const OUString& rValue ) 100 { 101 return rValue.toDouble(); 102 } 103 104 sal_Int32 AttributeConversion::decodeInteger( const OUString& rValue ) 105 { 106 return rValue.toInt32(); 107 } 108 109 sal_uInt32 AttributeConversion::decodeUnsigned( const OUString& rValue ) 110 { 111 return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 ); 112 } 113 114 sal_Int64 AttributeConversion::decodeHyper( const OUString& rValue ) 115 { 116 return rValue.toInt64(); 117 } 118 119 sal_Int32 AttributeConversion::decodeIntegerHex( const OUString& rValue ) 120 { 121 return rValue.toInt32( 16 ); 122 } 123 124 sal_uInt32 AttributeConversion::decodeUnsignedHex( const OUString& rValue ) 125 { 126 return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64( 16 ), 0, SAL_MAX_UINT32 ); 127 } 128 129 sal_Int64 AttributeConversion::decodeHyperHex( const OUString& rValue ) 130 { 131 return rValue.toInt64( 16 ); 132 } 133 134 // ============================================================================ 135 136 AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) : 137 mxAttribs( rxAttribs ) 138 { 139 OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" ); 140 } 141 142 bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const 143 { 144 return mxAttribs->hasAttribute( nAttrToken ); 145 } 146 147 // optional return values ----------------------------------------------------- 148 149 OptValue< sal_Int32 > AttributeList::getToken( sal_Int32 nAttrToken ) const 150 { 151 sal_Int32 nToken = mxAttribs->getOptionalValueToken( nAttrToken, XML_TOKEN_INVALID ); 152 return OptValue< sal_Int32 >( nToken != XML_TOKEN_INVALID, nToken ); 153 } 154 155 OptValue< OUString > AttributeList::getString( sal_Int32 nAttrToken ) const 156 { 157 // check if the attribute exists (empty string may be different to missing attribute) 158 if( mxAttribs->hasAttribute( nAttrToken ) ) 159 return OptValue< OUString >( mxAttribs->getOptionalValue( nAttrToken ) ); 160 return OptValue< OUString >(); 161 } 162 163 OptValue< OUString > AttributeList::getXString( sal_Int32 nAttrToken ) const 164 { 165 // check if the attribute exists (empty string may be different to missing attribute) 166 if( mxAttribs->hasAttribute( nAttrToken ) ) 167 return OptValue< OUString >( AttributeConversion::decodeXString( mxAttribs->getOptionalValue( nAttrToken ) ) ); 168 return OptValue< OUString >(); 169 } 170 171 OptValue< double > AttributeList::getDouble( sal_Int32 nAttrToken ) const 172 { 173 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 174 bool bValid = aValue.getLength() > 0; 175 return OptValue< double >( bValid, bValid ? AttributeConversion::decodeDouble( aValue ) : 0.0 ); 176 } 177 178 OptValue< sal_Int32 > AttributeList::getInteger( sal_Int32 nAttrToken ) const 179 { 180 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 181 bool bValid = aValue.getLength() > 0; 182 return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeInteger( aValue ) : 0 ); 183 } 184 185 OptValue< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nAttrToken ) const 186 { 187 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 188 bool bValid = aValue.getLength() > 0; 189 return OptValue< sal_uInt32 >( bValid, AttributeConversion::decodeUnsigned( aValue ) ); 190 } 191 192 OptValue< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const 193 { 194 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 195 bool bValid = aValue.getLength() > 0; 196 return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyper( aValue ) : 0 ); 197 } 198 199 OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const 200 { 201 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 202 bool bValid = aValue.getLength() > 0; 203 return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeIntegerHex( aValue ) : 0 ); 204 } 205 206 OptValue< sal_uInt32 > AttributeList::getUnsignedHex( sal_Int32 nAttrToken ) const 207 { 208 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 209 bool bValid = aValue.getLength() > 0; 210 return OptValue< sal_uInt32 >( bValid, bValid ? AttributeConversion::decodeUnsignedHex( aValue ) : 0 ); 211 } 212 213 OptValue< sal_Int64 > AttributeList::getHyperHex( sal_Int32 nAttrToken ) const 214 { 215 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 216 bool bValid = aValue.getLength() > 0; 217 return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyperHex( aValue ) : 0 ); 218 } 219 220 OptValue< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const 221 { 222 // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0" 223 switch( getToken( nAttrToken, XML_TOKEN_INVALID ) ) 224 { 225 case XML_t: return OptValue< bool >( true ); // used in VML 226 case XML_true: return OptValue< bool >( true ); 227 case XML_on: return OptValue< bool >( true ); 228 case XML_f: return OptValue< bool >( false ); // used in VML 229 case XML_false: return OptValue< bool >( false ); 230 case XML_off: return OptValue< bool >( false ); 231 } 232 OptValue< sal_Int32 > onValue = getInteger( nAttrToken ); 233 return OptValue< bool >( onValue.has(), onValue.get() != 0 ); 234 } 235 236 OptValue< DateTime > AttributeList::getDateTime( sal_Int32 nAttrToken ) const 237 { 238 OUString aValue = mxAttribs->getOptionalValue( nAttrToken ); 239 DateTime aDateTime; 240 bool bValid = (aValue.getLength() == 19) && (aValue[ 4 ] == '-') && (aValue[ 7 ] == '-') && 241 (aValue[ 10 ] == 'T') && (aValue[ 13 ] == ':') && (aValue[ 16 ] == ':'); 242 if( bValid ) 243 { 244 aDateTime.Year = static_cast< sal_uInt16 >( aValue.copy( 0, 4 ).toInt32() ); 245 aDateTime.Month = static_cast< sal_uInt16 >( aValue.copy( 5, 2 ).toInt32() ); 246 aDateTime.Day = static_cast< sal_uInt16 >( aValue.copy( 8, 2 ).toInt32() ); 247 aDateTime.Hours = static_cast< sal_uInt16 >( aValue.copy( 11, 2 ).toInt32() ); 248 aDateTime.Minutes = static_cast< sal_uInt16 >( aValue.copy( 14, 2 ).toInt32() ); 249 aDateTime.Seconds = static_cast< sal_uInt16 >( aValue.copy( 17, 2 ).toInt32() ); 250 } 251 return OptValue< DateTime >( bValid, aDateTime ); 252 } 253 254 // defaulted return values ---------------------------------------------------- 255 256 sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) const 257 { 258 return mxAttribs->getOptionalValueToken( nAttrToken, nDefault ); 259 } 260 261 OUString AttributeList::getString( sal_Int32 nAttrToken, const OUString& rDefault ) const 262 { 263 try 264 { 265 return mxAttribs->getValue( nAttrToken ); 266 } 267 catch( Exception& ) 268 { 269 } 270 return rDefault; 271 } 272 273 OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefault ) const 274 { 275 return getXString( nAttrToken ).get( rDefault ); 276 } 277 278 double AttributeList::getDouble( sal_Int32 nAttrToken, double fDefault ) const 279 { 280 return getDouble( nAttrToken ).get( fDefault ); 281 } 282 283 sal_Int32 AttributeList::getInteger( sal_Int32 nAttrToken, sal_Int32 nDefault ) const 284 { 285 return getInteger( nAttrToken ).get( nDefault ); 286 } 287 288 sal_uInt32 AttributeList::getUnsigned( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const 289 { 290 return getUnsigned( nAttrToken ).get( nDefault ); 291 } 292 293 sal_Int64 AttributeList::getHyper( sal_Int32 nAttrToken, sal_Int64 nDefault ) const 294 { 295 return getHyper( nAttrToken ).get( nDefault ); 296 } 297 298 sal_Int32 AttributeList::getIntegerHex( sal_Int32 nAttrToken, sal_Int32 nDefault ) const 299 { 300 return getIntegerHex( nAttrToken ).get( nDefault ); 301 } 302 303 sal_uInt32 AttributeList::getUnsignedHex( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const 304 { 305 return getUnsignedHex( nAttrToken ).get( nDefault ); 306 } 307 308 sal_Int64 AttributeList::getHyperHex( sal_Int32 nAttrToken, sal_Int64 nDefault ) const 309 { 310 return getHyperHex( nAttrToken ).get( nDefault ); 311 } 312 313 bool AttributeList::getBool( sal_Int32 nAttrToken, bool bDefault ) const 314 { 315 return getBool( nAttrToken ).get( bDefault ); 316 } 317 318 DateTime AttributeList::getDateTime( sal_Int32 nAttrToken, const DateTime& rDefault ) const 319 { 320 return getDateTime( nAttrToken ).get( rDefault ); 321 } 322 323 // ============================================================================ 324 325 } // namespace oox 326