Commits

Caolán McNamara  committed 9742419

cmcfixes79: #i114485#: use shared msfilter parser for HLINKS and override hyperlinks with DocumentSummaryStream entries when they exist

  • Participants
  • Parent commits 9400815

Comments (0)

Files changed (6)

File sw/source/filter/ww8/wrtww8.cxx

 #include <vcl/salbtype.hxx>
 #include <sot/storage.hxx>
 #include <svl/zformat.hxx>
-#include <sfx2/docinf.hxx>
+#include <filter/msfilter/docinf.hxx>
 #include <editeng/tstpitem.hxx>
 #include <svx/svdmodel.hxx>
 #include <svx/svdpage.hxx>
                 ::boost::shared_ptr<GDIMetaFile> pMetaFile =
                     pDocShell->GetPreviewMetaFile (sal_False);
                 uno::Sequence<sal_uInt8> metaFile(
-                    sfx2::convertMetaFile(pMetaFile.get()));
-                sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
+                    convertMetaFile(pMetaFile.get()));
+                SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
             }
             else
-                sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
+                SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
         }
     }
 }

File sw/source/filter/ww8/ww8par.cxx

 #include <rtl/tencinfo.h>
 
 #include <sot/storage.hxx>
-#include <sfx2/docinf.hxx>
 #include <sfx2/docfile.hxx>
 #include <tools/urlobj.hxx>
 #include <unotools/tempfile.hxx>
 
 #include "WW8Sttbf.hxx"
 #include "WW8FibData.hxx"
+#include "propread.hxx"
 #define MM_250 1417             // WW-Default fuer Hor. Seitenraender: 2.5 cm
 #define MM_200 1134             // WW-Default fuer u.Seitenrand: 2.0 cm
 
         DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
 
         if (xDocProps.is()) {
-            sfx2::LoadOlePropertySet(xDocProps, pStg);
+            LoadOlePropertySet(xDocProps, pStg, &aHyperLinks);
         }
     }
 }
 
     pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
 
+    pSBase->applyDocumentSummaryInformationHyperlinks(aHyperLinks);
+
     static const SvxExtNumType eNumTA[16] =
     {
         SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,

File sw/source/filter/ww8/ww8par.hxx

     */
     std::vector<const SwCharFmt*> aRubyCharFmts;
 
+    /*
+    vector of hyperlinks from the DocumentSummaryInformation that may override
+    the HYPERLINK field urls.
+    */
+    std::vector<VtHyperlink> aHyperLinks;
+
     WW8PostProcessAttrsInfo * mpPostProcessAttrsInfo;
 
     WW8Fib* pWwFib;

File sw/source/filter/ww8/ww8par5.cxx

     return FLD_TEXT;
  }
 
-eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, String& rStr )
+eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* pF, String& rStr )
 {
 #if defined(WW_NATIVE_TOC)
     if (1) {
         }
     }
 
+    //#i114485 URLs in the DocumentSummaryInformation stream override the
+    //inline field code!
+    if (pF->pHyperLink)
+    {
+        sURL = URIHelper::SmartRel2Abs(
+            INetURLObject(sBaseURL), pF->pHyperLink->hlink1, Link(), false);
+        sMark = pF->pHyperLink->hlink2;
+    }
+
     // das Resultat uebernehmen
     ASSERT((sURL.Len() || sMark.Len()), "WW8: Empty URL")
 

File sw/source/filter/ww8/ww8scan.cxx

 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
 #include "ww8scan.hxx"
 
+#include "fields.hxx"
 
 #include <functional>
 #include <algorithm>
     pBook = new WW8PLCFx_Book(pTblSt, *pWwFib);
 }
 
+bool WW8ScannerBase::getFirstHyperLink(HyperLinkIterator &rIter)
+{
+    rIter.pFld = pFldPLCF;
+    rIter.nIndex = rIter.pFld->GetLastHyperlinkIdx();
+
+    if (rIter.nIndex != 0xFFFFFFFF)
+        return true;
+
+    return advanceHyperLink(rIter);
+}
+
+bool WW8ScannerBase::advanceHyperLink(HyperLinkIterator &rIter)
+{
+    while (rIter.pFld)
+    {
+        if (rIter.nIndex != 0xFFFFFFFF)
+            rIter.nIndex = rIter.pFld->GetPrevHyperlinkIdx(rIter.nIndex);
+
+        if (rIter.nIndex == 0xFFFFFFFF)
+        {
+            if (rIter.pFld == pFldPLCF)
+                rIter.pFld = pFldFtnPLCF;
+            else if (rIter.pFld == pFldFtnPLCF)
+                rIter.pFld = pFldHdFtPLCF;
+            else if (rIter.pFld == pFldHdFtPLCF)
+                rIter.pFld = pFldAndPLCF;
+            else if (rIter.pFld == pFldAndPLCF)
+                rIter.pFld = pFldEdnPLCF;
+            else if (rIter.pFld == pFldEdnPLCF)
+                rIter.pFld = pFldTxbxPLCF;
+            else if (rIter.pFld == pFldTxbxPLCF)
+                rIter.pFld = pFldTxbxHdFtPLCF;
+            else if (rIter.pFld == pFldTxbxHdFtPLCF)
+                rIter.pFld = NULL;
+
+            if (rIter.pFld)
+                rIter.nIndex = rIter.pFld->GetLastHyperlinkIdx();
+        }
+
+        if (rIter.nIndex != 0xFFFFFFFF)
+            break;
+    }
+
+    return rIter.pFld ? true : false;
+}
+
+
+void HyperLinkIterator::OverrideLink(const VtHyperlink &rHyperLink)
+{
+    pFld->OverrideLink(nIndex, rHyperLink);
+}
+
+void WW8ScannerBase::applyDocumentSummaryInformationHyperlinks(const std::vector<VtHyperlink> &rHyperLinks)
+{
+    /*
+    2.4.7 Application Data For VtHyperlink The following algorithm specifies how
+    hyperlink properties, as specified in [MS-OSHARED] section 2.3.3.1.18, are
+    associated with content in a document construct their dwApp field value.
+      * If the hyperlink is associated with an OfficeArtFSP shape, as specified in
+        [MS-ODRAW] section 2.2.39, the dwApp value MUST be 0xFFFFFFFF. Otherwise
+        the hyperlink MUST be associated with a picture, an external link to a
+        picture source, or other document content.
+      * If the hyperlink is associated directly with a picture, as opposed to the
+        hyperlink field associated with the picture, or an external link to a
+        picture source, the dwApp value MUST be set to an FcCompressed structure
+        that specifies the starting offset of the field result in the WordDocument
+        Stream associated with the picture. For further specification on field
+        results, see PlcFld.
+      * If the hyperlink is associated with any other type of document content,
+        including the hyperlink field of a WordArt shape or picture, the dwApp
+        value MUST be set to an unsigned 4-byte integer that specifies the index
+        into a PlcFld. The specified PlcFld item corresponds to the field begin
+        character of the hyperlink field in the document content associated with
+        the hyperlink property.
+      * The hyperlink properties that have dwApp set to an index into a PlcFld MUST
+        conform to a specific ordering relative to each other when written. They
+        MUST be written within the property set hyperlink property array
+        VtHyperlinks, as specified in [MS-OSHARED] section 2.3.3.1.21, grouped
+        according to the document PlcFld to which the indices apply, in the
+        following order:
+
+            Main Document links
+            Footnote Document links
+            Header Document links
+            Comment Document links
+            Endnote Document links
+            Textbox Document links
+            Header Textbox Document links
+
+        Within these groupings the hyperlink properties MUST be ordered from
+        largest index to smallest index.
+    */
+
+    HyperLinkIterator aHyperLinkIter;
+    if (!getFirstHyperLink(aHyperLinkIter))
+        return;
+
+    std::vector<VtHyperlink>::const_iterator aEnd = rHyperLinks.end();
+    for (std::vector<VtHyperlink>::const_iterator aI = rHyperLinks.begin(); aI != aEnd; ++aI)
+    {
+        if (aI->dwApp == 0xFFFFFFFF)
+            continue;
+        //dwInfo is 5 for HYPERLINK fields
+        if (aI->dwInfo != 5)
+            continue;
+        ASSERT( aHyperLinkIter->GetDwApp() == aI->dwApp,
+            "DocumentSummaryInformation Links inconsistency, ignoring remainder");
+
+        if (aHyperLinkIter.GetDwApp() != aI->dwApp)
+            break;
+
+        aHyperLinkIter.OverrideLink(*aI);
+        if (!advanceHyperLink(aHyperLinkIter))
+            break;
+    }
+}
+
 WW8ScannerBase::~WW8ScannerBase()
 {
     DeletePieceTable();
 
     rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0;
 
+    rF.pHyperLink = NULL;
+
     if( !rPLCF.Get( rF.nSCode, pData ) )             // Ende des PLCFspecial ?
         goto Err;
 
     bool bOk = WW8GetFieldPara(*pPLCF, rF);
 
     pPLCF->SetIdx(n);
+
+    if (bOk)
+    {
+        std::map<ULONG, VtHyperlink>::const_iterator aI = maHyperLinks.find(nIdx);
+        if (aI != maHyperLinks.end())
+            rF.pHyperLink = &(aI->second);
+    }
+
     return bOk;
 }
 
+ULONG WW8PLCFx_FLD::GetLastHyperlinkIdx() const
+{
+    ULONG nRet = 0xFFFFFFFF;
+
+    if (!pPLCF)
+        return nRet;
+
+    long nIMax = pPLCF->GetIMax();
+
+    nRet = GetPrevHyperlinkIdx(nIMax);
+
+    return nRet;
+}
+
+ULONG WW8PLCFx_FLD::GetPrevHyperlinkIdx(ULONG nIndex) const
+{
+    ULONG nRet = 0xFFFFFFFF;
+
+    if (!pPLCF)
+        return nRet;
+
+    USHORT nID = 0;
+
+    ULONG nOldIdx = pPLCF->GetIdx();
+
+    for (long i = nIndex-1; i >= 0; --i)
+    {
+        void* pData;
+
+        pPLCF->SetIdx(i);
+
+        WW8_CP nSCode;
+        if (!pPLCF->Get(nSCode, pData))
+            break;
+
+        if((((BYTE*)pData)[0] & 0x1f ) == 0x13 )
+            nID = ((BYTE*)pData)[1];
+
+        if (nID == ww::eHYPERLINK)
+        {
+            nRet = pPLCF->GetIdx();
+            break;
+        }
+    }
+
+    pPLCF->SetIdx( nOldIdx );
+
+    return nRet;
+
+}
+
 //-----------------------------------------
 //      class WW8PLCF_Book
 //-----------------------------------------

File sw/source/filter/ww8/ww8scan.hxx

 #include <tools/datetime.hxx>
 #include <tools/stream.hxx>
 #include <tools/string.hxx>
+#include <filter/msfilter/docinf.hxx>
 #include <errhdl.hxx>       // ASSERT()
 #include "hash_wrap.hxx"
 #include "sortedarray.hxx"
 
 #include <unomid.h>
 
+#include <map>
+
 #define APPEND_CONST_ASC(s) AppendAscii(RTL_CONSTASCII_STRINGPARAM(s))
 #define ASSIGN_CONST_ASC(s) AssignAscii(RTL_CONSTASCII_STRINGPARAM(s))
 #define CREATE_CONST_ASC(s) String::CreateFromAscii( \
 
 struct WW8FieldDesc
 {
+    const VtHyperlink *pHyperLink; ///< Override link from DocumentSummaryInformation
     long nLen;              ///< Gesamtlaenge ( zum Text ueberlesen )
     WW8_CP nSCode;          ///< Anfang Befehlscode
     WW8_CP nLCode;          ///< Laenge
 class WW8PLCFx_FLD : public WW8PLCFx
 {
 private:
+    std::map<ULONG, VtHyperlink> maHyperLinks;
     WW8PLCFspecial* pPLCF;
     const WW8Fib& rFib;
     //No copying
     bool StartPosIsFieldStart();
     bool EndPosIsFieldEnd();
     bool GetPara(long nIdx, WW8FieldDesc& rF);
+
+    ULONG GetLastHyperlinkIdx() const;
+    ULONG GetPrevHyperlinkIdx(ULONG nIndex) const;
+    void OverrideLink(ULONG nIndex, const VtHyperlink &rHyperLink) { maHyperLinks[nIndex] = rHyperLink; }
 };
 
 enum eBookStatus { BOOK_NORMAL = 0, BOOK_IGNORE = 0x1, BOOK_FIELD = 0x2 };
 
 #endif // !DUMP
 
+struct HyperLinkIterator
+{
+    WW8PLCFx_FLD *pFld;
+    ULONG nIndex;
+    ULONG GetDwApp() const { return nIndex; }
+    void OverrideLink(const VtHyperlink &rHyperLink);
+};
+
 class WW8ScannerBase
 {
 friend WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(ww::WordVersion eVersion, 
 
     WW8PLCFpcd* OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF );
     void DeletePieceTable();
+
+    bool getFirstHyperLink(HyperLinkIterator &rIter);
+    bool advanceHyperLink(HyperLinkIterator &rIter);
 public:
     WW8ScannerBase( SvStream* pSt, SvStream* pTblSt, SvStream* pDataSt,
         const WW8Fib* pWwF );
     xub_StrLen WW8ReadString(SvStream& rStrm, String& rStr, WW8_CP nAktStartCp, 
         long nTotalLen, rtl_TextEncoding eEnc ) const;
 
+    void applyDocumentSummaryInformationHyperlinks(const std::vector<VtHyperlink> &rHyperLinks);
 };
 
 /** FIB - the File Information Block