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 <sberg...@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, ¶ms ); - 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 <sberg...@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 <chrrossman...@gmx.de> Date: Tue Jun 3 22:33:25 2014 +0200 new method INetURLObject::getData() for data urls Signed-off-by: Stephan Bergmann <sberg...@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, ¶ms ); + 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, _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits