tdf#159474: fix handling of pre-set RepairPackage property

StorageFilterDetect::detect had a wrong logic here, only honoring
repair request in case it haappened interactively inside it. The
pre-existing RepairPackage set to true was treated as "do not try
to repair".

Change-Id: I3fb63a5d72097a79977e8ed734f8e69dd2ea999a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162858
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162867
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
diff --git a/filter/source/storagefilterdetect/filterdetect.cxx b/filter/source/storagefilterdetect/filterdetect.cxx
index c73355e..1d0d755 100644
--- a/filter/source/storagefilterdetect/filterdetect.cxx
+++ b/filter/source/storagefilterdetect/filterdetect.cxx
@@ -121,44 +121,44 @@ OUString SAL_CALL StorageFilterDetect::detect(uno::Sequence<beans::PropertyValue
        if ( ( aWrap.TargetException >>= aZipException ) && !aRequestedTypeName.isEmpty() )
        {
            // The package is a broken one.
            uno::Reference< task::XInteractionHandler > xInteraction =
                aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER, uno::Reference< task::XInteractionHandler >() );

            if ( xInteraction.is() )
            INetURLObject aParser(
                aMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_URL, OUString()));
            OUString aDocumentTitle = aParser.getName(INetURLObject::LAST_SEGMENT, true,
                                                      INetURLObject::DecodeMechanism::WithCharset);
            bool bRepairPackage = aMediaDesc.getUnpackedValueOrDefault("RepairPackage", false);
            // fdo#46310 Don't ask to repair if the user rejected it once.
            if (!bRepairPackage && aMediaDesc.getUnpackedValueOrDefault("RepairAllowed", true))
            {
                INetURLObject aParser( aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL, OUString() ) );
                OUString aDocumentTitle = aParser.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
                bool bRepairPackage = aMediaDesc.getUnpackedValueOrDefault( "RepairPackage", false );
                // fdo#46310 Don't try to repair if the user rejected it once.
                bool bRepairAllowed = aMediaDesc.getUnpackedValueOrDefault( "RepairAllowed", true );
                uno::Reference< task::XInteractionHandler > xInteraction =
                    aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER, uno::Reference< task::XInteractionHandler >() );

                if ( !bRepairPackage && bRepairAllowed )
                if ( xInteraction.is() )
                {
                    // Ask the user whether he wants to try to repair.
                    RequestPackageReparation aRequest( aDocumentTitle );
                    xInteraction->handle( aRequest.GetRequest() );

                    if ( aRequest.isApproved() )
                    {
                        aTypeName = aRequestedTypeName;
                        // lok: we want to overwrite file in jail, so don't use template flag
                        const bool bIsLOK = comphelper::LibreOfficeKit::isActive();
                        aMediaDesc[MediaDescriptor::PROP_DOCUMENTTITLE] <<= aDocumentTitle;
                        aMediaDesc[MediaDescriptor::PROP_ASTEMPLATE] <<= !bIsLOK;
                        aMediaDesc["RepairPackage"] <<= true;
                    }
                    else
                    RequestPackageReparation aRequest(aDocumentTitle);
                    xInteraction->handle(aRequest.GetRequest());
                    bRepairPackage = aRequest.isApproved();
                    if (!bRepairPackage)
                    {
                        // Repair either not allowed or not successful.
                        NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
                        xInteraction->handle( aNotifyRequest.GetRequest() );
                        aMediaDesc["RepairAllowed"] <<= false;
                    }

                    // Write the changes back.
                    aMediaDesc >> rDescriptor;
                }
            }
            if (bRepairPackage)
            {
                aTypeName = aRequestedTypeName;
                // lok: we want to overwrite file in jail, so don't use template flag
                const bool bIsLOK = comphelper::LibreOfficeKit::isActive();
                aMediaDesc[MediaDescriptor::PROP_DOCUMENTTITLE] <<= aDocumentTitle;
                aMediaDesc[MediaDescriptor::PROP_ASTEMPLATE] <<= !bIsLOK;
                aMediaDesc["RepairPackage"] <<= true;
            }

            // Write the changes back.
            aMediaDesc >> rDescriptor;
        }
    }
    catch( uno::RuntimeException& )
diff --git a/sw/qa/extras/odfimport/data/unreferenced_stream.odt b/sw/qa/extras/odfimport/data/unreferenced_stream.odt
new file mode 100644
index 0000000..0cdba0d
--- /dev/null
+++ b/sw/qa/extras/odfimport/data/unreferenced_stream.odt
Binary files differ
diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx
index 6ccc8cc..168de4f 100644
--- a/sw/qa/extras/odfimport/odfimport.cxx
+++ b/sw/qa/extras/odfimport/odfimport.cxx
@@ -1534,5 +1534,20 @@ CPPUNIT_TEST_FIXTURE(Test, testEmptyTrailingSpans)
    CPPUNIT_ASSERT_DOUBLES_EQUAL(184, height2, 1); // allow a bit of room for rounding just in case
}

CPPUNIT_TEST_FIXTURE(Test, testBrokenPackage_Tdf159474)
{
    // Given an invalid ODF having a stream not referenced in manifest.xml
    const OUString url = createFileURL(u"unreferenced_stream.odt");
    // It expectedly fails to load normally:
    CPPUNIT_ASSERT_ASSERTION_FAIL(loadFromDesktop(url, {}, {}));
    // importing it must succeed with RepairPackage set to true.
    mxComponent
        = loadFromDesktop(url, {}, { comphelper::makePropertyValue(u"RepairPackage"_ustr, true) });
    // The document imports in repair mode; the original broken package is used as a template,
    // and the loaded document has no URL:
    CPPUNIT_ASSERT(mxComponent.queryThrow<frame::XModel>()->getURL().isEmpty());
    CPPUNIT_ASSERT_EQUAL(u"Empty document"_ustr, getParagraph(1)->getString());
}

CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */