[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