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