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 $
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
;
41 // ============================================================================
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
)
77 sal_Int32 nChars
= rInStrm
.readInt32();
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' );
85 aRet
= aRet
.copy( 0, nNulPos
);
86 // skip remaining chars
87 rInStrm
.skip( (bUnicode
? 2 : 1) * (nChars
- nReadChars
) );
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
)
119 bool bIsStdPic
= importGuid( rInStrm
).equalsAscii( OLE_GUID_STDPIC
);
120 OSL_ENSURE( bIsStdPic
, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" );
125 sal_uInt32 nStdPicId
;
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
)
136 bool bIsStdHlink
= importGuid( rInStrm
).equalsAscii( OLE_GUID_STDHLINK
);
137 OSL_ENSURE( bIsStdHlink
, "OleHelper::importStdHlink - unexpected header GUID, expected StdHlink" );
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
) )
149 if( getFlag( nFlags
, OLE_STDHLINK_HASDISPLAY
) )
150 orHlinkInfo
.maDisplay
= lclReadStdHlinkString( rInStrm
, eTextEnc
, true );
152 if( getFlag( nFlags
, OLE_STDHLINK_HASFRAME
) )
153 orHlinkInfo
.maFrame
= lclReadStdHlinkString( rInStrm
, eTextEnc
, true );
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
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 );
174 sal_Int32 nBytes
= rInStrm
.readInt32();
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
);
197 OSL_ENSURE( false, "OleHelper::importStdHlink - unsupported hyperlink moniker" );
204 if( getFlag( nFlags
, OLE_STDHLINK_HASLOCATION
) )
205 orHlinkInfo
.maLocation
= lclReadStdHlinkString( rInStrm
, eTextEnc
, true );
210 // ============================================================================