[ooo-build-commit] patches/dev300

Kohei Yoshida kohei at kemper.freedesktop.org
Wed Jul 8 15:12:30 PDT 2009


 patches/dev300/apply                           |    3 
 patches/dev300/calc-external-ref-path-fix.diff |  291 +++++++++++++++++++++++++
 2 files changed, 294 insertions(+)

New commits:
commit afd5a40e2798fd6950e03218b7a8527ee96a255b
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed Jul 8 18:09:34 2009 -0400

    Fix incorrect absolute path generation for external doc URI.
    
    * patches/dev300/apply:
    * patches/dev300/calc-external-ref-path-fix.diff: fixed a number
      of bugs related to external references handling. (i#103317)

diff --git a/patches/dev300/apply b/patches/dev300/apply
index d25a1bd..fa9fde9 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -3162,6 +3162,9 @@ cws-ooxml03-enable-docx.diff
 # cell's dirty flag upon loading.
 calc-dirty-cells-after-load-fix.diff, n#491898, kohei
 
+# fix incorrect URI path generation for external references.
+calc-external-ref-path-fix.diff, i#103347, kohei
+
 [ CalcRowLimit ]
 # The work to increase Calc's row size limit, and any work associated with it.
 SectionOwner => kohei
diff --git a/patches/dev300/calc-external-ref-path-fix.diff b/patches/dev300/calc-external-ref-path-fix.diff
new file mode 100644
index 0000000..94b6679
--- /dev/null
+++ b/patches/dev300/calc-external-ref-path-fix.diff
@@ -0,0 +1,291 @@
+diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
+index 1ca3bac..b9bbaa9 100644
+--- sc/inc/externalrefmgr.hxx
++++ sc/inc/externalrefmgr.hxx
+@@ -403,10 +403,13 @@ public:
+     /** Source document meta-data container. */
+     struct SrcFileData
+     {
+-        String maFileName;
++        String maFileName;      /// original file name as loaded from the file.
++        String maRealFileName;  /// file name created from the relative name.
+         String maRelativeName;
+         String maFilterName;
+         String maFilterOptions;
++
++        void maybeCreateRealFileName(const String& rOwnDocName);
+     };
+ 
+ public:
+@@ -551,7 +554,7 @@ public:
+      */
+     void convertToAbsName(String& rFile) const;
+     sal_uInt16 getExternalFileId(const String& rFile);
+-    const String* getExternalFileName(sal_uInt16 nFileId) const;
++    const String* getExternalFileName(sal_uInt16 nFileId);
+     bool hasExternalFile(sal_uInt16 nFileId) const;
+     bool hasExternalFile(const String& rFile) const;
+     const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
+@@ -560,8 +563,15 @@ public:
+     const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
+     void refreshNames(sal_uInt16 nFileId);
+     void breakLink(sal_uInt16 nFileId);
+-    void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
++    void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter);
+ 
++    /** 
++     * Set a relative file path for the specified file ID.  Note that the 
++     * caller must ensure that the passed URL is a valid relative URL. 
++     *
++     * @param nFileId file ID for an external document
++     * @param rRelUrl relative URL
++     */
+     void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
+ 
+     /**
+@@ -581,9 +591,12 @@ public:
+     /**
+      * Re-generates relative names for all stored source files.  This is
+      * necessary when exporting to an ods document, to ensure that all source
+-     * files have their respective relative names for xlink:href export.
++     * files have their respective relative names for xlink:href export. 
++     *  
++     * @param rBaseFileUrl Absolute URL of the content.xml fragment of the 
++     *                     document being exported.
+      */
+-    void resetSrcFileData();
++    void resetSrcFileData(const String& rBaseFileUrl);
+ 
+     /** 
+      * Update a single referencing cell position.
+@@ -650,6 +663,19 @@ private:
+ 
+     void maybeLinkExternalFile(sal_uInt16 nFileId);
+ 
++    /** 
++     * Try to create a "real" file name from the relative path.  The original
++     * file name may not point to the real document when the referencing and 
++     * referenced documents have been moved. 
++     *  
++     * For the real file name to be created, the relative name should not be 
++     * empty before calling this method, or the real file name will not be 
++     * created. 
++     *
++     * @param nFileId file ID for an external document
++     */
++    void maybeCreateRealFileName(sal_uInt16 nFileId);
++
+     bool compileTokensByCell(const ScAddress& rCell);
+ 
+     /**
+diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
+index 0f8c609..dd246b6 100644
+--- sc/source/filter/xml/xmlexprt.cxx
++++ sc/source/filter/xml/xmlexprt.cxx
+@@ -3462,7 +3462,7 @@ void ScXMLExport::WriteExternalRefCaches()
+         return;
+ 
+     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+-    pRefMgr->resetSrcFileData();
++    pRefMgr->resetSrcFileData(GetOrigFileName());
+     sal_uInt16 nCount = pRefMgr->getExternalFileCount();
+     for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
+     {
+diff --git sc/source/filter/xml/xmlexternaltabi.cxx sc/source/filter/xml/xmlexternaltabi.cxx
+index ca94d26..7ddc42e 100644
+--- sc/source/filter/xml/xmlexternaltabi.cxx
++++ sc/source/filter/xml/xmlexternaltabi.cxx
+@@ -100,6 +100,27 @@ SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
+     return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+ }
+ 
++/** 
++ * Make sure the URL is a valid relative URL, mainly to avoid storing 
++ * absolute URL as relative URL by accident.  For now, we only check the 
++ * first two characters which are assumed to be always '..', because the 
++ * relative URL for an external document is always in reference to the 
++ * content.xml fragment of the original document. 
++ */
++static bool lcl_isValidRelativeURL(const OUString& rUrl)
++{
++    const sal_Unicode* p = rUrl.getStr();
++    sal_Int32 n = rUrl.getLength();
++    for (sal_Int32 i = 0; i < n; ++i)
++    {
++        sal_Unicode c = p[i];
++        if (i < 2 && c != '.')
++            // the path must begin with '..'
++            return false;
++    }
++    return true;
++}
++
+ void ScXMLExternalRefTabSourceContext::EndElement()
+ {
+     ScDocument* pDoc = mrScImport.GetDocument();
+@@ -107,7 +128,7 @@ void ScXMLExternalRefTabSourceContext::EndElement()
+         return;
+ 
+     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+-    if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
++    if (lcl_isValidRelativeURL(maRelativeUrl))
+         pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
+     pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
+ }
+diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+index 7032b2d..b831e93 100644
+--- sc/source/ui/docshell/externalrefmgr.cxx
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -989,7 +989,7 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
+     else
+     {
+         // The source document has changed.
+-        pMgr->switchSrcFile(mnFileId, aFile);
++        pMgr->switchSrcFile(mnFileId, aFile, aFilter);
+         maFilterName = aFilter;
+     }
+ }
+@@ -1824,24 +1824,17 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
+     if (!pFileData)
+         return NULL;
+ 
++    // Always load the document by using the path created from the relative
++    // path.  If the referenced document is not there, simply exit.  The
++    // original file name should be used only when the relative path is not
++    // given.
+     String aFile = pFileData->maFileName;
++    maybeCreateRealFileName(nFileId);
++    if (pFileData->maRealFileName.Len())
++        aFile = pFileData->maRealFileName;
++    
+     if (!isFileLoadable(aFile))
+-    {
+-        // The original file path is not loadable.  Try the relative path.
+-        // Note that the path is relative to the content.xml substream which
+-        // is one-level higher than the file itself.
+-
+-        if (!pFileData->maRelativeName.Len())
+-            return NULL;
+-
+-        INetURLObject aBaseURL(getOwnDocumentName());
+-        aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+-        bool bWasAbs = false;
+-        aFile = aBaseURL.smartRel2Abs(pFileData->maRelativeName, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
+-        if (!isFileLoadable(aFile))
+-            // Ok, I've tried both paths but no success.  Bail out.
+-            return NULL;
+-    }
++        return NULL;
+ 
+     String aOptions;
+     ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
+@@ -1893,6 +1886,9 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
+ 
+ bool ScExternalRefManager::isFileLoadable(const String& rFile) const
+ {
++    if (!rFile.Len())
++        return false;
++
+     if (isOwnDocument(rFile))
+         return false;
+ 
+@@ -1927,6 +1923,32 @@ void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
+     maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
+ }
+ 
++void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
++{
++    if (!maRelativeName.Len())
++        // No relative path given.  Nothing to do.
++        return;
++
++    if (maRealFileName.Len())
++        // Real file name already created.  Nothing to do.
++        return;
++
++    // Formulate the absolute file path from the relative path.
++    const String& rRelPath = maRelativeName;
++    INetURLObject aBaseURL(rOwnDocName);
++    aBaseURL.insertName(OUString::createFromAscii("content.xml"));
++    bool bWasAbs = false;
++    maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
++}
++
++void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
++{
++    if (nFileId >= maSrcFiles.size())
++        return;
++
++    maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
++}
++
+ bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
+ {
+     ScBaseCell* pCell;
+@@ -1997,12 +2019,17 @@ sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
+     return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
+ }
+ 
+-const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
++const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId)
+ {
+     if (nFileId >= maSrcFiles.size())
+         return NULL;
+ 
+-    return &maSrcFiles[nFileId].maFileName;
++    maybeCreateRealFileName(nFileId);
++
++    if (maSrcFiles[nFileId].maRealFileName.Len())
++        return &maSrcFiles[nFileId].maRealFileName;
++    else
++        return &maSrcFiles[nFileId].maFileName;
+ }
+ 
+ bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
+@@ -2071,10 +2098,17 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
+     notifyAllLinkListeners(nFileId, LINK_BROKEN);
+ }
+ 
+-void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
++void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter)
+ {
+     maSrcFiles[nFileId].maFileName = rNewFile;
+     maSrcFiles[nFileId].maRelativeName.Erase();
++    maSrcFiles[nFileId].maRealFileName.Erase();
++    if (!maSrcFiles[nFileId].maFilterName.Equals(rNewFilter))
++    {
++        // Filter type has changed.
++        maSrcFiles[nFileId].maFilterName = rNewFilter;
++        maSrcFiles[nFileId].maFilterOptions.Erase();
++    }
+     refreshNames(nFileId);
+ }
+ 
+@@ -2108,19 +2142,18 @@ bool ScExternalRefManager::hasExternalData() const
+     return !maSrcFiles.empty();
+ }
+ 
+-void ScExternalRefManager::resetSrcFileData()
++void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl)
+ {
+-    INetURLObject aBaseURL(getOwnDocumentName());
+-    aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+-    String aBaseUrlStr = aBaseURL.GetMainURL(INetURLObject::NO_DECODE);
+     for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+           itr != itrEnd; ++itr)
+     {
+-        if (!itr->maRelativeName.Len())
+-        {
+-            itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
+-                aBaseUrlStr, itr->maFileName);
+-        }
++        // Re-generate relative file name from the absolute file name.
++        String aAbsName = itr->maRealFileName;
++        if (!aAbsName.Len())
++            aAbsName = itr->maFileName;
++
++        itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
++            rBaseFileUrl, aAbsName);
+     }
+ }
+ 


More information about the ooo-build-commit mailing list