[Libreoffice-commits] core.git: 2 commits - bin/get-bugzilla-attachments-by-mimetype writerperfect/Library_wpftimpress.mk writerperfect/source writerperfect/StaticLibrary_writerperfect.mk

David Tardon dtardon at redhat.com
Fri Dec 13 00:45:45 PST 2013


 bin/get-bugzilla-attachments-by-mimetype             |    5 
 writerperfect/Library_wpftimpress.mk                 |    1 
 writerperfect/StaticLibrary_writerperfect.mk         |    1 
 writerperfect/source/common/DirectoryStream.cxx      |  164 ++++++++++++++
 writerperfect/source/common/DirectoryStream.hxx      |   48 ++++
 writerperfect/source/impress/KeynoteImportFilter.cxx |  218 +++++++++++++++++--
 6 files changed, 422 insertions(+), 15 deletions(-)

New commits:
commit af8191d2fa6bc7fce9020fd75c44c78d87cc1d75
Author: David Tardon <dtardon at redhat.com>
Date:   Fri Dec 13 09:29:58 2013 +0100

    do not download html files from moz bz
    
    Change-Id: I18519dd8ad0bdaac55a1d5bccdc30b943d717c9c

diff --git a/bin/get-bugzilla-attachments-by-mimetype b/bin/get-bugzilla-attachments-by-mimetype
index 4aed0e6..d9e03e5 100755
--- a/bin/get-bugzilla-attachments-by-mimetype
+++ b/bin/get-bugzilla-attachments-by-mimetype
@@ -448,6 +448,11 @@ common_noncore_mimetypes = {
 
 for (prefix, uri) in rss_bugzillas.items():
     for (mimetype,extension) in mimetypes.items():
+        # It seems that bugzilla has problems returing that many results
+        # (10000 results is probably a limit set somewhere) so we always
+        # end processing the complete list.
+        if mimetype == 'text/html' and prefix == 'moz':
+                continue
         get_through_rss_query(uri, mimetype, prefix, extension)
 
 for (mimetype,extension) in mimetypes.items():
commit 735dc598cd38c76aeeaa37df57f1d0018fe294c8
Author: David Tardon <dtardon at redhat.com>
Date:   Mon Dec 9 20:11:43 2013 +0100

    handle Keynote package format too
    
    Change-Id: I3023bcba0a3d3bd83aca56e4ef72a892da5b55cf

diff --git a/writerperfect/Library_wpftimpress.mk b/writerperfect/Library_wpftimpress.mk
index cb69f98..08cdd12 100644
--- a/writerperfect/Library_wpftimpress.mk
+++ b/writerperfect/Library_wpftimpress.mk
@@ -35,6 +35,7 @@ $(eval $(call gb_Library_use_libraries,wpftimpress,\
 	sal \
 	sot \
 	tl \
+	ucbhelper \
 	utl \
 	xo \
 	$(gb_UWINAPI) \
diff --git a/writerperfect/StaticLibrary_writerperfect.mk b/writerperfect/StaticLibrary_writerperfect.mk
index d6b7ab5..6b21c02 100644
--- a/writerperfect/StaticLibrary_writerperfect.mk
+++ b/writerperfect/StaticLibrary_writerperfect.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_StaticLibrary_use_api,writerperfect,\
 ))
 
 $(eval $(call gb_StaticLibrary_add_exception_objects,writerperfect,\
+	writerperfect/source/common/DirectoryStream \
 	writerperfect/source/common/DocumentHandler \
 	writerperfect/source/common/WPXSvStream \
 ))
diff --git a/writerperfect/source/common/DirectoryStream.cxx b/writerperfect/source/common/DirectoryStream.cxx
new file mode 100644
index 0000000..14b37f3
--- /dev/null
+++ b/writerperfect/source/common/DirectoryStream.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* writerperfect
+ * Version: MPL 2.0 / LGPLv2.1+
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Major Contributor(s):
+ * Copyright (C) 2007 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU Lesser General Public License Version 2.1 or later
+ * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
+ * applicable instead of those above.
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+#include <rtl/ustring.hxx>
+
+#include <ucbhelper/content.hxx>
+
+#include "DirectoryStream.hxx"
+#include "WPXSvStream.hxx"
+
+namespace io = com::sun::star::io;
+namespace sdbc = com::sun::star::sdbc;
+namespace ucb = com::sun::star::ucb;
+namespace uno = com::sun::star::uno;
+
+namespace writerperfect
+{
+
+namespace
+{
+
+struct NotADirectoryException
+{
+};
+
+}
+
+namespace
+{
+
+uno::Reference<io::XInputStream> findStream(ucbhelper::Content &rContent, const rtl::OUString &rName)
+{
+    uno::Reference<io::XInputStream> xInputStream;
+
+    uno::Sequence<rtl::OUString> lPropNames(1);
+    lPropNames[0] = "Title";
+    try
+    {
+        const uno::Reference<sdbc::XResultSet> xResultSet(
+                rContent.createCursor(lPropNames, ucbhelper::INCLUDE_DOCUMENTS_ONLY));
+        if (xResultSet->first())
+        {
+            const uno::Reference<ucb::XContentAccess> xContentAccess(xResultSet, uno::UNO_QUERY_THROW);
+            const uno::Reference<sdbc::XRow> xRow(xResultSet, uno::UNO_QUERY_THROW);
+            do
+            {
+                const rtl::OUString aTitle(xRow->getString(1));
+                if (aTitle == rName)
+                {
+                    const uno::Reference<ucb::XContent> xSubContent(xContentAccess->queryContent());
+                    ucbhelper::Content aSubContent(xSubContent, uno::Reference<ucb::XCommandEnvironment>(), comphelper::getProcessComponentContext());
+                    xInputStream = aSubContent.openStream();
+                    break;
+                }
+            } while (xResultSet->next());
+        }
+    }
+    catch (uno::RuntimeException)
+    {
+        // ignore
+    }
+    catch (uno::Exception)
+    {
+        // ignore
+    }
+
+    return xInputStream;
+}
+
+}
+
+struct DirectoryStream::Impl
+{
+    Impl(const uno::Reference<ucb::XContent> &rxContent);
+
+    uno::Reference<ucb::XContent> xContent;
+};
+
+DirectoryStream::Impl::Impl(const uno::Reference<ucb::XContent> &rxContent)
+    : xContent(rxContent)
+{
+}
+
+DirectoryStream::DirectoryStream(const com::sun::star::uno::Reference<com::sun::star::ucb::XContent> &xContent)
+    : m_pImpl(new Impl(xContent))
+{
+}
+
+DirectoryStream::~DirectoryStream()
+{
+    delete m_pImpl;
+}
+
+bool DirectoryStream::isOLEStream()
+{
+    return true;
+}
+
+WPXInputStream *DirectoryStream::getDocumentOLEStream(const char *const pName)
+{
+    WPXInputStream *input = 0;
+
+    ucbhelper::Content aContent(m_pImpl->xContent, uno::Reference<ucb::XCommandEnvironment>(), comphelper::getProcessComponentContext());
+    const uno::Reference<io::XInputStream> xInputStream(findStream(aContent, rtl::OUString::createFromAscii(pName)));
+    if (xInputStream.is())
+        input = new WPXSvInputStream(xInputStream);
+
+    return input;
+}
+
+const unsigned char *DirectoryStream::read(const unsigned long, unsigned long &nNumBytesRead)
+{
+    nNumBytesRead = 0;
+    return 0;
+}
+
+int DirectoryStream::seek(const long, const WPX_SEEK_TYPE)
+{
+    return -1;
+}
+
+long DirectoryStream::tell()
+{
+    return 0;
+}
+
+bool DirectoryStream::atEOS()
+{
+    return true;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/common/DirectoryStream.hxx b/writerperfect/source/common/DirectoryStream.hxx
new file mode 100644
index 0000000..8dc6efb
--- /dev/null
+++ b/writerperfect/source/common/DirectoryStream.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef DIRECTORYSTREAM_H_INCLUDED
+#define DIRECTORYSTREAM_H_INCLUDED
+
+#include <libwpd-stream/libwpd-stream.h>
+
+#include <com/sun/star/uno/Reference.h>
+
+namespace com { namespace sun { namespace star { namespace ucb {
+    class XContent;
+} } } }
+
+namespace writerperfect
+{
+
+class DirectoryStream : public WPXInputStream
+{
+    struct Impl;
+
+public:
+    explicit DirectoryStream(const com::sun::star::uno::Reference<com::sun::star::ucb::XContent> &xContent);
+    virtual ~DirectoryStream();
+
+    virtual bool isOLEStream();
+    virtual WPXInputStream *getDocumentOLEStream(const char *pName);
+
+    virtual const unsigned char *read(unsigned long nNumBytes, unsigned long &nNumBytesRead);
+    virtual int seek(long nOffset, WPX_SEEK_TYPE eSeekType);
+    virtual long tell();
+    virtual bool atEOS();
+
+private:
+    Impl *m_pImpl;
+};
+
+}
+
+#endif //  DIRECTORYSTREAM_H_INCLUDED
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerperfect/source/impress/KeynoteImportFilter.cxx b/writerperfect/source/impress/KeynoteImportFilter.cxx
index 0035d5d..a63357c3 100644
--- a/writerperfect/source/impress/KeynoteImportFilter.cxx
+++ b/writerperfect/source/impress/KeynoteImportFilter.cxx
@@ -7,10 +7,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <boost/shared_ptr.hpp>
+
 #include <osl/diagnose.h>
 #include <rtl/tencinfo.h>
 
+#include <comphelper/processfactory.hxx>
+#include <comphelper/types.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XChild.hpp>
 #include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XContent.hpp>
 #include <com/sun/star/xml/sax/XAttributeList.hpp>
 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
 #include <com/sun/star/xml/sax/InputSource.hpp>
@@ -18,17 +27,22 @@
 #include <com/sun/star/io/XSeekable.hpp>
 #include <com/sun/star/uno/Reference.h>
 
+#include <ucbhelper/content.hxx>
+
 #include <xmloff/attrlist.hxx>
 
 #include <libetonyek/libetonyek.h>
 #include <libodfgen/libodfgen.hxx>
 
+#include "common/DirectoryStream.hxx"
 #include "common/DocumentHandler.hxx"
 #include "common/WPXSvStream.hxx"
 #include "KeynoteImportFilter.hxx"
 
 #include <iostream>
 
+using boost::shared_ptr;
+
 using namespace ::com::sun::star::uno;
 using com::sun::star::uno::Reference;
 using com::sun::star::io::XInputStream;
@@ -48,6 +62,46 @@ using com::sun::star::xml::sax::XAttributeList;
 using com::sun::star::xml::sax::XDocumentHandler;
 using com::sun::star::xml::sax::XParser;
 
+namespace beans = com::sun::star::beans;
+namespace container = com::sun::star::container;
+namespace ucb = com::sun::star::ucb;
+
+namespace
+{
+
+template<class T>
+sal_Bool lcl_queryIsPackage( const Sequence<T> &lComponentData )
+{
+    sal_Bool bIsPackage = sal_False;
+
+    const sal_Int32 nLength = lComponentData.getLength();
+    const T *pValue = lComponentData.getConstArray();
+    for ( sal_Int32 i = 0; i < nLength; ++i)
+    {
+        if ( pValue[i].Name == "IsPackage" )
+        {
+            pValue[i].Value >>= bIsPackage;
+            break;
+        }
+    }
+
+    return bIsPackage;
+}
+
+sal_Bool lcl_isPackage( const Any &rComponentData )
+{
+    Sequence < beans::NamedValue > lComponentDataNV;
+    Sequence < beans::PropertyValue > lComponentDataPV;
+
+    if ( rComponentData >>= lComponentDataNV )
+        return lcl_queryIsPackage( lComponentDataNV );
+    else if ( rComponentData >>= lComponentDataPV )
+        return lcl_queryIsPackage( lComponentDataPV );
+
+    return false;
+}
+
+}
 
 sal_Bool SAL_CALL KeynoteImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
 throw (RuntimeException)
@@ -56,10 +110,16 @@ throw (RuntimeException)
     sal_Int32 nLength = aDescriptor.getLength();
     const PropertyValue *pValue = aDescriptor.getConstArray();
     Reference < XInputStream > xInputStream;
+    Reference < ucb::XContent > xContent;
+    sal_Bool bIsPackage = sal_False;
     for ( sal_Int32 i = 0 ; i < nLength; i++)
     {
-        if ( pValue[i].Name == "InputStream" )
+        if ( pValue[i].Name == "ComponentData" )
+            bIsPackage = lcl_isPackage( pValue[i].Value );
+        else if ( pValue[i].Name == "InputStream" )
             pValue[i].Value >>= xInputStream;
+        else if ( pValue[i].Name == "UCBContent" )
+            pValue[i].Value >>= xContent;
     }
     if ( !xInputStream.is() )
     {
@@ -67,6 +127,12 @@ throw (RuntimeException)
         return sal_False;
     }
 
+    if ( bIsPackage && !xContent.is() )
+    {
+        SAL_WARN("writerperfect", "the input claims to be a package, but does not have UCBContent");
+        bIsPackage = false;
+    }
+
     // An XML import service: what we push sax messages to..
     Reference < XDocumentHandler > xInternalHandler(
         mxContext->getServiceManager()->createInstanceWithContext(
@@ -81,10 +147,14 @@ throw (RuntimeException)
     // writes to in-memory target doc
     DocumentHandler xHandler(xInternalHandler);
 
-    WPXSvInputStream input( xInputStream );
+    shared_ptr< WPXInputStream > input;
+    if ( bIsPackage )
+        input.reset( new writerperfect::DirectoryStream( xContent ) );
+    else
+        input.reset( new WPXSvInputStream( xInputStream ) );
 
     OdpGenerator exporter(&xHandler, ODF_FLAT_XML);
-    bool tmpParseResult = libetonyek::KEYDocument::parse(&input, &exporter);
+    bool tmpParseResult = libetonyek::KEYDocument::parse(input.get(), &exporter);
     return tmpParseResult;
 }
 
@@ -107,37 +177,155 @@ OUString SAL_CALL KeynoteImportFilter::detect( com::sun::star::uno::Sequence< Pr
 throw( com::sun::star::uno::RuntimeException )
 {
     SAL_INFO("writerperfect", "KeynoteImportFilter::detect");
-    OUString sTypeName;
+
     sal_Int32 nLength = Descriptor.getLength();
-    sal_Int32 location = nLength;
+    sal_Int32 nNewLength = nLength + 2;
+    sal_Int32 nComponentDataLocation = -1;
+    sal_Int32 nTypeNameLocation = -1;
+    sal_Int32 nUCBContentLocation = -1;
+    bool bIsPackage = false;
+    bool bUCBContentChanged = false;
     const PropertyValue *pValue = Descriptor.getConstArray();
     Reference < XInputStream > xInputStream;
+    Reference < ucb::XContent > xContent;
+    Sequence < beans::NamedValue > lComponentDataNV;
+    Sequence < beans::PropertyValue > lComponentDataPV;
+    bool bComponentDataNV = true;
+
     for ( sal_Int32 i = 0 ; i < nLength; i++)
     {
         if ( pValue[i].Name == "TypeName" )
-            location=i;
+        {
+            nTypeNameLocation = i;
+            --nNewLength;
+        }
+        if ( pValue[i].Name == "ComponentData" )
+        {
+            bComponentDataNV = pValue[i].Value >>= lComponentDataNV;
+            if (!bComponentDataNV)
+                pValue[i].Value >>= lComponentDataPV;
+            nComponentDataLocation = i;
+            --nNewLength;
+        }
         else if ( pValue[i].Name == "InputStream" )
+        {
             pValue[i].Value >>= xInputStream;
+        }
+        else if ( pValue[i].Name == "UCBContent" )
+        {
+            pValue[i].Value >>= xContent;
+            nUCBContentLocation = i;
+        }
     }
 
+    assert(nNewLength >= nLength);
+
     if (!xInputStream.is())
         return OUString();
 
-    WPXSvInputStream input( xInputStream );
+    shared_ptr< WPXInputStream > input( new WPXSvInputStream( xInputStream ) );
 
-    if (libetonyek::KEYDocument::isSupported(&input))
-        sTypeName = "impress_AppleKeynote";
-
-    if (!sTypeName.isEmpty())
+    /* Apple Keynote documents come in two variants:
+     * * actual files (zip), only produced by Keynote 5 (at least with
+     *   default settings)
+     * * packages (IOW, directories), produced by Keynote 1-4 and again
+     *   starting with 6.
+     * But since the libetonyek import only works with a stream, we need
+     * to pass it one for the whole package. Here we determine if that
+     * is needed.
+     *
+     * Note: for convenience, we also recognize that the main XML file
+     * from a package was passed and pass the whole package to the
+     * filter instead.
+     */
+    if ( xContent.is() )
     {
-        if ( location == nLength )
+        ucbhelper::Content aContent( xContent, Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
+        if ( aContent.isFolder() )
         {
-            Descriptor.realloc(nLength+1);
-            Descriptor[location].Name = "TypeName";
+            input.reset( new writerperfect::DirectoryStream( xContent ) );
+            bIsPackage = true;
         }
 
-        Descriptor[location].Value <<=sTypeName;
+        libetonyek::KEYDocumentType type = libetonyek::KEY_DOCUMENT_TYPE_UNKNOWN;
+        if ( !libetonyek::KEYDocument::isSupported( input.get(), &type ) )
+            return OUString();
+
+        if ( type == libetonyek::KEY_DOCUMENT_TYPE_APXL_FILE )
+        {
+            assert( !bIsPackage );
+
+            const Reference < container::XChild > xChild( xContent, UNO_QUERY );
+            if ( xChild.is() )
+            {
+                const Reference < ucb::XContent > xPackageContent( xChild->getParent(), UNO_QUERY );
+                if ( xPackageContent.is() )
+                {
+                    input.reset( new writerperfect::DirectoryStream( xPackageContent ) );
+                    if ( libetonyek::KEYDocument::isSupported( input.get() ) )
+                    {
+                        xContent = xPackageContent;
+                        bUCBContentChanged = true;
+                        bIsPackage = true;
+                    }
+                }
+            }
+        }
     }
+
+    // we do not need to insert ComponentData if this is not a package
+    if ( !bIsPackage && ( nComponentDataLocation == -1 ) )
+        --nNewLength;
+
+    if ( nNewLength > nLength )
+        Descriptor.realloc( nNewLength );
+
+    if ( nTypeNameLocation == -1 )
+    {
+        assert( nLength < nNewLength );
+        nTypeNameLocation = nLength++;
+        Descriptor[nTypeNameLocation].Name = "TypeName";
+    }
+
+    if ( bIsPackage && ( nComponentDataLocation == -1 ) )
+    {
+        assert( nLength < nNewLength );
+        nComponentDataLocation = nLength++;
+        Descriptor[nComponentDataLocation].Name = "ComponentData";
+    }
+
+    if ( bIsPackage )
+    {
+        if (bComponentDataNV)
+        {
+            const sal_Int32 nCDSize = lComponentDataNV.getLength();
+            lComponentDataNV.realloc( nCDSize + 1 );
+            beans::NamedValue aValue;
+            aValue.Name = "IsPackage";
+            aValue.Value = comphelper::makeBoolAny(sal_True);
+            lComponentDataNV[nCDSize] = aValue;
+            Descriptor[nComponentDataLocation].Value <<= lComponentDataNV;
+        }
+        else
+        {
+            const sal_Int32 nCDSize = lComponentDataPV.getLength();
+            lComponentDataPV.realloc( nCDSize + 1 );
+            beans::PropertyValue aProp;
+            aProp.Name = "IsPackage";
+            aProp.Value = comphelper::makeBoolAny(sal_True);
+            aProp.Handle = -1;
+            aProp.State = beans::PropertyState_DIRECT_VALUE;
+            lComponentDataPV[nCDSize] = aProp;
+            Descriptor[nComponentDataLocation].Value <<= lComponentDataPV;
+        }
+    }
+
+    if ( bUCBContentChanged )
+        Descriptor[nUCBContentLocation].Value <<= xContent;
+
+    const OUString sTypeName("impress_AppleKeynote");
+    Descriptor[nTypeNameLocation].Value <<= sTypeName;
+
     return sTypeName;
 }
 


More information about the Libreoffice-commits mailing list