summaryrefslogtreecommitdiff
path: root/oox/source/ole/olehelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/ole/olehelper.cxx')
-rw-r--r--oox/source/ole/olehelper.cxx316
1 files changed, 316 insertions, 0 deletions
diff --git a/oox/source/ole/olehelper.cxx b/oox/source/ole/olehelper.cxx
new file mode 100644
index 000000000000..95678f147cd4
--- /dev/null
+++ b/oox/source/ole/olehelper.cxx
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/olehelper.hxx"
+
+#include <rtl/ustrbuf.hxx>
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/graphichelper.hxx"
+#include "oox/token/tokens.hxx"
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+// ============================================================================
+
+namespace {
+
+const sal_uInt32 OLE_COLORTYPE_MASK = 0xFF000000;
+const sal_uInt32 OLE_COLORTYPE_CLIENT = 0x00000000;
+const sal_uInt32 OLE_COLORTYPE_PALETTE = 0x01000000;
+const sal_uInt32 OLE_COLORTYPE_BGR = 0x02000000;
+const sal_uInt32 OLE_COLORTYPE_SYSCOLOR = 0x80000000;
+
+const sal_uInt32 OLE_PALETTECOLOR_MASK = 0x0000FFFF;
+const sal_uInt32 OLE_BGRCOLOR_MASK = 0x00FFFFFF;
+const sal_uInt32 OLE_SYSTEMCOLOR_MASK = 0x0000FFFF;
+
+/** Swaps the red and blue component of the passed color. */
+inline sal_uInt32 lclSwapRedBlue( sal_uInt32 nColor )
+{
+ return static_cast< sal_uInt32 >( (nColor & 0xFF00FF00) | ((nColor & 0x0000FF) << 16) | ((nColor & 0xFF0000) >> 16) );
+}
+
+/** Returns the UNO RGB color from the passed encoded OLE BGR color. */
+inline sal_Int32 lclDecodeBgrColor( sal_uInt32 nOleColor )
+{
+ return static_cast< sal_Int32 >( lclSwapRedBlue( nOleColor ) & 0xFFFFFF );
+}
+
+// ----------------------------------------------------------------------------
+
+const sal_Char OLE_GUID_URLMONIKER[] = "{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}";
+const sal_Char OLE_GUID_FILEMONIKER[] = "{00000303-0000-0000-C000-000000000046}";
+
+const sal_uInt32 OLE_STDPIC_ID = 0x0000746C;
+
+const sal_uInt32 OLE_STDHLINK_VERSION = 2;
+const sal_uInt32 OLE_STDHLINK_HASTARGET = 0x00000001; /// Has hyperlink moniker.
+const sal_uInt32 OLE_STDHLINK_ABSOLUTE = 0x00000002; /// Absolute path.
+const sal_uInt32 OLE_STDHLINK_HASLOCATION = 0x00000008; /// Has target location.
+const sal_uInt32 OLE_STDHLINK_HASDISPLAY = 0x00000010; /// Has display string.
+const sal_uInt32 OLE_STDHLINK_HASGUID = 0x00000020; /// Has identification GUID.
+const sal_uInt32 OLE_STDHLINK_HASTIME = 0x00000040; /// Has creation time.
+const sal_uInt32 OLE_STDHLINK_HASFRAME = 0x00000080; /// Has frame.
+const sal_uInt32 OLE_STDHLINK_ASSTRING = 0x00000100; /// Hyperlink as simple string.
+
+// ----------------------------------------------------------------------------
+
+template< typename Type >
+void lclAppendHex( OUStringBuffer& orBuffer, Type nValue )
+{
+ const sal_Int32 nWidth = 2 * sizeof( Type );
+ static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ orBuffer.setLength( orBuffer.getLength() + nWidth );
+ for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
+ orBuffer.setCharAt( nCharIdx, spcHexChars[ nValue & 0xF ] );
+}
+
+OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, bool bUnicode )
+{
+ OUString aRet;
+ sal_Int32 nChars = rInStrm.readInt32();
+ if( nChars > 0 )
+ {
+ sal_Int32 nReadChars = getLimitedValue< sal_Int32, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 );
+ // byte strings are always in ANSI (Windows 1252) encoding
+ aRet = bUnicode ? rInStrm.readUnicodeArray( nReadChars, true ) : rInStrm.readCharArrayUC( nReadChars, RTL_TEXTENCODING_MS_1252, true );
+ // strings are NUL terminated, remove trailing NUL and possible other garbage
+ sal_Int32 nNulPos = aRet.indexOf( '\0' );
+ if( nNulPos >= 0 )
+ aRet = aRet.copy( 0, nNulPos );
+ // skip remaining chars
+ rInStrm.skip( (bUnicode ? 2 : 1) * (nChars - nReadChars) );
+ }
+ return aRet;
+}
+
+} // namespace
+
+// ============================================================================
+
+StdFontInfo::StdFontInfo() :
+ mnHeight( 0 ),
+ mnWeight( OLE_STDFONT_NORMAL ),
+ mnCharSet( WINDOWS_CHARSET_ANSI ),
+ mnFlags( 0 )
+{
+}
+
+StdFontInfo::StdFontInfo( const ::rtl::OUString& rName, sal_uInt32 nHeight,
+ sal_uInt16 nWeight, sal_uInt16 nCharSet, sal_uInt8 nFlags ) :
+ maName( rName ),
+ mnHeight( nHeight ),
+ mnWeight( nWeight ),
+ mnCharSet( nCharSet ),
+ mnFlags( nFlags )
+{
+}
+
+// ============================================================================
+
+/*static*/ sal_Int32 OleHelper::decodeOleColor(
+ const GraphicHelper& rGraphicHelper, sal_uInt32 nOleColor, bool bDefaultColorBgr )
+{
+ static const sal_Int32 spnSystemColors[] =
+ {
+ XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption,
+ XML_menu, XML_window, XML_windowFrame, XML_menuText,
+ XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder,
+ XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace,
+ XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText,
+ XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText,
+ XML_infoBk
+ };
+
+ switch( nOleColor & OLE_COLORTYPE_MASK )
+ {
+ case OLE_COLORTYPE_CLIENT:
+ return bDefaultColorBgr ? lclDecodeBgrColor( nOleColor ) : rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
+
+ case OLE_COLORTYPE_PALETTE:
+ return rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
+
+ case OLE_COLORTYPE_BGR:
+ return lclDecodeBgrColor( nOleColor );
+
+ case OLE_COLORTYPE_SYSCOLOR:
+ return rGraphicHelper.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nOleColor & OLE_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE );
+ }
+ OSL_FAIL( "OleHelper::decodeOleColor - unknown color type" );
+ return API_RGB_BLACK;
+}
+
+/*static*/ sal_uInt32 OleHelper::encodeOleColor( sal_Int32 nRgbColor )
+{
+ return OLE_COLORTYPE_BGR | lclSwapRedBlue( static_cast< sal_uInt32 >( nRgbColor & 0xFFFFFF ) );
+}
+
+/*static*/ OUString OleHelper::importGuid( BinaryInputStream& rInStrm )
+{
+ OUStringBuffer aBuffer;
+ aBuffer.append( sal_Unicode( '{' ) );
+ lclAppendHex( aBuffer, rInStrm.readuInt32() );
+ aBuffer.append( sal_Unicode( '-' ) );
+ lclAppendHex( aBuffer, rInStrm.readuInt16() );
+ aBuffer.append( sal_Unicode( '-' ) );
+ lclAppendHex( aBuffer, rInStrm.readuInt16() );
+ aBuffer.append( sal_Unicode( '-' ) );
+ lclAppendHex( aBuffer, rInStrm.readuInt8() );
+ lclAppendHex( aBuffer, rInStrm.readuInt8() );
+ aBuffer.append( sal_Unicode( '-' ) );
+ for( int nIndex = 0; nIndex < 6; ++nIndex )
+ lclAppendHex( aBuffer, rInStrm.readuInt8() );
+ aBuffer.append( sal_Unicode( '}' ) );
+ return aBuffer.makeStringAndClear();
+}
+
+/*static*/ bool OleHelper::importStdFont( StdFontInfo& orFontInfo, BinaryInputStream& rInStrm, bool bWithGuid )
+{
+ if( bWithGuid )
+ {
+ bool bIsStdFont = importGuid( rInStrm ).equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(OLE_GUID_STDFONT));
+ OSL_ENSURE( bIsStdFont, "OleHelper::importStdFont - unexpected header GUID, expected StdFont" );
+ if( !bIsStdFont )
+ return false;
+ }
+
+ sal_uInt8 nVersion, nNameLen;
+ rInStrm >> nVersion >> orFontInfo.mnCharSet >> orFontInfo.mnFlags >> orFontInfo.mnWeight >> orFontInfo.mnHeight >> nNameLen;
+ // according to spec the name is ASCII
+ orFontInfo.maName = rInStrm.readCharArrayUC( nNameLen, RTL_TEXTENCODING_ASCII_US );
+ OSL_ENSURE( nVersion <= 1, "OleHelper::importStdFont - wrong version" );
+ return !rInStrm.isEof() && (nVersion <= 1);
+}
+
+/*static*/ bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm, bool bWithGuid )
+{
+ if( bWithGuid )
+ {
+ bool bIsStdPic = importGuid( rInStrm ).equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(OLE_GUID_STDPIC));
+ OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" );
+ if( !bIsStdPic )
+ return false;
+ }
+
+ sal_uInt32 nStdPicId;
+ sal_Int32 nBytes;
+ rInStrm >> nStdPicId >> nBytes;
+ OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" );
+ return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes);
+}
+
+/*static*/ bool OleHelper::importStdHlink( StdHlinkInfo& orHlinkInfo, BinaryInputStream& rInStrm, bool bWithGuid )
+{
+ if( bWithGuid )
+ {
+ bool bIsStdHlink = importGuid( rInStrm ).equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(OLE_GUID_STDHLINK));
+ OSL_ENSURE( bIsStdHlink, "OleHelper::importStdHlink - unexpected header GUID, expected StdHlink" );
+ if( !bIsStdHlink )
+ return false;
+ }
+
+ sal_uInt32 nVersion, nFlags;
+ rInStrm >> nVersion >> nFlags;
+ OSL_ENSURE( nVersion == OLE_STDHLINK_VERSION, "OleHelper::importStdHlink - unexpected header version" );
+ if( rInStrm.isEof() || (nVersion != OLE_STDHLINK_VERSION) )
+ return false;
+
+ // display string
+ if( getFlag( nFlags, OLE_STDHLINK_HASDISPLAY ) )
+ orHlinkInfo.maDisplay = lclReadStdHlinkString( rInStrm, true );
+ // frame string
+ if( getFlag( nFlags, OLE_STDHLINK_HASFRAME ) )
+ orHlinkInfo.maFrame = lclReadStdHlinkString( rInStrm, true );
+
+ // target
+ if( getFlag( nFlags, OLE_STDHLINK_HASTARGET ) )
+ {
+ if( getFlag( nFlags, OLE_STDHLINK_ASSTRING ) )
+ {
+ OSL_ENSURE( getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - link not absolute" );
+ orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, true );
+ }
+ else // hyperlink moniker
+ {
+ OUString aGuid = importGuid( rInStrm );
+ if( aGuid.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(OLE_GUID_FILEMONIKER)) )
+ {
+ // file name, maybe relative and with directory up-count
+ sal_Int16 nUpLevels;
+ rInStrm >> nUpLevels;
+ OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - absolute filename with upcount" );
+ orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, false );
+ rInStrm.skip( 24 );
+ sal_Int32 nBytes = rInStrm.readInt32();
+ if( nBytes > 0 )
+ {
+ sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 );
+ sal_uInt16 nChars = getLimitedValue< sal_uInt16, sal_Int32 >( rInStrm.readInt32() / 2, 0, SAL_MAX_UINT16 );
+ rInStrm.skip( 2 ); // key value
+ orHlinkInfo.maTarget = rInStrm.readUnicodeArray( nChars ); // NOT null terminated
+ rInStrm.seek( nEndPos );
+ }
+ if( !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ) )
+ for( sal_Int16 nLevel = 0; nLevel < nUpLevels; ++nLevel )
+ orHlinkInfo.maTarget = CREATE_OUSTRING( "../" ) + orHlinkInfo.maTarget;
+ }
+ else if( aGuid.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(OLE_GUID_URLMONIKER)) )
+ {
+ // URL, maybe relative and with leading '../'
+ sal_Int32 nBytes = rInStrm.readInt32();
+ sal_Int64 nEndPos = rInStrm.tell() + ::std::max< sal_Int32 >( nBytes, 0 );
+ orHlinkInfo.maTarget = rInStrm.readNulUnicodeArray();
+ rInStrm.seek( nEndPos );
+ }
+ else
+ {
+ OSL_FAIL( "OleHelper::importStdHlink - unsupported hyperlink moniker" );
+ return false;
+ }
+ }
+ }
+
+ // target location
+ if( getFlag( nFlags, OLE_STDHLINK_HASLOCATION ) )
+ orHlinkInfo.maLocation = lclReadStdHlinkString( rInStrm, true );
+
+ return !rInStrm.isEof();
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */