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_xmlsecurity.hxx"
30 
31 #include "resourcemanager.hxx"
32 
33 #include <vcl/svapp.hxx>
34 #include <vcl/fixed.hxx>
35 #include <svtools/stdctrl.hxx>
36 #include <svl/solar.hrc>
37 #include <unotools/syslocale.hxx>
38 #include <rtl/ustring.h>
39 #include <rtl/ustrbuf.h>
40 #include <vector>
41 
42 using ::rtl::OUString;
43 using namespace std;
44 
45 namespace XmlSec
46 {
47 	static ResMgr*			pResMgr = 0;
48     static SvtSysLocale*    pSysLocale = 0;
49 
50 	ResMgr* GetResMgr( void )
51 	{
52 		if( !pResMgr )
53 		{
54 			ByteString	aName( "xmlsec" );
55 //    		pResMgr = ResMgr::CreateResMgr( aName.GetBuffer(), Application::GetSettings().GetUILanguage() );
56 //			LanguageType	aLang( LANGUAGE_ENGLISH_US );
57 //			pResMgr = ResMgr::CreateResMgr( aName.GetBuffer(), aLang );
58 // MT: Change to Locale
59 			pResMgr = ResMgr::CreateResMgr( aName.GetBuffer() );
60 		}
61 
62 	return pResMgr;
63 	}
64 
65 	const LocaleDataWrapper&    GetLocaleData( void )
66 	{
67         if (!pSysLocale)
68             pSysLocale = new SvtSysLocale;
69         return pSysLocale->GetLocaleData();
70 	}
71 
72 	DateTime GetDateTime( const ::com::sun::star::util::DateTime& _rDT )
73 	{
74 		return DateTime(
75 			Date( _rDT.Day, _rDT.Month, _rDT.Year ),
76 			Time( _rDT.Hours, _rDT.Minutes, _rDT.Seconds, _rDT.HundredthSeconds ) );
77 	}
78 
79 	String GetDateTimeString( const ::com::sun::star::util::DateTime& _rDT )
80 	{
81         // --> PB 2004-10-12 #i20172# String with date and time information
82         DateTime aDT( GetDateTime( _rDT ) );
83         const LocaleDataWrapper& rLoDa = GetLocaleData();
84         String sRet( rLoDa.getDate( aDT ) );
85         sRet += ' ';
86         sRet += rLoDa.getTime( aDT );
87         return sRet;
88 	}
89 
90 	String GetDateTimeString( const rtl::OUString& _rDate, const rtl::OUString& _rTime )
91 	{
92 		String sDay( _rDate, 6, 2 );
93 		String sMonth( _rDate, 4, 2 );
94 		String sYear( _rDate, 0, 4 );
95 
96 		String sHour( _rTime, 0, 2 );
97 		String sMin( _rTime, 4, 2 );
98 		String sSec( _rTime, 6, 2 );
99 
100 
101 		Date aDate( (sal_uInt16)sDay.ToInt32(), (sal_uInt16) sMonth.ToInt32(), (sal_uInt16)sYear.ToInt32() );
102 		Time aTime( sHour.ToInt32(), sMin.ToInt32(), sSec.ToInt32(), 0 );
103         const LocaleDataWrapper& rLoDa = GetLocaleData();
104 		String aStr( rLoDa.getDate( aDate ) );
105 		aStr.AppendAscii( " " );
106 		aStr += rLoDa.getTime( aTime );
107 		return aStr;
108 	}
109 
110 	String GetDateString( const ::com::sun::star::util::DateTime& _rDT )
111 	{
112 		return GetLocaleData().getDate( GetDateTime( _rDT ) );
113 	}
114 
115     /*
116         Creates two strings based on the distinguished name which are displayed in the
117         certificate details view. The first string contains only the values of the attribute
118         and valudes pairs, which are separated by commas. All escape characters ('"') are
119         removed.
120         The second string is for the details view at the bottom. It shows the attribute/value
121         pairs on different lines. All escape characters ('"') are removed.
122     */
123     pair< OUString, OUString> GetDNForCertDetailsView( const OUString & rRawString)
124     {
125         vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(rRawString);
126         ::rtl::OUStringBuffer s1, s2;
127         OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = "));
128         typedef vector< pair < OUString, OUString > >::const_iterator CIT;
129         for (CIT i = vecAttrValueOfDN.begin(); i < vecAttrValueOfDN.end(); i ++)
130         {
131             if (i != vecAttrValueOfDN.begin())
132             {
133                 s1.append(static_cast<sal_Unicode>(','));
134                 s2.append(static_cast<sal_Unicode>('\n'));
135             }
136             s1.append(i->second);
137             s2.append(i->first);
138             s2.append(sEqual);
139             s2.append(i->second);
140         }
141         return make_pair(s1.makeStringAndClear(), s2.makeStringAndClear());
142     }
143 
144 /*
145     Whenever the attribute value contains special characters, such as '"' or ',' (without '')
146     then the value will be enclosed in double quotes by the respective Windows or NSS function
147     which we use to retrieve, for example, the subject name. If double quotes appear in the value then
148     they are escaped with a double quote. This function removes the escape characters.
149 */
150 #ifdef WNT
151 vector< pair< OUString, OUString> > parseDN(const OUString& rRawString)
152 {
153         vector< pair<OUString, OUString> > retVal;
154         bool bInEscape = false;
155         bool bInValue = false;
156         bool bInType = true;
157         sal_Int32 nTypeNameStart = 0;
158         OUString sType;
159         ::rtl::OUStringBuffer sbufValue;
160         sal_Int32 length = rRawString.getLength();
161 
162         for (sal_Int32 i = 0; i < length; i++)
163         {
164             sal_Unicode c = rRawString[i];
165 
166             if (c == '=')
167             {
168                 if (! bInValue)
169                 {
170                     sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
171                     sType = sType.trim();
172                     bInType = false;
173                 }
174                 else
175                 {
176                     sbufValue.append(c);
177                 }
178             }
179             else if (c == '"')
180             {
181                 if (!bInEscape)
182                 {
183                     //If this is the quote is the first of the couple which enclose the
184                     //whole value, because the value contains special characters
185                     //then we just drop it. That is, this character must be followed by
186                     //a character which is not '"'.
187                     if ( i + 1 < length && rRawString[i+1] == '"')
188                         bInEscape = true;
189                     else
190                         bInValue = !bInValue; //value is enclosed in " "
191                 }
192                 else
193                 {
194                     //This quote is escaped by a preceding quote and therefore is
195                     //part of the value
196                     sbufValue.append(c);
197                     bInEscape = false;
198                 }
199             }
200             else if (c == ',' || c == '+')
201             {
202                 //The comma separate the attribute value pairs.
203                 //If the comma is not part of a value (the value would then be enclosed in '"'),
204                 //then we have reached the end of the value
205                 if (!bInValue)
206                 {
207                     OSL_ASSERT(sType.getLength());
208                     retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear()));
209                     sType = OUString();
210                     //The next char is the start of the new type
211                     nTypeNameStart = i + 1;
212                     bInType = true;
213                 }
214                 else
215                 {
216                     //The whole string is enclosed because it contains special characters.
217                     //The enclosing '"' are not part of certificate but will be added by
218                     //the function (Windows or NSS) which retrieves DN
219                     sbufValue.append(c);
220                 }
221             }
222             else
223             {
224                 if (!bInType)
225                     sbufValue.append(c);
226             }
227         }
228         if (sbufValue.getLength())
229         {
230             OSL_ASSERT(sType.getLength());
231             retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear()));
232         }
233         return retVal;
234     }
235 #else
236 vector< pair< OUString, OUString> > parseDN(const OUString& rRawString)
237     {
238         vector< pair<OUString, OUString> > retVal;
239         //bInEscape == true means that the preceding character is an escape character
240         bool bInEscape = false;
241         bool bInValue = false;
242         bool bInType = true;
243         sal_Int32 nTypeNameStart = 0;
244         OUString sType;
245         ::rtl::OUStringBuffer sbufValue;
246         sal_Int32 length = rRawString.getLength();
247 
248         for (sal_Int32 i = 0; i < length; i++)
249         {
250             sal_Unicode c = rRawString[i];
251 
252             if (c == '=')
253             {
254                 if (! bInValue)
255                 {
256                     sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart);
257                     sType = sType.trim();
258                     bInType = false;
259                 }
260                 else
261                 {
262                     sbufValue.append(c);
263                 }
264             }
265             else if (c == '\\')
266             {
267                 if (!bInEscape)
268                 {
269                     bInEscape = true;
270                 }
271                 else
272                 { // bInEscape is true
273                     sbufValue.append(c);
274                     bInEscape = false;
275                 }
276             }
277             else if (c == '"')
278             {
279                 //an unescaped '"' is either at the beginning or end of the value
280                 if (!bInEscape)
281                 {
282                     if ( !bInValue)
283                         bInValue = true;
284                     else if (bInValue)
285                         bInValue = false;
286                 }
287                 else
288                 {
289                     //This quote is escaped by a preceding quote and therefore is
290                     //part of the value
291                     sbufValue.append(c);
292                     bInEscape = false;
293                 }
294             }
295             else if (c == ',' || c == '+')
296             {
297                 //The comma separate the attribute value pairs.
298                 //If the comma is not part of a value (the value would then be enclosed in '"'),
299                 //then we have reached the end of the value
300                 if (!bInValue)
301                 {
302                     OSL_ASSERT(sType.getLength());
303                     retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear()));
304                     sType = OUString();
305                     //The next char is the start of the new type
306                     nTypeNameStart = i + 1;
307                     bInType = true;
308                 }
309                 else
310                 {
311                     //The whole string is enclosed because it contains special characters.
312                     //The enclosing '"' are not part of certificate but will be added by
313                     //the function (Windows or NSS) which retrieves DN
314                     sbufValue.append(c);
315                 }
316             }
317             else
318             {
319                 if (!bInType)
320                 {
321                     sbufValue.append(c);
322                     bInEscape = false;
323                 }
324             }
325         }
326         if (sbufValue.getLength())
327         {
328             OSL_ASSERT(sType.getLength());
329             retVal.push_back(make_pair(sType, sbufValue.makeStringAndClear()));
330         }
331         return retVal;
332     }
333 
334 #endif
335 
336     String GetContentPart( const String& _rRawString )
337     {
338         char const * aIDs[] = { "CN", "OU", "O", "E", NULL };
339         OUString retVal;
340         int i = 0;
341         vector< pair< OUString, OUString > > vecAttrValueOfDN = parseDN(_rRawString);
342         while ( aIDs[i] )
343         {
344             OUString sPartId = OUString::createFromAscii( aIDs[i++] );
345             typedef vector< pair < OUString, OUString > >::const_iterator CIT;
346             for (CIT idn = vecAttrValueOfDN.begin(); idn != vecAttrValueOfDN.end(); idn++)
347             {
348                 if (idn->first.equals(sPartId))
349                 {
350                     retVal = idn->second;
351                     break;
352                 }
353             }
354             if (retVal.getLength())
355                 break;
356         }
357         return retVal;
358     }
359 
360 	String GetHexString( const ::com::sun::star::uno::Sequence< sal_Int8 >& _rSeq, const char* _pSep, sal_uInt16 _nLineBreak )
361 	{
362 		const sal_Int8*			pSerNumSeq = _rSeq.getConstArray();
363 		int						nCnt = _rSeq.getLength();
364 		String					aStr;
365 		const char				pHexDigs[ 17 ] = "0123456789ABCDEF";
366 		char					pBuffer[ 3 ] = "  ";
367 		sal_uInt8					nNum;
368 		sal_uInt16					nBreakStart = _nLineBreak? _nLineBreak : 1;
369 		sal_uInt16					nBreak = nBreakStart;
370 		for( int i = 0 ; i < nCnt ; ++i )
371 		{
372 			nNum = sal_uInt8( pSerNumSeq[ i ] );
373 
374 			//MM : exchange the buffer[0] and buffer[1], which make it consistent with Mozilla and Windows
375 			pBuffer[ 1 ] = pHexDigs[ nNum & 0x0F ];
376 			nNum >>= 4;
377 			pBuffer[ 0 ] = pHexDigs[ nNum ];
378 			aStr.AppendAscii( pBuffer );
379 
380 			--nBreak;
381 			if( nBreak )
382 				aStr.AppendAscii( _pSep );
383 			else
384 			{
385 				nBreak = nBreakStart;
386 				aStr.AppendAscii( "\n" );
387 			}
388 		}
389 
390 		return aStr;
391 	}
392 
393 	long ShrinkToFitWidth( Control& _rCtrl, long _nOffs )
394 	{
395 		long	nWidth = _rCtrl.GetTextWidth( _rCtrl.GetText() );
396 		Size	aSize( _rCtrl.GetSizePixel() );
397 		nWidth += _nOffs;
398 		aSize.Width() = nWidth;
399 		_rCtrl.SetSizePixel( aSize );
400 		return nWidth;
401 	}
402 
403 	void AlignAfterImage( const FixedImage& _rImage, Control& _rCtrl, long _nXOffset )
404 	{
405 		Point	aPos( _rImage.GetPosPixel() );
406 		Size	aSize( _rImage.GetSizePixel() );
407 		long	n = aPos.X();
408 		n += aSize.Width();
409 		n += _nXOffset;
410 		aPos.X() = n;
411 		n = aPos.Y();
412 		n += aSize.Height() / 2;					// y-position is in the middle of the image
413 		n -= _rCtrl.GetSizePixel().Height() / 2;	// center Control
414 		aPos.Y() = n;
415 		_rCtrl.SetPosPixel( aPos );
416 	}
417 
418 	void AlignAfterImage( const FixedImage& _rImage, FixedInfo& _rFI, long _nXOffset )
419 	{
420 		AlignAfterImage( _rImage, static_cast< Control& >( _rFI ), _nXOffset );
421 		ShrinkToFitWidth( _rFI );
422 	}
423 
424 	void AlignAndFitImageAndControl( FixedImage& _rImage, FixedInfo& _rFI, long _nXOffset )
425 	{
426 		_rImage.SetSizePixel( _rImage.GetImage().GetSizePixel() );
427 		AlignAfterImage( _rImage, _rFI, _nXOffset );
428 	}
429 }
430 
431 
432