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
lclAddHexDigit(sal_Unicode & orcChar,sal_Unicode cDigit,int nBitShift)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
lclGetXChar(const sal_Unicode * & rpcStr,const sal_Unicode * pcEnd)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
decodeToken(const OUString & rValue)78 sal_Int32 AttributeConversion::decodeToken( const OUString& rValue )
79 {
80 return StaticTokenMap::get().getTokenFromUnicode( rValue );
81 }
82
decodeXString(const OUString & rValue)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
decodeDouble(const OUString & rValue)96 double AttributeConversion::decodeDouble( const OUString& rValue )
97 {
98 return rValue.toDouble();
99 }
100
decodeInteger(const OUString & rValue)101 sal_Int32 AttributeConversion::decodeInteger( const OUString& rValue )
102 {
103 return rValue.toInt32();
104 }
105
decodeUnsigned(const OUString & rValue)106 sal_uInt32 AttributeConversion::decodeUnsigned( const OUString& rValue )
107 {
108 return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 );
109 }
110
decodeHyper(const OUString & rValue)111 sal_Int64 AttributeConversion::decodeHyper( const OUString& rValue )
112 {
113 return rValue.toInt64();
114 }
115
decodeIntegerHex(const OUString & rValue)116 sal_Int32 AttributeConversion::decodeIntegerHex( const OUString& rValue )
117 {
118 return rValue.toInt32( 16 );
119 }
120
decodeUnsignedHex(const OUString & rValue)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
decodeHyperHex(const OUString & rValue)126 sal_Int64 AttributeConversion::decodeHyperHex( const OUString& rValue )
127 {
128 return rValue.toInt64( 16 );
129 }
130
131 // ============================================================================
132
AttributeList(const Reference<XFastAttributeList> & rxAttribs)133 AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) :
134 mxAttribs( rxAttribs )
135 {
136 OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" );
137 }
138
hasAttribute(sal_Int32 nAttrToken) const139 bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const
140 {
141 return mxAttribs->hasAttribute( nAttrToken );
142 }
143
144 // optional return values -----------------------------------------------------
145
getToken(sal_Int32 nAttrToken) const146 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
getString(sal_Int32 nAttrToken) const152 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
getXString(sal_Int32 nAttrToken) const160 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
getDouble(sal_Int32 nAttrToken) const168 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
getInteger(sal_Int32 nAttrToken) const175 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
getUnsigned(sal_Int32 nAttrToken) const182 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
getHyper(sal_Int32 nAttrToken) const189 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
getIntegerHex(sal_Int32 nAttrToken) const196 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
getUnsignedHex(sal_Int32 nAttrToken) const203 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
getHyperHex(sal_Int32 nAttrToken) const210 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
getBool(sal_Int32 nAttrToken) const217 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
getDateTime(sal_Int32 nAttrToken) const233 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
getToken(sal_Int32 nAttrToken,sal_Int32 nDefault) const243 sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
244 {
245 return mxAttribs->getOptionalValueToken( nAttrToken, nDefault );
246 }
247
getString(sal_Int32 nAttrToken,const OUString & rDefault) const248 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
getXString(sal_Int32 nAttrToken,const OUString & rDefault) const260 OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefault ) const
261 {
262 return getXString( nAttrToken ).get( rDefault );
263 }
264
getDouble(sal_Int32 nAttrToken,double fDefault) const265 double AttributeList::getDouble( sal_Int32 nAttrToken, double fDefault ) const
266 {
267 return getDouble( nAttrToken ).get( fDefault );
268 }
269
getInteger(sal_Int32 nAttrToken,sal_Int32 nDefault) const270 sal_Int32 AttributeList::getInteger( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
271 {
272 return getInteger( nAttrToken ).get( nDefault );
273 }
274
getUnsigned(sal_Int32 nAttrToken,sal_uInt32 nDefault) const275 sal_uInt32 AttributeList::getUnsigned( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
276 {
277 return getUnsigned( nAttrToken ).get( nDefault );
278 }
279
getHyper(sal_Int32 nAttrToken,sal_Int64 nDefault) const280 sal_Int64 AttributeList::getHyper( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
281 {
282 return getHyper( nAttrToken ).get( nDefault );
283 }
284
getIntegerHex(sal_Int32 nAttrToken,sal_Int32 nDefault) const285 sal_Int32 AttributeList::getIntegerHex( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
286 {
287 return getIntegerHex( nAttrToken ).get( nDefault );
288 }
289
getUnsignedHex(sal_Int32 nAttrToken,sal_uInt32 nDefault) const290 sal_uInt32 AttributeList::getUnsignedHex( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
291 {
292 return getUnsignedHex( nAttrToken ).get( nDefault );
293 }
294
getHyperHex(sal_Int32 nAttrToken,sal_Int64 nDefault) const295 sal_Int64 AttributeList::getHyperHex( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
296 {
297 return getHyperHex( nAttrToken ).get( nDefault );
298 }
299
getBool(sal_Int32 nAttrToken,bool bDefault) const300 bool AttributeList::getBool( sal_Int32 nAttrToken, bool bDefault ) const
301 {
302 return getBool( nAttrToken ).get( bDefault );
303 }
304
getDateTime(sal_Int32 nAttrToken,const DateTime & rDefault) const305 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