Introduce INetContentType::scan

...for use in <https://gerrit.libreoffice.org/#/c/8737/> "new methodINetURLObject::getData()
for data urls."

Change-Id: Id381d7c328153fbea44c0efb80532b2961c6c2b7
This commit is contained in:
Stephan Bergmann 2014-03-27 18:05:51 +01:00
parent 92ad689bcb
commit c36daa01f4
5 changed files with 185 additions and 34 deletions

View file

@ -253,8 +253,9 @@ public:
/** Parse the body of an RFC 2045 Content-Type header field.
@param rMediaType The body of the Content-Type header field. It must
be of the form
@param pBegin The range (that must be valid) from non-null pBegin,
inclusive. to non-null pEnd, exclusive, forms the body of the
Content-Type header field. It must be of the form
token "/" token *(";" token "=" (token / quoted-string))
@ -263,21 +264,28 @@ public:
should be US-ASCII, but any Unicode values in the range U+0080..U+FFFF
are interpretet 'as appropriate.'
@param rType Returns the type (the first of the above tokens), in US-
ASCII encoding and converted to lower case.
@param rSubType Returns the sub type (the second of the above
@param pType If not null, returns the type (the first of the above
tokens), in US-ASCII encoding and converted to lower case.
@param rParameters If not null, returns the parameters as a list of
@param pSubType If not null, returns the sub-type (the second of the
above tokens), in US-ASCII encoding and converted to lower case.
@param pParameters If not null, returns the parameters as a list of
INetContentTypeParameters (the attributes are in US-ASCII encoding and
converted to lower case, the values are in Unicode encoding). If
null, only the syntax of the parameters is checked, but they are not
returned.
@return True if the syntax of the field body is correct. If false is
returned, none of the output parameters will be modified!
@return Null if the syntax of the field body is incorrect (i.e., does
not start with type and sub-type tokens). Otherwise, a pointer past the
longest valid input prefix. If null is returned, none of the output
parameters will be modified.
*/
static sal_Unicode const * scan(
sal_Unicode const *pBegin, sal_Unicode const * pEnd,
OUString * pType = 0, OUString * pSubType = 0,
INetContentTypeParameterList * pParameters = 0);
static bool parse(OUString const & rMediaType, OUString & rType,
OUString & rSubType,
INetContentTypeParameterList * pParameters = 0);

View file

@ -0,0 +1,30 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# 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/.
#
$(eval $(call gb_CppunitTest_CppunitTest,svl_inetcontenttype))
$(eval $(call gb_CppunitTest_add_exception_objects,svl_inetcontenttype, \
svl/qa/unit/test_INetContentType \
))
$(eval $(call gb_CppunitTest_use_api,svl_inetcontenttype, \
udkapi \
))
$(eval $(call gb_CppunitTest_use_externals,svl_inetcontenttype, \
boost_headers \
))
$(eval $(call gb_CppunitTest_use_libraries,svl_inetcontenttype, \
sal \
svl \
tl \
))
# vim: set noet sw=4 ts=4:

View file

@ -32,6 +32,7 @@ $(eval $(call gb_Module_add_l10n_targets,svl,\
$(eval $(call gb_Module_add_check_targets,svl,\
CppunitTest_svl_lngmisc \
CppunitTest_svl_qa_cppunit \
CppunitTest_svl_inetcontenttype \
CppunitTest_svl_items \
))

View file

@ -0,0 +1,92 @@
/* -*- 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/.
*/
#include <sal/config.h>
#include <cstring>
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <rtl/ustring.hxx>
#include <svl/inettype.hxx>
#include <tools/inetmime.hxx>
namespace {
class Test: public CppUnit::TestFixture {
public:
void testBad();
void testFull();
void testFollow();
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testBad);
CPPUNIT_TEST(testFull);
CPPUNIT_TEST(testFollow);
CPPUNIT_TEST_SUITE_END();
};
void Test::testBad() {
OUString in("foo=bar");
CPPUNIT_ASSERT_EQUAL(
static_cast<sal_Unicode const *>(0),
INetContentTypes::scan(in.getStr(), in.getStr() + in.getLength()));
OUString t;
OUString s;
INetContentTypeParameterList ps;
CPPUNIT_ASSERT(!INetContentTypes::parse(in, t, s, &ps));
CPPUNIT_ASSERT(t.isEmpty());
CPPUNIT_ASSERT(s.isEmpty());
CPPUNIT_ASSERT_EQUAL(
static_cast<INetContentTypeParameter const *>(0), ps.find("foo"));
}
void Test::testFull() {
OUString in("foo/bar;baz=boz");
CPPUNIT_ASSERT_EQUAL(
in.getStr() + in.getLength(),
INetContentTypes::scan(in.getStr(), in.getStr() + in.getLength()));
OUString t;
OUString s;
INetContentTypeParameterList ps;
CPPUNIT_ASSERT(INetContentTypes::parse(in, t, s, &ps));
CPPUNIT_ASSERT_EQUAL(OUString("foo"), t);
CPPUNIT_ASSERT_EQUAL(OUString("bar"), s);
INetContentTypeParameter const * p = ps.find("baz");
CPPUNIT_ASSERT(p != 0);
CPPUNIT_ASSERT_EQUAL(OUString("boz"), p->m_sValue);
}
void Test::testFollow() {
OUString in("foo/bar;baz=boz;base64,");
CPPUNIT_ASSERT_EQUAL(
in.getStr() + std::strlen("foo/bar;baz=boz"),
INetContentTypes::scan(in.getStr(), in.getStr() + in.getLength()));
OUString t;
OUString s;
INetContentTypeParameterList ps;
CPPUNIT_ASSERT(!INetContentTypes::parse(in, t, s));
CPPUNIT_ASSERT(t.isEmpty());
CPPUNIT_ASSERT(s.isEmpty());
CPPUNIT_ASSERT_EQUAL(
static_cast<INetContentTypeParameter const *>(0), ps.find("baz"));
}
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -779,46 +779,66 @@ bool INetContentTypes::GetExtensionFromURL(OUString const & rURL,
}
// static
bool INetContentTypes::parse(OUString const & rMediaType,
OUString & rType, OUString & rSubType,
INetContentTypeParameterList * pParameters)
sal_Unicode const * INetContentTypes::scan(
sal_Unicode const * pBegin, sal_Unicode const * pEnd, OUString * pType,
OUString * pSubType, INetContentTypeParameterList * pParameters)
{
sal_Unicode const * p = rMediaType.getStr();
sal_Unicode const * pEnd = p + rMediaType.getLength();
p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd);
sal_Unicode const * pToken = p;
bool bDowncase = false;
sal_Unicode const * p = INetMIME::skipLinearWhiteSpaceComment(pBegin, pEnd);
sal_Unicode const * pTypeBegin = p;
while (p != pEnd && INetMIME::isTokenChar(*p))
{
bDowncase = bDowncase || rtl::isAsciiUpperCase(*p);
++p;
}
if (p == pToken)
return false;
rType = OUString(pToken, p - pToken);
if (bDowncase)
rType= rType.toAsciiLowerCase();
if (p == pTypeBegin)
return 0;
sal_Unicode const * pTypeEnd = p;
p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd);
if (p == pEnd || *p++ != '/')
return false;
return 0;
p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd);
pToken = p;
bDowncase = false;
sal_Unicode const * pSubTypeBegin = p;
while (p != pEnd && INetMIME::isTokenChar(*p))
{
bDowncase = bDowncase || rtl::isAsciiUpperCase(*p);
++p;
}
if (p == pToken)
return false;
rSubType = OUString(pToken, p - pToken);
if (bDowncase)
rSubType = rSubType.toAsciiLowerCase();
if (p == pSubTypeBegin)
return 0;
sal_Unicode const * pSubTypeEnd = p;
return INetMIME::scanParameters(p, pEnd, pParameters) == pEnd;
if (pType != 0)
{
*pType = OUString(pTypeBegin, pTypeEnd - pTypeBegin).toAsciiLowerCase();
}
if (pSubType != 0)
{
*pSubType = OUString(pSubTypeBegin, pSubTypeEnd - pSubTypeBegin)
.toAsciiLowerCase();
}
return INetMIME::scanParameters(p, pEnd, pParameters);
}
bool INetContentTypes::parse(
OUString const & rMediaType, OUString & rType, OUString & rSubType,
INetContentTypeParameterList * pParameters)
{
sal_Unicode const * b = rMediaType.getStr();
sal_Unicode const * e = b + rMediaType.getLength();
OUString t;
OUString s;
INetContentTypeParameterList p;
if (scan(b, e, &t, &s, pParameters == 0 ? 0 : &p) == e) {
rType = t;
rSubType = s;
if (pParameters != 0) {
*pParameters = p;
}
return true;
} else {
return false;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */