[Libreoffice-commits] core.git: 3 commits - include/o3tl include/tools sw/source tools/Library_tl.mk tools/qa tools/source

Stephan Bergmann sbergman at redhat.com
Fri Jun 6 02:13:42 PDT 2014


 include/o3tl/heap_ptr.hxx          |   72 ++++++++++++++---------------
 include/tools/urlobj.hxx           |    5 ++
 sw/source/filter/html/htmlgrin.cxx |   20 ++++----
 tools/Library_tl.mk                |    1 
 tools/qa/cppunit/test_urlobj.cxx   |   90 +++++++++++++++++++++++++++++++++++++
 tools/source/fsys/urlobj.cxx       |   60 ++++++++++++++++++++++++
 6 files changed, 203 insertions(+), 45 deletions(-)

New commits:
commit 805b57cd5b34454589ad6ce11c16507695fd3ff3
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Jun 6 11:12:42 2014 +0200

    Various INetURLObject::getData() fixes
    
    Change-Id: I5eafd6250bbde7227dcc0447a4280b7741c320de

diff --git a/tools/qa/cppunit/test_urlobj.cxx b/tools/qa/cppunit/test_urlobj.cxx
index 5cc1d1b..6cfca96 100644
--- a/tools/qa/cppunit/test_urlobj.cxx
+++ b/tools/qa/cppunit/test_urlobj.cxx
@@ -12,6 +12,7 @@
 #include <sal/types.h>
 #include "cppunit/TestFixture.h"
 #include <cppunit/extensions/HelperMacros.h>
+#include <tools/stream.hxx>
 #include <tools/urlobj.hxx>
 
 #define OUSTR_TO_STDSTR( oustr ) std::string( OUStringToOString( oustr, RTL_TEXTENCODING_ASCII_US ).getStr() )
@@ -243,6 +244,94 @@ namespace tools_urlobj
             }
         }
 
+        void urlobjTest_data() {
+            INetURLObject url;
+            SvMemoryStream * strm;
+            unsigned char const * buf;
+
+            url = INetURLObject("data:");
+            //TODO: CPPUNIT_ASSERT(url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm == 0);
+
+            url = INetURLObject("data:,");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(0), strm->GetSize());
+            delete strm;
+
+            url = INetURLObject("data:,,%C3%A4%90");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(4), strm->GetSize());
+            buf = static_cast<unsigned char const *>(strm->GetData());
+            CPPUNIT_ASSERT_EQUAL(0x2C, int(buf[0]));
+            CPPUNIT_ASSERT_EQUAL(0xC3, int(buf[1]));
+            CPPUNIT_ASSERT_EQUAL(0xA4, int(buf[2]));
+            CPPUNIT_ASSERT_EQUAL(0x90, int(buf[3]));
+            delete strm;
+
+            url = INetURLObject("data:base64,");
+            //TODO: CPPUNIT_ASSERT(url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm == 0);
+
+            url = INetURLObject("data:;base64,");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(0), strm->GetSize());
+            delete strm;
+
+            url = INetURLObject("data:;bAsE64,");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(0), strm->GetSize());
+            delete strm;
+
+            url = INetURLObject("data:;base64,YWJjCg==");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(4), strm->GetSize());
+            buf = static_cast<unsigned char const *>(strm->GetData());
+            CPPUNIT_ASSERT_EQUAL(0x61, int(buf[0]));
+            CPPUNIT_ASSERT_EQUAL(0x62, int(buf[1]));
+            CPPUNIT_ASSERT_EQUAL(0x63, int(buf[2]));
+            CPPUNIT_ASSERT_EQUAL(0x0A, int(buf[3]));
+            delete strm;
+
+            url = INetURLObject("data:;base64,YWJjCg=");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm == 0);
+
+            url = INetURLObject("data:;base64,YWJ$Cg==");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm == 0);
+
+            url = INetURLObject("data:text/plain;param=%22;base64,%22,YQ==");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm != 0);
+            CPPUNIT_ASSERT_EQUAL(sal_uIntPtr(4), strm->GetSize());
+            buf = static_cast<unsigned char const *>(strm->GetData());
+            CPPUNIT_ASSERT_EQUAL(0x59, int(buf[0]));
+            CPPUNIT_ASSERT_EQUAL(0x51, int(buf[1]));
+            CPPUNIT_ASSERT_EQUAL(0x3D, int(buf[2]));
+            CPPUNIT_ASSERT_EQUAL(0x3D, int(buf[3]));
+            delete strm;
+
+            url = INetURLObject("http://example.com");
+            CPPUNIT_ASSERT(!url.HasError());
+            strm = url.getData();
+            CPPUNIT_ASSERT(strm == 0);
+        }
+
         // Change the following lines only, if you add, remove or rename
         // member functions of the current class,
         // because these macros are need by auto register mechanism.
@@ -256,6 +345,7 @@ namespace tools_urlobj
         CPPUNIT_TEST( urlobjTest_006 );
         CPPUNIT_TEST( urlobjCmisTest );
         CPPUNIT_TEST( urlobjTest_emptyPath );
+        CPPUNIT_TEST( urlobjTest_data );
         CPPUNIT_TEST_SUITE_END(  );
     };                          // class createPool
 
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index 08583fb..55a5ddd 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <boost/checked_delete.hpp>
+#include <o3tl/heap_ptr.hxx>
 #include <tools/urlobj.hxx>
 #include <tools/debug.hxx>
 #include <tools/inetmime.hxx>
@@ -588,6 +592,21 @@ void INetURLObject::setInvalid()
     m_aFragment.clear();
 }
 
+namespace {
+
+SvMemoryStream * memoryStream(void const * data, sal_Int32 length) {
+    o3tl::heap_ptr<char, boost::checked_array_deleter<char> > b(
+        new char[length]);
+    memcpy(b.get(), data, length);
+    o3tl::heap_ptr<SvMemoryStream> s(
+        new SvMemoryStream(b.get(), length, STREAM_READ));
+    s->ObjectOwnsMemory(true);
+    b.release();
+    return s.release();
+}
+
+}
+
 SvMemoryStream* INetURLObject::getData()
 {
     if( GetProtocol() != INET_PROT_DATA )
@@ -596,34 +615,32 @@ SvMemoryStream* INetURLObject::getData()
     }
 
     OUString sURLPath = GetURLPath( DECODE_WITH_CHARSET, RTL_TEXTENCODING_ISO_8859_1 );
-    OUString sType, sSubType;
-    OUString sBase64Enc(";base64,");
-
-    INetContentTypeParameterList params;
-    sal_Unicode const * pSkippedMediatype = INetMIME::scanContentType( sURLPath.getStr(), sURLPath.getStr() + sURLPath.getLength(), &sType, &sSubType, &params );
-    sal_Int32 nCharactersSkipped = pSkippedMediatype-sURLPath.getStr();
-    sal_Int32 nCommaIndex = sURLPath.indexOf( ",", nCharactersSkipped );
-    sal_Int32 nBase64Index = sURLPath.indexOf( sBase64Enc, nCharactersSkipped );
-    SvMemoryStream* aStream=NULL;
-
-    if( nBase64Index >= 0 && nBase64Index < nCommaIndex )
+    sal_Unicode const * pSkippedMediatype = INetMIME::scanContentType( sURLPath.getStr(), sURLPath.getStr() + sURLPath.getLength(), NULL, NULL, NULL );
+    sal_Int32 nCharactersSkipped = pSkippedMediatype == NULL
+        ? 0 : pSkippedMediatype-sURLPath.getStr();
+    if (sURLPath.match(",", nCharactersSkipped))
+    {
+        nCharactersSkipped += strlen(",");
+        OString sURLEncodedData(
+            sURLPath.getStr() + nCharactersSkipped,
+            sURLPath.getLength() - nCharactersSkipped,
+            RTL_TEXTENCODING_ISO_8859_1, OUSTRING_TO_OSTRING_CVTFLAGS);
+        return memoryStream(
+            sURLEncodedData.getStr(), sURLEncodedData.getLength());
+    }
+    else if (sURLPath.matchIgnoreAsciiCase(";base64,", nCharactersSkipped))
     {
-        // base64 decoding
-        OUString sBase64Data = sURLPath.copy( nBase64Index + sBase64Enc.getLength() );
+        nCharactersSkipped += strlen(";base64,");
+        OUString sBase64Data = sURLPath.copy( nCharactersSkipped );
         css::uno::Sequence< sal_Int8 > aDecodedData;
-        ::sax::Converter::decodeBase64( aDecodedData, sBase64Data );
-        if( aDecodedData.hasElements() )
+        if (sax::Converter::decodeBase64SomeChars(aDecodedData, sBase64Data)
+            == sBase64Data.getLength())
         {
-            aStream = new SvMemoryStream( aDecodedData.getArray(), aDecodedData.getLength(), STREAM_READ );
+            return memoryStream(
+                aDecodedData.getArray(), aDecodedData.getLength());
         }
     }
-    else
-    {
-        // URL decoding
-        OUString sURLEncodedData = sURLPath.copy( nCommaIndex+1 );
-        aStream = new SvMemoryStream( const_cast< sal_Char * >(OUStringToOString(sURLEncodedData, RTL_TEXTENCODING_UTF8).getStr()), sURLEncodedData.getLength(), STREAM_READ);
-    }
-    return aStream;
+    return NULL;
 }
 
 namespace unnamed_tools_urlobj {
commit 75e0fe06ac08e55e24ef82de9e4b1102518f4e6f
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Jun 6 11:12:04 2014 +0200

    Extend o3tl::heap_ptr to support arrays
    
    Change-Id: I546afcb626e27f6f1115715829779fc0b657548e

diff --git a/include/o3tl/heap_ptr.hxx b/include/o3tl/heap_ptr.hxx
index c0b13e1..4a7e368 100644
--- a/include/o3tl/heap_ptr.hxx
+++ b/include/o3tl/heap_ptr.hxx
@@ -71,12 +71,12 @@ namespace o3tl
     needs to define a non-inline destructor. Else the compiler will
     complain.
 */
-template <class T>
+template <class T, class Deleter = boost::checked_deleter<T> >
 class heap_ptr
 {
   public:
     typedef T               element_type;       /// Provided for generic programming.
-    typedef heap_ptr<T>     self;
+    typedef heap_ptr<T, Deleter> self;
 
     typedef T * (self::*    safe_bool )();
 
@@ -139,10 +139,10 @@ class heap_ptr
 /** Supports the semantic of std::swap(). Provided as an aid to
     generic programming.
 */
-template<class T>
+template<class T, class Deleter>
 inline void
-swap( heap_ptr<T> &       io_a,
-      heap_ptr<T> &       io_b )
+swap( heap_ptr<T, Deleter> &       io_a,
+      heap_ptr<T, Deleter> &       io_b )
 {
     io_a.swap(io_b);
 }
@@ -151,9 +151,9 @@ swap( heap_ptr<T> &       io_a,
 
 // IMPLEMENTATION
 
-template <class T>
+template <class T, class Deleter>
 inline void
-heap_ptr<T>::internal_delete()
+heap_ptr<T, Deleter>::internal_delete()
 {
     ::boost::checked_delete(pHeapObject);
 
@@ -162,72 +162,72 @@ heap_ptr<T>::internal_delete()
     //   where internal_delete() is used.
 }
 
-template <class T>
+template <class T, class Deleter>
 inline
-heap_ptr<T>::heap_ptr( T * pass_heapObject )
+heap_ptr<T, Deleter>::heap_ptr( T * pass_heapObject )
     : pHeapObject(pass_heapObject)
 {
 }
 
-template <class T>
+template <class T, class Deleter>
 inline
-heap_ptr<T>::~heap_ptr()
+heap_ptr<T, Deleter>::~heap_ptr()
 {
     internal_delete();
 }
 
-template <class T>
-inline heap_ptr<T> &
-heap_ptr<T>::operator=(T * pass_heapObject)
+template <class T, class Deleter>
+inline heap_ptr<T, Deleter> &
+heap_ptr<T, Deleter>::operator=(T * pass_heapObject)
 {
     reset(pass_heapObject);
     return *this;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline const T &
-heap_ptr<T>::operator*() const
+heap_ptr<T, Deleter>::operator*() const
 {
     BOOST_ASSERT( pHeapObject != 0
                   && "Accessing a heap_ptr<>(0)." );
     return *pHeapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline T &
-heap_ptr<T>::operator*()
+heap_ptr<T, Deleter>::operator*()
 {
     BOOST_ASSERT( pHeapObject != 0
                   && "Accessing a heap_ptr<>(0)." );
     return *pHeapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline const T *
-heap_ptr<T>::operator->() const
+heap_ptr<T, Deleter>::operator->() const
 {
     return pHeapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline T *
-heap_ptr<T>::operator->()
+heap_ptr<T, Deleter>::operator->()
 {
     return pHeapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline
-heap_ptr<T>::operator typename heap_ptr<T>::safe_bool() const
+heap_ptr<T, Deleter>::operator typename heap_ptr<T, Deleter>::safe_bool() const
 {
     return is()
             ? safe_bool(&self::get)
             : safe_bool(0);
 }
 
-template <class T>
+template <class T, class Deleter>
 void
-heap_ptr<T>::reset(T * pass_heapObject)
+heap_ptr<T, Deleter>::reset(T * pass_heapObject)
 {
     if (    pHeapObject != 0
         &&  pHeapObject == pass_heapObject)
@@ -237,41 +237,41 @@ heap_ptr<T>::reset(T * pass_heapObject)
     pHeapObject = pass_heapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 T *
-heap_ptr<T>::release()
+heap_ptr<T, Deleter>::release()
 {
     T * ret = pHeapObject;
     pHeapObject = 0;
     return ret;
 }
 
-template <class T>
+template <class T, class Deleter>
 void
-heap_ptr<T>::swap(self & io_other)
+heap_ptr<T, Deleter>::swap(self & io_other)
 {
     T * temp = io_other.pHeapObject;
     io_other.pHeapObject = pHeapObject;
     pHeapObject = temp;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline bool
-heap_ptr<T>::is() const
+heap_ptr<T, Deleter>::is() const
 {
     return pHeapObject != 0;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline const T *
-heap_ptr<T>::get() const
+heap_ptr<T, Deleter>::get() const
 {
     return pHeapObject;
 }
 
-template <class T>
+template <class T, class Deleter>
 inline T *
-heap_ptr<T>::get()
+heap_ptr<T, Deleter>::get()
 {
     return pHeapObject;
 }
commit 8b46d5c849a24e67fb2807a80164caf9001d9544
Author: Chr. Rossmanith <ChrRossmanith at gmx.de>
Date:   Tue Jun 3 22:33:25 2014 +0200

    new method INetURLObject::getData() for data urls
    
    Signed-off-by: Stephan Bergmann <sbergman at redhat.com>
    
    Conflicts:
    	tools/source/fsys/urlobj.cxx
    
    Change-Id: I59b5b95cf9b65920ec04922fdb25e4228fd22995

diff --git a/include/tools/urlobj.hxx b/include/tools/urlobj.hxx
index ace1d76..cd10405 100644
--- a/include/tools/urlobj.hxx
+++ b/include/tools/urlobj.hxx
@@ -26,6 +26,8 @@
 #include <rtl/textenc.h>
 #include <sal/types.h>
 
+class SvMemoryStream;
+
 namespace com { namespace sun { namespace star { namespace util {
     class XStringWidth;
 } } } }
@@ -851,6 +853,9 @@ public:
     OUString getFSysPath(FSysStyle eStyle, sal_Unicode * pDelimiter = 0)
         const;
 
+    // Data URLs:
+    SvMemoryStream* getData();
+
     // POP3 and URLs:
 
     OUString GetMsgId(DecodeMechanism eMechanism = DECODE_TO_IURI,
diff --git a/sw/source/filter/html/htmlgrin.cxx b/sw/source/filter/html/htmlgrin.cxx
index 30d9dd1..18cdf93 100644
--- a/sw/source/filter/html/htmlgrin.cxx
+++ b/sw/source/filter/html/htmlgrin.cxx
@@ -67,8 +67,8 @@
 #include <numrule.hxx>
 #include <boost/shared_ptr.hpp>
 
-#include <sax/tools/converter.hxx>
 #include <vcl/graphicfilter.hxx>
+#include <tools/urlobj.hxx>
 
 using namespace ::com::sun::star;
 
@@ -695,16 +695,18 @@ IMAGE_SETEVENT:
     aFrmSet.Put( aFrmSize );
 
     Graphic aEmptyGrf;
-    if( sGrfNm.startsWith("data:") )
+    INetURLObject aGraphicURL( sGrfNm );
+    if( aGraphicURL.GetProtocol() == INET_PROT_DATA )
     {
-        // use embedded base64 encoded data
-        ::com::sun::star::uno::Sequence< sal_Int8 > aPass;
-        OUString sBase64Data = sGrfNm.replaceAt(0,22,"");
-        ::sax::Converter::decodeBase64(aPass, sBase64Data);
-        if( aPass.hasElements() )
+        SvMemoryStream* aStream = aGraphicURL.getData();
+        if( aStream )
         {
-                SvMemoryStream aStream(aPass.getArray(), aPass.getLength(), STREAM_READ);
-                GraphicFilter::GetGraphicFilter().ImportGraphic( aEmptyGrf, OUString(), aStream );
+            GraphicFilter::GetGraphicFilter().ImportGraphic( aEmptyGrf, OUString(), *aStream );
+            free( aStream );
+        }
+        else
+        {
+            aEmptyGrf.SetDefaultType();
         }
     }
     else
diff --git a/tools/Library_tl.mk b/tools/Library_tl.mk
index c6ee6cb..856471b 100644
--- a/tools/Library_tl.mk
+++ b/tools/Library_tl.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_Library_use_libraries,tl,\
     i18nlangtag \
     cppu \
     sal \
+    sax \
 	$(gb_UWINAPI) \
 ))
 
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index 69b84a9..08583fb 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -20,6 +20,7 @@
 #include <tools/urlobj.hxx>
 #include <tools/debug.hxx>
 #include <tools/inetmime.hxx>
+#include <tools/stream.hxx>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/util/XStringWidth.hpp>
 #include <osl/diagnose.h>
@@ -37,6 +38,10 @@
 
 #include <string.h>
 
+#include <com/sun/star/uno/Sequence.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/uri.hxx>
+
 namespace unnamed_tools_urlobj {} using namespace unnamed_tools_urlobj;
     // unnamed namespaces don't work well yet...
 
@@ -583,6 +588,44 @@ void INetURLObject::setInvalid()
     m_aFragment.clear();
 }
 
+SvMemoryStream* INetURLObject::getData()
+{
+    if( GetProtocol() != INET_PROT_DATA )
+    {
+        return NULL;
+    }
+
+    OUString sURLPath = GetURLPath( DECODE_WITH_CHARSET, RTL_TEXTENCODING_ISO_8859_1 );
+    OUString sType, sSubType;
+    OUString sBase64Enc(";base64,");
+
+    INetContentTypeParameterList params;
+    sal_Unicode const * pSkippedMediatype = INetMIME::scanContentType( sURLPath.getStr(), sURLPath.getStr() + sURLPath.getLength(), &sType, &sSubType, &params );
+    sal_Int32 nCharactersSkipped = pSkippedMediatype-sURLPath.getStr();
+    sal_Int32 nCommaIndex = sURLPath.indexOf( ",", nCharactersSkipped );
+    sal_Int32 nBase64Index = sURLPath.indexOf( sBase64Enc, nCharactersSkipped );
+    SvMemoryStream* aStream=NULL;
+
+    if( nBase64Index >= 0 && nBase64Index < nCommaIndex )
+    {
+        // base64 decoding
+        OUString sBase64Data = sURLPath.copy( nBase64Index + sBase64Enc.getLength() );
+        css::uno::Sequence< sal_Int8 > aDecodedData;
+        ::sax::Converter::decodeBase64( aDecodedData, sBase64Data );
+        if( aDecodedData.hasElements() )
+        {
+            aStream = new SvMemoryStream( aDecodedData.getArray(), aDecodedData.getLength(), STREAM_READ );
+        }
+    }
+    else
+    {
+        // URL decoding
+        OUString sURLEncodedData = sURLPath.copy( nCommaIndex+1 );
+        aStream = new SvMemoryStream( const_cast< sal_Char * >(OUStringToOString(sURLEncodedData, RTL_TEXTENCODING_UTF8).getStr()), sURLEncodedData.getLength(), STREAM_READ);
+    }
+    return aStream;
+}
+
 namespace unnamed_tools_urlobj {
 
 INetURLObject::FSysStyle guessFSysStyleByCounting(sal_Unicode const * pBegin,


More information about the Libreoffice-commits mailing list