merge the formfield patch from ooo-build
[ooovba.git] / oox / source / ole / olehelper.cxx
blobc0eb37003d9a94a89bd916a210564f2bc272fd03
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: olehelper.cxx,v $
10 * $Revision: 1.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/ole/olehelper.hxx"
32 #include <rtl/ustrbuf.hxx>
33 #include "oox/helper/binaryinputstream.hxx"
35 using ::rtl::OUString;
36 using ::rtl::OUStringBuffer;
38 namespace oox {
39 namespace ole {
41 // ============================================================================
43 namespace {
45 const sal_Char* const OLE_GUID_STDPIC = "{0BE35204-8F91-11CE-9DE3-00AA004BB851}";
46 const sal_Char* const OLE_GUID_STDHLINK = "{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}";
47 const sal_Char* const OLE_GUID_URLMONIKER = "{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}";
48 const sal_Char* const OLE_GUID_FILEMONIKER = "{00000303-0000-0000-C000-000000000046}";
50 const sal_uInt32 OLE_STDPIC_ID = 0x0000746C;
52 const sal_uInt32 OLE_STDHLINK_VERSION = 2;
53 const sal_uInt32 OLE_STDHLINK_HASTARGET = 0x00000001; /// Has hyperlink moniker.
54 const sal_uInt32 OLE_STDHLINK_ABSOLUTE = 0x00000002; /// Absolute path.
55 const sal_uInt32 OLE_STDHLINK_HASLOCATION = 0x00000008; /// Has target location.
56 const sal_uInt32 OLE_STDHLINK_HASDISPLAY = 0x00000010; /// Has display string.
57 const sal_uInt32 OLE_STDHLINK_HASGUID = 0x00000020; /// Has identification GUID.
58 const sal_uInt32 OLE_STDHLINK_HASTIME = 0x00000040; /// Has creation time.
59 const sal_uInt32 OLE_STDHLINK_HASFRAME = 0x00000080; /// Has frame.
60 const sal_uInt32 OLE_STDHLINK_ASSTRING = 0x00000100; /// Hyperlink as simple string.
62 // ----------------------------------------------------------------------------
64 template< typename Type >
65 void lclAppendHex( OUStringBuffer& orBuffer, Type nValue )
67 const sal_Int32 nWidth = 2 * sizeof( Type );
68 static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
69 orBuffer.setLength( orBuffer.getLength() + nWidth );
70 for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
71 orBuffer.setCharAt( nCharIdx, spcHexChars[ nValue & 0xF ] );
74 OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bUnicode )
76 OUString aRet;
77 sal_Int32 nChars = rInStrm.readInt32();
78 if( nChars > 0 )
80 sal_Int32 nReadChars = getLimitedValue< sal_Int32, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 );
81 aRet = bUnicode ? rInStrm.readUnicodeArray( nReadChars, true ) : rInStrm.readCharArrayUC( nReadChars, eTextEnc, true );
82 // strings are NUL terminated, remove trailing NUL and possible other garbage
83 sal_Int32 nNulPos = aRet.indexOf( '\0' );
84 if( nNulPos >= 0 )
85 aRet = aRet.copy( 0, nNulPos );
86 // skip remaining chars
87 rInStrm.skip( (bUnicode ? 2 : 1) * (nChars - nReadChars) );
89 return aRet;
92 } // namespace
94 // ============================================================================
96 /*static*/ OUString OleHelper::importGuid( BinaryInputStream& rInStrm )
98 OUStringBuffer aBuffer;
99 aBuffer.append( sal_Unicode( '{' ) );
100 lclAppendHex( aBuffer, rInStrm.readuInt32() );
101 aBuffer.append( sal_Unicode( '-' ) );
102 lclAppendHex( aBuffer, rInStrm.readuInt16() );
103 aBuffer.append( sal_Unicode( '-' ) );
104 lclAppendHex( aBuffer, rInStrm.readuInt16() );
105 aBuffer.append( sal_Unicode( '-' ) );
106 lclAppendHex( aBuffer, rInStrm.readuInt8() );
107 lclAppendHex( aBuffer, rInStrm.readuInt8() );
108 aBuffer.append( sal_Unicode( '-' ) );
109 for( int nIndex = 0; nIndex < 6; ++nIndex )
110 lclAppendHex( aBuffer, rInStrm.readuInt8() );
111 aBuffer.append( sal_Unicode( '}' ) );
112 return aBuffer.makeStringAndClear();
115 /*static*/ bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm, bool bWithGuid )
117 if( bWithGuid )
119 bool bIsStdPic = importGuid( rInStrm ).equalsAscii( OLE_GUID_STDPIC );
120 OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" );
121 if( !bIsStdPic )
122 return false;
125 sal_uInt32 nStdPicId;
126 sal_Int32 nBytes;
127 rInStrm >> nStdPicId >> nBytes;
128 OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" );
129 return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes);
132 /*static*/ bool OleHelper::importStdHlink( StdHlinkInfo& orHlinkInfo, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bWithGuid )
134 if( bWithGuid )
136 bool bIsStdHlink = importGuid( rInStrm ).equalsAscii( OLE_GUID_STDHLINK );
137 OSL_ENSURE( bIsStdHlink, "OleHelper::importStdHlink - unexpected header GUID, expected StdHlink" );
138 if( !bIsStdHlink )
139 return false;
142 sal_uInt32 nVersion, nFlags;
143 rInStrm >> nVersion >> nFlags;
144 OSL_ENSURE( nVersion == OLE_STDHLINK_VERSION, "OleHelper::importStdHlink - unexpected header version" );
145 if( rInStrm.isEof() || (nVersion != OLE_STDHLINK_VERSION) )
146 return false;
148 // display string
149 if( getFlag( nFlags, OLE_STDHLINK_HASDISPLAY ) )
150 orHlinkInfo.maDisplay = lclReadStdHlinkString( rInStrm, eTextEnc, true );
151 // frame string
152 if( getFlag( nFlags, OLE_STDHLINK_HASFRAME ) )
153 orHlinkInfo.maFrame = lclReadStdHlinkString( rInStrm, eTextEnc, true );
155 // target
156 if( getFlag( nFlags, OLE_STDHLINK_HASTARGET ) )
158 if( getFlag( nFlags, OLE_STDHLINK_ASSTRING ) )
160 OSL_ENSURE( getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - link not absolute" );
161 orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, true );
163 else // hyperlink moniker
165 OUString aGuid = importGuid( rInStrm );
166 if( aGuid.equalsAscii( OLE_GUID_FILEMONIKER ) )
168 // file name, maybe relative and with directory up-count
169 sal_Int16 nUpLevels;
170 rInStrm >> nUpLevels;
171 OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - absolute filename with upcount" );
172 orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, false );
173 rInStrm.skip( 24 );
174 sal_Int32 nBytes = rInStrm.readInt32();
175 if( nBytes > 0 )
177 sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 );
178 sal_uInt16 nChars = getLimitedValue< sal_uInt16, sal_Int32 >( rInStrm.readInt32() / 2, 0, SAL_MAX_UINT16 );
179 rInStrm.skip( 2 ); // key value
180 orHlinkInfo.maTarget = rInStrm.readUnicodeArray( nChars ); // NOT null terminated
181 rInStrm.seek( nEndPos );
183 if( !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ) )
184 for( sal_Int16 nLevel = 0; nLevel < nUpLevels; ++nLevel )
185 orHlinkInfo.maTarget = CREATE_OUSTRING( "../" ) + orHlinkInfo.maTarget;
187 else if( aGuid.equalsAscii( OLE_GUID_URLMONIKER ) )
189 // URL, maybe relative and with leading '../'
190 sal_Int32 nBytes = rInStrm.readInt32();
191 sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 );
192 orHlinkInfo.maTarget = rInStrm.readNulUnicodeArray();
193 rInStrm.seek( nEndPos );
195 else
197 OSL_ENSURE( false, "OleHelper::importStdHlink - unsupported hyperlink moniker" );
198 return false;
203 // target location
204 if( getFlag( nFlags, OLE_STDHLINK_HASLOCATION ) )
205 orHlinkInfo.maLocation = lclReadStdHlinkString( rInStrm, eTextEnc, true );
207 return true;
210 // ============================================================================
212 } // namespace ole
213 } // namespace oox