LCOV - code coverage report
Current view: top level - writerperfect/source/common - WPXSvStream.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 365 0.0 %
Date: 2014-04-14 Functions: 0 67 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "WPXSvStream.hxx"
      11             : 
      12             : #include <com/sun/star/packages/zip/XZipFileAccess2.hpp>
      13             : #include <com/sun/star/uno/Any.hxx>
      14             : 
      15             : #include <comphelper/processfactory.hxx>
      16             : #include <comphelper/seekableinput.hxx>
      17             : 
      18             : #include <rtl/string.hxx>
      19             : #include <tools/stream.hxx>
      20             : #include <unotools/streamwrap.hxx>
      21             : #include <unotools/ucbstreamhelper.hxx>
      22             : 
      23             : #include <limits>
      24             : #include <vector>
      25             : 
      26             : #include <boost/noncopyable.hpp>
      27             : #include <boost/scoped_ptr.hpp>
      28             : #include <boost/unordered_map.hpp>
      29             : 
      30             : using namespace ::com::sun::star::uno;
      31             : using namespace ::com::sun::star::io;
      32             : 
      33             : namespace container = com::sun::star::container;
      34             : namespace lang = com::sun::star::lang;
      35             : namespace packages = com::sun::star::packages;
      36             : 
      37             : namespace
      38             : {
      39             : 
      40             : class PositionHolder : boost::noncopyable
      41             : {
      42             : public:
      43             :     explicit PositionHolder(const Reference<XSeekable> &rxSeekable);
      44             :     ~PositionHolder();
      45             : 
      46             : private:
      47             :     const Reference<XSeekable> mxSeekable;
      48             :     const sal_uInt64 mnPosition;
      49             : };
      50             : 
      51           0 : PositionHolder::PositionHolder(const Reference<XSeekable> &rxSeekable)
      52             :     : mxSeekable(rxSeekable)
      53           0 :     , mnPosition(rxSeekable->getPosition())
      54             : {
      55           0 : }
      56             : 
      57           0 : PositionHolder::~PositionHolder() try
      58             : {
      59           0 :     mxSeekable->seek(mnPosition);
      60             : }
      61           0 : catch (...)
      62             : {
      63           0 : }
      64             : 
      65             : } // anonymous namespace
      66             : 
      67             : typedef struct
      68           0 : {
      69             :     SotStorageRef ref;
      70           0 : } SotStorageRefWrapper;
      71             : 
      72             : typedef struct
      73           0 : {
      74             :     SotStorageStreamRef ref;
      75           0 : } SotStorageStreamRefWrapper;
      76             : 
      77             : namespace
      78             : {
      79             : 
      80           0 : const rtl::OUString concatPath(const rtl::OUString &lhs, const rtl::OUString &rhs)
      81             : {
      82           0 :     if (lhs.isEmpty())
      83           0 :         return rhs;
      84           0 :     return lhs + "/" + rhs;
      85             : }
      86             : 
      87           0 : struct OLEStreamData
      88             : {
      89             :     explicit OLEStreamData(const rtl::OString &rName);
      90             : 
      91             :     SotStorageStreamRefWrapper stream;
      92             : 
      93             :     /** Name of the stream.
      94             :       *
      95             :       * This is not @c rtl::OUString, because we need to be able to
      96             :       * produce const char* from it.
      97             :       */
      98             :     rtl::OString name;
      99             : };
     100             : 
     101             : typedef boost::unordered_map<rtl::OUString, std::size_t, rtl::OUStringHash> NameMap_t;
     102             : typedef boost::unordered_map<rtl::OUString, SotStorageRefWrapper, rtl::OUStringHash> OLEStorageMap_t;
     103             : 
     104             : /** Representation of an OLE2 storage.
     105             :   *
     106             :   * This class tries to bring a bit of sanity to use of SotStorage with
     107             :   * respect to the needs of @c librevenge::RVNGInputStream API. It
     108             :   * holds all nested storages for the whole lifetime (more precisely,
     109             :   * since initialization, which is performed by calling @c
     110             :   * initialize()), thus ensuring that no created stream is destroyed
     111             :   * just because its parent storage went out of scope. It also holds a
     112             :   * bidirectional map of stream names to their indexes (index of a
     113             :   * stream is determined by deep-first traversal), which is also
     114             :   * populated during initialization (member variables @c maStreams and
     115             :   * @c maNameMap).
     116             :   *
     117             :   * Streams are created on demand (and saved, for the same reason as
     118             :   * storages).
     119             :   */
     120           0 : struct OLEStorageImpl
     121             : {
     122             :     OLEStorageImpl();
     123             : 
     124             :     void initialize(SvStream *pStream);
     125             : 
     126             :     SotStorageStreamRef getStream(const rtl::OUString &rPath);
     127             :     SotStorageStreamRef getStream(std::size_t nId);
     128             : 
     129             : private:
     130             :     void traverse(const SotStorageRef &rStorage, const rtl::OUString &rPath);
     131             : 
     132             :     SotStorageStreamRef createStream(const rtl::OUString &rPath);
     133             : 
     134             : public:
     135             :     SotStorageRefWrapper mxRootStorage; //< root storage of the OLE2
     136             :     OLEStorageMap_t maStorageMap; //< map of all sub storages by name
     137             :     ::std::vector< OLEStreamData > maStreams; //< list of streams and their names
     138             :     NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
     139             :     bool mbInitialized;
     140             : };
     141             : 
     142           0 : OLEStreamData::OLEStreamData(const rtl::OString &rName)
     143             :     : stream()
     144           0 :     , name(rName)
     145             : {
     146           0 : }
     147             : 
     148           0 : OLEStorageImpl::OLEStorageImpl()
     149             :     : mxRootStorage()
     150             :     , maStorageMap()
     151             :     , maStreams()
     152             :     , maNameMap()
     153           0 :     , mbInitialized(false)
     154             : {
     155           0 : }
     156             : 
     157           0 : void OLEStorageImpl::initialize(SvStream *const pStream)
     158             : {
     159           0 :     if (!pStream)
     160           0 :         return;
     161             : 
     162           0 :     mxRootStorage.ref = new SotStorage( pStream, true );
     163             : 
     164           0 :     traverse(mxRootStorage.ref, "");
     165             : 
     166           0 :     mbInitialized = true;
     167             : }
     168             : 
     169           0 : SotStorageStreamRef OLEStorageImpl::getStream(const rtl::OUString &rPath)
     170             : {
     171           0 :     NameMap_t::iterator aIt = maNameMap.find(rPath);
     172             : 
     173             :     // For the while don't return stream in this situation.
     174             :     // Later, given how libcdr's zip stream implementation behaves,
     175             :     // return the first stream in the storage if there is one.
     176           0 :     if (maNameMap.end() == aIt)
     177           0 :         return SotStorageStreamRef();
     178             : 
     179           0 :     if (!maStreams[aIt->second].stream.ref.Is())
     180           0 :         maStreams[aIt->second].stream.ref = createStream(rPath);
     181             : 
     182           0 :     return maStreams[aIt->second].stream.ref;
     183             : }
     184             : 
     185           0 : SotStorageStreamRef OLEStorageImpl::getStream(const std::size_t nId)
     186             : {
     187           0 :     if (!maStreams[nId].stream.ref.Is())
     188           0 :         maStreams[nId].stream.ref = createStream(rtl::OStringToOUString(maStreams[nId].name, RTL_TEXTENCODING_UTF8));
     189             : 
     190           0 :     return maStreams[nId].stream.ref;
     191             : }
     192             : 
     193           0 : void OLEStorageImpl::traverse(const SotStorageRef &rStorage, const rtl::OUString &rPath)
     194             : {
     195           0 :     SvStorageInfoList infos;
     196             : 
     197           0 :     rStorage->FillInfoList(&infos);
     198             : 
     199           0 :     for (SvStorageInfoList::const_iterator aIt = infos.begin(); infos.end() != aIt; ++aIt)
     200             :     {
     201           0 :         if (aIt->IsStream())
     202             :         {
     203           0 :             maStreams.push_back(OLEStreamData(rtl::OUStringToOString(aIt->GetName(), RTL_TEXTENCODING_UTF8)));
     204           0 :             maNameMap[concatPath(rPath, aIt->GetName())] = maStreams.size() - 1;
     205             :         }
     206           0 :         else if (aIt->IsStorage())
     207             :         {
     208           0 :             const rtl::OUString aPath = concatPath(rPath, aIt->GetName());
     209           0 :             SotStorageRefWrapper xStorage;
     210           0 :             xStorage.ref = rStorage->OpenSotStorage(aIt->GetName(), STREAM_STD_READ);
     211           0 :             maStorageMap[aPath] = xStorage;
     212             : 
     213             :             // deep-first traversal
     214           0 :             traverse(xStorage.ref, aPath);
     215             :         }
     216             :         else
     217             :         {
     218             :             assert(false);
     219             :         }
     220           0 :     }
     221           0 : }
     222             : 
     223           0 : SotStorageStreamRef OLEStorageImpl::createStream(const rtl::OUString &rPath)
     224             : {
     225           0 :     const sal_Int32 nDelim = rPath.lastIndexOf(sal_Unicode('/'));
     226             : 
     227           0 :     if (-1 == nDelim)
     228           0 :         return mxRootStorage.ref->OpenSotStream(rPath, STREAM_STD_READ);
     229             : 
     230           0 :     const rtl::OUString aDir = rPath.copy(0, nDelim);
     231           0 :     const rtl::OUString aName = rPath.copy(nDelim + 1);
     232             : 
     233           0 :     const OLEStorageMap_t::const_iterator aIt = maStorageMap.find(aDir);
     234             : 
     235             :     // We can only get there for paths that are present in the OLE.
     236             :     // Which means the storage must exist.
     237             :     assert(maStorageMap.end() != aIt);
     238             : 
     239           0 :     return aIt->second.ref->OpenSotStream(aName, STREAM_STD_READ);
     240             : }
     241             : 
     242             : }
     243             : 
     244             : namespace
     245             : {
     246             : 
     247           0 : struct ZipStreamData
     248             : {
     249             :     explicit ZipStreamData(const rtl::OString &rName);
     250             : 
     251             :     Reference<XInputStream> xStream;
     252             : 
     253             :     /** Name of the stream.
     254             :       *
     255             :       * This is not @c rtl::OUString, because we need to be able to
     256             :       * produce const char* from it.
     257             :       */
     258             :     rtl::OString aName;
     259             : };
     260             : 
     261             : /** Representation of a Zip storage.
     262             :   *
     263             :   * This is quite similar to OLEStorageImpl, except that we do not need
     264             :   * to keep all storages (folders) open.
     265             :   */
     266           0 : struct ZipStorageImpl
     267             : {
     268             :     ZipStorageImpl(const Reference<container::XNameAccess> &rxContainer);
     269             : 
     270             :     /** Initialize for access.
     271             :       *
     272             :       * This creates a bidirectional map of stream names to their
     273             :       * indexes (index of a stream is determined by deep-first
     274             :       * traversal).
     275             :       */
     276             :     void initialize();
     277             : 
     278             :     Reference<XInputStream> getStream(const rtl::OUString &rPath);
     279             :     Reference<XInputStream> getStream(std::size_t nId);
     280             : 
     281             : private:
     282             :     void traverse(const Reference<container::XNameAccess> &rxEnum);
     283             : 
     284             :     Reference<XInputStream> createStream(const rtl::OUString &rPath);
     285             : 
     286             : public:
     287             :     Reference<container::XNameAccess> mxContainer; //< root of the Zip
     288             :     ::std::vector< ZipStreamData > maStreams; //< list of streams and their names
     289             :     NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
     290             :     bool mbInitialized;
     291             : };
     292             : 
     293           0 : ZipStreamData::ZipStreamData(const rtl::OString &rName)
     294             :     : xStream()
     295           0 :     , aName(rName)
     296             : {
     297           0 : }
     298             : 
     299           0 : ZipStorageImpl::ZipStorageImpl(const Reference<container::XNameAccess> &rxContainer)
     300             :     : mxContainer(rxContainer)
     301             :     , maStreams()
     302             :     , maNameMap()
     303           0 :     , mbInitialized(false)
     304             : {
     305             :     assert(mxContainer.is());
     306           0 : }
     307             : 
     308           0 : void ZipStorageImpl::initialize()
     309             : {
     310           0 :     traverse(mxContainer);
     311             : 
     312           0 :     mbInitialized = true;
     313           0 : }
     314             : 
     315           0 : Reference<XInputStream> ZipStorageImpl::getStream(const rtl::OUString &rPath)
     316             : {
     317           0 :     NameMap_t::iterator aIt = maNameMap.find(rPath);
     318             : 
     319             :     // For the while don't return stream in this situation.
     320             :     // Later, given how libcdr's zip stream implementation behaves,
     321             :     // return the first stream in the storage if there is one.
     322           0 :     if (maNameMap.end() == aIt)
     323           0 :         return Reference<XInputStream>();
     324             : 
     325           0 :     if (!maStreams[aIt->second].xStream.is())
     326           0 :         maStreams[aIt->second].xStream = createStream(rPath);
     327             : 
     328           0 :     return maStreams[aIt->second].xStream;
     329             : }
     330             : 
     331           0 : Reference<XInputStream> ZipStorageImpl::getStream(const std::size_t nId)
     332             : {
     333           0 :     if (!maStreams[nId].xStream.is())
     334           0 :         maStreams[nId].xStream = createStream(rtl::OStringToOUString(maStreams[nId].aName, RTL_TEXTENCODING_UTF8));
     335             : 
     336           0 :     return maStreams[nId].xStream;
     337             : }
     338             : 
     339           0 : void ZipStorageImpl::traverse(const Reference<container::XNameAccess> &rxContainer)
     340             : {
     341           0 :     const Sequence<rtl::OUString> lNames = rxContainer->getElementNames();
     342             : 
     343           0 :     maStreams.reserve(lNames.getLength());
     344             : 
     345           0 :     for (sal_Int32 n = 0; n < lNames.getLength(); ++n)
     346             :     {
     347           0 :         if (!lNames[n].endsWithAsciiL("/", 1)) // skip dirs
     348             :         {
     349           0 :             maStreams.push_back(ZipStreamData(rtl::OUStringToOString(lNames[n], RTL_TEXTENCODING_UTF8)));
     350           0 :             maNameMap[lNames[n]] = maStreams.size() - 1;
     351             :         }
     352           0 :     }
     353           0 : }
     354             : 
     355           0 : Reference<XInputStream> ZipStorageImpl::createStream(const rtl::OUString &rPath)
     356             : {
     357           0 :     Reference<XInputStream> xStream;
     358             : 
     359             :     try
     360             :     {
     361           0 :         const Reference<XInputStream> xInputStream(mxContainer->getByName(rPath), UNO_QUERY_THROW);
     362           0 :         const Reference<XSeekable> xSeekable(xInputStream, UNO_QUERY);
     363             : 
     364           0 :         if (xSeekable.is())
     365           0 :             xStream = xInputStream;
     366             :         else
     367           0 :             xStream.set(new comphelper::OSeekableInputWrapper(xInputStream, comphelper::getProcessComponentContext()));
     368             :     }
     369           0 :     catch (const Exception &)
     370             :     {
     371             :         // nothing needed
     372             :     }
     373             : 
     374           0 :     return xStream;
     375             : }
     376             : 
     377             : }
     378             : 
     379             : class WPXSvInputStreamImpl
     380             : {
     381             : public :
     382             :     WPXSvInputStreamImpl( ::com::sun::star::uno::Reference<
     383             :                       ::com::sun::star::io::XInputStream > xStream );
     384             :     ~WPXSvInputStreamImpl();
     385             : 
     386             :     bool isStructured();
     387             :     unsigned subStreamCount();
     388             :     const char * subStreamName(unsigned id);
     389             :     bool existsSubStream(const char *name);
     390             :     WPXInputStream * getSubStreamByName(const char *name);
     391             :     WPXInputStream * getSubStreamById(unsigned id);
     392             : 
     393             :     const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead);
     394             :     int seek(long offset);
     395             :     long tell();
     396             :     bool isEnd();
     397             : 
     398             :     void invalidateReadBuffer();
     399             : 
     400             : private:
     401             :     bool isOLE();
     402             :     void ensureOLEIsInitialized();
     403             : 
     404             :     bool isZip();
     405             :     void ensureZipIsInitialized();
     406             : 
     407             :     WPXInputStream *createWPXStream(const SotStorageStreamRef &rxStorage);
     408             :     WPXInputStream *createWPXStream(const Reference<XInputStream> &rxStream);
     409             : 
     410             : private:
     411             :     ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > mxStream;
     412             :     ::com::sun::star::uno::Reference< ::com::sun::star::io::XSeekable > mxSeekable;
     413             :     ::com::sun::star::uno::Sequence< sal_Int8 > maData;
     414             :     boost::scoped_ptr< OLEStorageImpl > mpOLEStorage;
     415             :     boost::scoped_ptr< ZipStorageImpl > mpZipStorage;
     416             :     bool mbCheckedOLE;
     417             :     bool mbCheckedZip;
     418             : public:
     419             :     sal_Int64 mnLength;
     420             :     unsigned char *mpReadBuffer;
     421             :     unsigned long mnReadBufferLength;
     422             :     unsigned long mnReadBufferPos;
     423             : };
     424             : 
     425           0 : WPXSvInputStreamImpl::WPXSvInputStreamImpl( Reference< XInputStream > xStream ) :
     426             :     mxStream(xStream),
     427             :     mxSeekable(xStream, UNO_QUERY),
     428             :     maData(0),
     429             :     mpOLEStorage(0),
     430             :     mpZipStorage(0),
     431             :     mbCheckedOLE(false),
     432             :     mbCheckedZip(false),
     433             :     mnLength(0),
     434             :     mpReadBuffer(0),
     435             :     mnReadBufferLength(0),
     436           0 :     mnReadBufferPos(0)
     437             : {
     438           0 :     if (!xStream.is() || !mxStream.is())
     439           0 :         mnLength = 0;
     440             :     else
     441             :     {
     442           0 :         if (!mxSeekable.is())
     443           0 :             mnLength = 0;
     444             :         else
     445             :         {
     446             :             try
     447             :             {
     448           0 :                 mnLength = mxSeekable->getLength();
     449             :             }
     450           0 :             catch ( ... )
     451             :             {
     452             :                 SAL_WARN("writerperfect", "mnLength = mxSeekable->getLength() threw exception");
     453           0 :                 mnLength = 0;
     454             :             }
     455             :         }
     456             :     }
     457           0 : }
     458             : 
     459           0 : WPXSvInputStreamImpl::~WPXSvInputStreamImpl()
     460             : {
     461           0 : }
     462             : 
     463           0 : const unsigned char *WPXSvInputStreamImpl::read(unsigned long numBytes, unsigned long &numBytesRead)
     464             : {
     465           0 :     numBytesRead = 0;
     466             : 
     467           0 :     if (numBytes == 0 || isEnd())
     468           0 :         return 0;
     469             : 
     470           0 :     numBytesRead = mxStream->readSomeBytes (maData, numBytes);
     471           0 :     if (numBytesRead == 0)
     472           0 :         return 0;
     473             : 
     474           0 :     return (const unsigned char *)maData.getConstArray();
     475             : }
     476             : 
     477           0 : long WPXSvInputStreamImpl::tell()
     478             : {
     479           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     480           0 :         return -1L;
     481             :     else
     482             :     {
     483           0 :         sal_Int64 tmpPosition = mxSeekable->getPosition();
     484           0 :         if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
     485           0 :             return -1L;
     486           0 :         return (long)tmpPosition;
     487             :     }
     488             : }
     489             : 
     490           0 : int WPXSvInputStreamImpl::seek(long offset)
     491             : {
     492           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     493           0 :         return -1;
     494             : 
     495           0 :     sal_Int64 tmpPosition = mxSeekable->getPosition();
     496           0 :     if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)()))
     497           0 :         return -1;
     498             : 
     499             :     try
     500             :     {
     501           0 :         mxSeekable->seek(offset);
     502           0 :         return 0;
     503             :     }
     504           0 :     catch (...)
     505             :     {
     506             :         SAL_WARN("writerperfect", "mxSeekable->seek(offset) threw exception");
     507           0 :         return -1;
     508             :     }
     509             : }
     510             : 
     511           0 : bool WPXSvInputStreamImpl::isEnd()
     512             : {
     513           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     514           0 :         return true;
     515           0 :     return (mxSeekable->getPosition() >= mnLength);
     516             : }
     517             : 
     518           0 : bool WPXSvInputStreamImpl::isStructured()
     519             : {
     520           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     521           0 :         return false;
     522             : 
     523           0 :     PositionHolder pos(mxSeekable);
     524           0 :     mxSeekable->seek(0);
     525             : 
     526           0 :     if (isOLE())
     527           0 :         return true;
     528             : 
     529           0 :     mxSeekable->seek(0);
     530             : 
     531           0 :     return isZip();
     532             : }
     533             : 
     534           0 : unsigned WPXSvInputStreamImpl::subStreamCount()
     535             : {
     536           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     537           0 :         return 0;
     538             : 
     539           0 :     PositionHolder pos(mxSeekable);
     540           0 :     mxSeekable->seek(0);
     541             : 
     542           0 :     if (isOLE())
     543             :     {
     544           0 :         ensureOLEIsInitialized();
     545             : 
     546           0 :         return mpOLEStorage->maStreams.size();
     547             :     }
     548             : 
     549           0 :     mxSeekable->seek(0);
     550             : 
     551           0 :     if (isZip())
     552             :     {
     553           0 :         ensureZipIsInitialized();
     554             : 
     555           0 :         return mpZipStorage->maStreams.size();
     556             :     }
     557             : 
     558           0 :     return 0;
     559             : }
     560             : 
     561           0 : const char *WPXSvInputStreamImpl::subStreamName(const unsigned id)
     562             : {
     563           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     564           0 :         return 0;
     565             : 
     566           0 :     PositionHolder pos(mxSeekable);
     567           0 :     mxSeekable->seek(0);
     568             : 
     569           0 :     if (isOLE())
     570             :     {
     571           0 :         ensureOLEIsInitialized();
     572             : 
     573           0 :         if (mpOLEStorage->maStreams.size() <= id)
     574           0 :             return 0;
     575             : 
     576           0 :         return mpOLEStorage->maStreams[id].name.getStr();
     577             :     }
     578             : 
     579           0 :     mxSeekable->seek(0);
     580             : 
     581           0 :     if (isZip())
     582             :     {
     583           0 :         ensureZipIsInitialized();
     584             : 
     585           0 :         if (mpZipStorage->maStreams.size() <= id)
     586           0 :             return 0;
     587             : 
     588           0 :         return mpZipStorage->maStreams[id].aName.getStr();
     589             :     }
     590             : 
     591           0 :     return 0;
     592             : }
     593             : 
     594           0 : bool WPXSvInputStreamImpl::existsSubStream(const char *const name)
     595             : {
     596           0 :     if (!name)
     597           0 :         return false;
     598             : 
     599           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     600           0 :         return false;
     601             : 
     602           0 :     PositionHolder pos(mxSeekable);
     603           0 :     mxSeekable->seek(0);
     604             : 
     605           0 :     const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8));
     606             : 
     607           0 :     if (isOLE())
     608             :     {
     609           0 :         ensureOLEIsInitialized();
     610           0 :         return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName);
     611             :     }
     612             : 
     613           0 :     mxSeekable->seek(0);
     614             : 
     615           0 :     if (isZip())
     616             :     {
     617           0 :         ensureZipIsInitialized();
     618           0 :         return mpZipStorage->maNameMap.end() != mpZipStorage->maNameMap.find(aName);
     619             :     }
     620             : 
     621           0 :     return false;
     622             : }
     623             : 
     624           0 : WPXInputStream *WPXSvInputStreamImpl::getSubStreamByName(const char *const name)
     625             : {
     626           0 :     if (!name)
     627           0 :         return 0;
     628             : 
     629           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     630           0 :         return 0;
     631             : 
     632           0 :     PositionHolder pos(mxSeekable);
     633           0 :     mxSeekable->seek(0);
     634             : 
     635           0 :     const rtl::OUString aName(rtl::OStringToOUString(rtl::OString(name), RTL_TEXTENCODING_UTF8));
     636             : 
     637           0 :     if (isOLE())
     638             :     {
     639           0 :         ensureOLEIsInitialized();
     640           0 :         return createWPXStream(mpOLEStorage->getStream(aName));
     641             :     }
     642             : 
     643           0 :     mxSeekable->seek(0);
     644             : 
     645           0 :     if (isZip())
     646             :     {
     647           0 :         ensureZipIsInitialized();
     648             : 
     649             :         try
     650             :         {
     651           0 :             return createWPXStream(mpZipStorage->getStream(aName));
     652             :         }
     653           0 :         catch (const Exception &)
     654             :         {
     655             :             // nothing needed
     656             :         }
     657             :     }
     658             : 
     659           0 :     return 0;
     660             : }
     661             : 
     662           0 : WPXInputStream *WPXSvInputStreamImpl::getSubStreamById(const unsigned id)
     663             : {
     664           0 :     if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
     665           0 :         return 0;
     666             : 
     667           0 :     PositionHolder pos(mxSeekable);
     668           0 :     mxSeekable->seek(0);
     669             : 
     670           0 :     if (isOLE())
     671             :     {
     672           0 :         ensureOLEIsInitialized();
     673             : 
     674           0 :         if (mpOLEStorage->maStreams.size() <= id)
     675           0 :             return 0;
     676             : 
     677           0 :         return createWPXStream(mpOLEStorage->getStream(id));
     678             :     }
     679             : 
     680           0 :     mxSeekable->seek(0);
     681             : 
     682           0 :     if (isZip())
     683             :     {
     684           0 :         ensureZipIsInitialized();
     685             : 
     686           0 :         if (mpZipStorage->maStreams.size() <= id)
     687           0 :             return 0;
     688             : 
     689             :         try
     690             :         {
     691           0 :             return createWPXStream(mpZipStorage->getStream(id));
     692             :         }
     693           0 :         catch (const Exception &)
     694             :         {
     695             :             // nothing needed
     696             :         }
     697             :     }
     698           0 :     return 0;
     699             : }
     700             : 
     701           0 : void WPXSvInputStreamImpl::invalidateReadBuffer()
     702             : {
     703           0 :     if (mpReadBuffer)
     704             :     {
     705           0 :         seek((long) tell() + (long)mnReadBufferPos - (long)mnReadBufferLength);
     706           0 :         mpReadBuffer = 0;
     707           0 :         mnReadBufferPos = 0;
     708           0 :         mnReadBufferLength = 0;
     709             :     }
     710           0 : }
     711             : 
     712           0 : WPXInputStream *WPXSvInputStreamImpl::createWPXStream(const SotStorageStreamRef &rxStorage)
     713             : {
     714           0 :     if (rxStorage.Is())
     715             :     {
     716           0 :         Reference < XInputStream > xContents(new utl::OSeekableInputStreamWrapper( rxStorage ));
     717           0 :         return new WPXSvInputStream( xContents );
     718             :     }
     719           0 :     return 0;
     720             : }
     721             : 
     722           0 : WPXInputStream *WPXSvInputStreamImpl::createWPXStream(const Reference<XInputStream> &rxStream)
     723             : {
     724           0 :     if (rxStream.is())
     725           0 :         return new WPXSvInputStream( rxStream );
     726             :     else
     727           0 :         return 0;
     728             : }
     729             : 
     730           0 : bool WPXSvInputStreamImpl::isOLE()
     731             : {
     732           0 :     if (!mbCheckedOLE)
     733             :     {
     734             :         assert(0 == mxSeekable->getPosition());
     735             : 
     736           0 :         boost::scoped_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( mxStream ));
     737           0 :         if (pStream && SotStorage::IsOLEStorage(pStream.get()))
     738           0 :             mpOLEStorage.reset(new OLEStorageImpl());
     739             : 
     740           0 :         mbCheckedOLE = true;
     741             :     }
     742             : 
     743           0 :     return bool(mpOLEStorage);
     744             : }
     745             : 
     746           0 : bool WPXSvInputStreamImpl::isZip()
     747             : {
     748           0 :     if (!mbCheckedZip)
     749             :     {
     750             :         assert(0 == mxSeekable->getPosition());
     751             : 
     752             :         try
     753             :         {
     754           0 :             Sequence<Any> aArgs(1);
     755           0 :             aArgs[0] <<= mxStream;
     756             : 
     757           0 :             const Reference<XComponentContext> xContext(comphelper::getProcessComponentContext(), UNO_QUERY_THROW);
     758             :             const Reference<packages::zip::XZipFileAccess2> xZip(
     759           0 :                     xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.packages.zip.ZipFileAccess", aArgs, xContext),
     760           0 :                     UNO_QUERY_THROW);
     761           0 :             mpZipStorage.reset(new ZipStorageImpl(xZip));
     762             :         }
     763           0 :         catch (const Exception &)
     764             :         {
     765             :             // ignore
     766             :         }
     767             : 
     768           0 :         mbCheckedZip = true;
     769             :     }
     770             : 
     771           0 :     return bool(mpZipStorage);
     772             : }
     773             : 
     774           0 : void WPXSvInputStreamImpl::ensureOLEIsInitialized()
     775             : {
     776             :     assert(mpOLEStorage);
     777             : 
     778           0 :     if (!mpOLEStorage->mbInitialized)
     779           0 :         mpOLEStorage->initialize(utl::UcbStreamHelper::CreateStream( mxStream ));
     780           0 : }
     781             : 
     782           0 : void WPXSvInputStreamImpl::ensureZipIsInitialized()
     783             : {
     784             :     assert(mpZipStorage);
     785             : 
     786           0 :     if (!mpZipStorage->mbInitialized)
     787           0 :         mpZipStorage->initialize();
     788           0 : }
     789             : 
     790           0 : WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) :
     791           0 :     mpImpl(new WPXSvInputStreamImpl(xStream))
     792             : {
     793           0 : }
     794             : 
     795           0 : WPXSvInputStream::~WPXSvInputStream()
     796             : {
     797           0 :    if (mpImpl)
     798           0 :        delete mpImpl;
     799           0 : }
     800             : 
     801             : #define BUFFER_MAX 65536
     802             : 
     803           0 : const unsigned char *WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead)
     804             : {
     805           0 :     numBytesRead = 0;
     806             : 
     807           0 :     if (numBytes == 0 || numBytes > (std::numeric_limits<unsigned long>::max)()/2)
     808           0 :         return 0;
     809             : 
     810           0 :     if (mpImpl->mpReadBuffer)
     811             :     {
     812           0 :         if ((mpImpl->mnReadBufferPos + numBytes > mpImpl->mnReadBufferPos) && (mpImpl->mnReadBufferPos + numBytes <= mpImpl->mnReadBufferLength))
     813             :         {
     814           0 :             const unsigned char *pTmp = mpImpl->mpReadBuffer + mpImpl->mnReadBufferPos;
     815           0 :             mpImpl->mnReadBufferPos += numBytes;
     816           0 :             numBytesRead = numBytes;
     817           0 :             return pTmp;
     818             :         }
     819             : 
     820           0 :         mpImpl->invalidateReadBuffer();
     821             :     }
     822             : 
     823           0 :     unsigned long curpos = (unsigned long) mpImpl->tell();
     824           0 :     if (curpos == (unsigned long)-1)  // returned ERROR
     825           0 :         return 0;
     826             : 
     827           0 :     if ((curpos + numBytes < curpos) /*overflow*/ ||
     828           0 :             (curpos + numBytes >= (sal_uInt64)mpImpl->mnLength))  /*reading more than available*/
     829             :     {
     830           0 :         numBytes = mpImpl->mnLength - curpos;
     831             :     }
     832             : 
     833           0 :     if (numBytes < BUFFER_MAX)
     834             :     {
     835           0 :         if (BUFFER_MAX < mpImpl->mnLength - curpos)
     836           0 :             mpImpl->mnReadBufferLength = BUFFER_MAX;
     837             :         else /* BUFFER_MAX >= mpImpl->mnLength - curpos */
     838           0 :             mpImpl->mnReadBufferLength = mpImpl->mnLength - curpos;
     839             :     }
     840             :     else
     841           0 :         mpImpl->mnReadBufferLength = numBytes;
     842             : 
     843           0 :     unsigned long tmpNumBytes(0);
     844           0 :     mpImpl->mpReadBuffer = const_cast<unsigned char*>(mpImpl->read(mpImpl->mnReadBufferLength, tmpNumBytes));
     845           0 :     if (tmpNumBytes != mpImpl->mnReadBufferLength)
     846           0 :         mpImpl->mnReadBufferLength = tmpNumBytes;
     847             : 
     848           0 :     mpImpl->mnReadBufferPos = 0;
     849           0 :     if (!mpImpl->mnReadBufferLength)
     850           0 :         return 0;
     851             : 
     852           0 :     numBytesRead = numBytes;
     853             : 
     854           0 :     mpImpl->mnReadBufferPos += numBytesRead;
     855           0 :     return const_cast<const unsigned char *>(mpImpl->mpReadBuffer);
     856             : }
     857             : 
     858           0 : long WPXSvInputStream::tell()
     859             : {
     860           0 :     long retVal = mpImpl->tell();
     861           0 :     return retVal - (long)mpImpl->mnReadBufferLength + (long)mpImpl->mnReadBufferPos;
     862             : }
     863             : 
     864           0 : int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType)
     865             : {
     866           0 :     sal_Int64 tmpOffset = offset;
     867           0 :     if (seekType == WPX_SEEK_CUR)
     868           0 :         tmpOffset += tell();
     869           0 :     if (seekType == WPX_SEEK_END)
     870           0 :         tmpOffset += mpImpl->mnLength;
     871             : 
     872           0 :     int retVal = 0;
     873           0 :     if (tmpOffset < 0)
     874             :     {
     875           0 :         tmpOffset = 0;
     876           0 :         retVal = -1;
     877             :     }
     878           0 :     if (tmpOffset > mpImpl->mnLength)
     879             :     {
     880           0 :         tmpOffset = mpImpl->mnLength;
     881           0 :         retVal = -1;
     882             :     }
     883             : 
     884           0 :     if (tmpOffset < mpImpl->tell() && (unsigned long)tmpOffset >= (unsigned long)mpImpl->tell() - mpImpl->mnReadBufferLength)
     885             :     {
     886           0 :         mpImpl->mnReadBufferPos = (unsigned long)(tmpOffset + (long) mpImpl->mnReadBufferLength - (long) mpImpl->tell());
     887           0 :         return retVal;
     888             :     }
     889             : 
     890           0 :     mpImpl->invalidateReadBuffer();
     891             : 
     892           0 :     if (mpImpl->seek(tmpOffset))
     893           0 :         return -1;
     894           0 :     return retVal;
     895             : }
     896             : 
     897           0 : bool WPXSvInputStream::isEnd()
     898             : {
     899           0 :     return mpImpl->isEnd() && mpImpl->mnReadBufferPos == mpImpl->mnReadBufferLength;
     900             : }
     901             : 
     902           0 : bool WPXSvInputStream::isStructured()
     903             : {
     904           0 :     mpImpl->invalidateReadBuffer();
     905           0 :     return mpImpl->isStructured();
     906             : }
     907             : 
     908           0 : unsigned WPXSvInputStream::subStreamCount()
     909             : {
     910           0 :     mpImpl->invalidateReadBuffer();
     911           0 :     return mpImpl->subStreamCount();
     912             : }
     913             : 
     914           0 : const char *WPXSvInputStream::subStreamName(const unsigned id)
     915             : {
     916           0 :     mpImpl->invalidateReadBuffer();
     917           0 :     return mpImpl->subStreamName(id);
     918             : }
     919             : 
     920           0 : bool WPXSvInputStream::existsSubStream(const char *const name)
     921             : {
     922           0 :     mpImpl->invalidateReadBuffer();
     923           0 :     return mpImpl->existsSubStream(name);
     924             : }
     925             : 
     926           0 : WPXInputStream *WPXSvInputStream::getSubStreamByName(const char *name)
     927             : {
     928           0 :     mpImpl->invalidateReadBuffer();
     929           0 :     return mpImpl->getSubStreamByName(name);
     930             : }
     931             : 
     932           0 : WPXInputStream *WPXSvInputStream::getSubStreamById(const unsigned id)
     933             : {
     934           0 :     mpImpl->invalidateReadBuffer();
     935           0 :     return mpImpl->getSubStreamById(id);
     936             : }
     937             : 
     938           0 : bool WPXSvInputStream::atEOS()
     939             : {
     940           0 :     return isEnd();
     941             : }
     942             : 
     943           0 : bool WPXSvInputStream::isOLEStream()
     944             : {
     945           0 :     return isStructured();
     946             : }
     947             : 
     948           0 : WPXInputStream *WPXSvInputStream::getDocumentOLEStream(const char *name)
     949             : {
     950           0 :     return getSubStreamByName(name);
     951             : }
     952             : 
     953             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10