[Media] Nuke unused llmime and associated build tests, also remove unneeded includes in llmimetypes header.

This commit is contained in:
Router Gray
2020-05-28 12:14:03 -05:00
parent 518da73ad2
commit ffb54802d4
7 changed files with 0 additions and 1821 deletions

View File

@@ -64,7 +64,6 @@ set(llmessage_SOURCE_FILES
llmessagetemplate.cpp
llmessagetemplateparser.cpp
llmessagethrottle.cpp
llmime.cpp
llnamevalue.cpp
llnullcipher.cpp
llpacketack.cpp
@@ -163,7 +162,6 @@ set(llmessage_HEADER_FILES
llmessagetemplate.h
llmessagetemplateparser.h
llmessagethrottle.h
llmime.h
llmsgvariabletype.h
llnamevalue.h
llnullcipher.h
@@ -241,7 +239,6 @@ if (LL_TESTS)
include(Tut)
SET(llmessage_TEST_SOURCE_FILES
llmime.cpp
llnamevalue.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp

View File

@@ -1,629 +0,0 @@
/**
* @file llmime.cpp
* @author Phoenix
* @date 2006-12-20
* @brief Implementation of mime tools.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmime.h"
#include <vector>
#include "llmemorystream.h"
/**
* Useful constants.
*/
// Headers specified in rfc-2045 will be canonicalized below.
static const std::string CONTENT_LENGTH("Content-Length");
static const std::string CONTENT_TYPE("Content-Type");
static const S32 KNOWN_HEADER_COUNT = 6;
static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
{
CONTENT_LENGTH,
CONTENT_TYPE,
std::string("MIME-Version"),
std::string("Content-Transfer-Encoding"),
std::string("Content-ID"),
std::string("Content-Description"),
};
// parser helpers
static const std::string MULTIPART("multipart");
static const std::string BOUNDARY("boundary");
static const std::string END_OF_CONTENT_PARAMETER("\r\n ;\t");
static const std::string SEPARATOR_PREFIX("--");
//static const std::string SEPARATOR_SUFFIX("\r\n");
/*
Content-Type: multipart/mixed; boundary="segment"
Content-Length: 24832
--segment
Content-Type: image/j2c
Content-Length: 23715
<data>
--segment
Content-Type: text/xml; charset=UTF-8
<meta data>
EOF
*/
/**
* LLMimeIndex
*/
/**
* @class LLMimeIndex::Impl
* @brief Implementation details of the mime index class.
* @see LLMimeIndex
*/
class LLMimeIndex::Impl
{
public:
Impl() : mOffset(-1), mUseCount(1)
{}
Impl(LLSD headers, S32 offset) :
mHeaders(headers), mOffset(offset), mUseCount(1)
{}
public:
LLSD mHeaders;
S32 mOffset;
S32 mUseCount;
typedef std::vector<LLMimeIndex> sub_part_t;
sub_part_t mAttachments;
};
LLSD LLMimeIndex::headers() const
{
return mImpl->mHeaders;
}
S32 LLMimeIndex::offset() const
{
return mImpl->mOffset;
}
S32 LLMimeIndex::contentLength() const
{
// Find the content length in the headers.
S32 length = -1;
LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH];
if(content_length.isDefined())
{
length = content_length.asInteger();
}
return length;
}
std::string LLMimeIndex::contentType() const
{
std::string type;
LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
if(content_type.isDefined())
{
type = content_type.asString();
}
return type;
}
bool LLMimeIndex::isMultipart() const
{
bool multipart = false;
LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
if(content_type.isDefined())
{
std::string type = content_type.asString();
int comp = type.compare(0, MULTIPART.size(), MULTIPART);
if(0 == comp)
{
multipart = true;
}
}
return multipart;
}
S32 LLMimeIndex::subPartCount() const
{
return mImpl->mAttachments.size();
}
LLMimeIndex LLMimeIndex::subPart(S32 index) const
{
LLMimeIndex part;
if((index >= 0) && (index < (S32)mImpl->mAttachments.size()))
{
part = mImpl->mAttachments[index];
}
return part;
}
LLMimeIndex::LLMimeIndex() : mImpl(new LLMimeIndex::Impl)
{
}
LLMimeIndex::LLMimeIndex(LLSD headers, S32 content_offset) :
mImpl(new LLMimeIndex::Impl(headers, content_offset))
{
}
LLMimeIndex::LLMimeIndex(const LLMimeIndex& mime) :
mImpl(mime.mImpl)
{
++mImpl->mUseCount;
}
LLMimeIndex::~LLMimeIndex()
{
if(0 == --mImpl->mUseCount)
{
delete mImpl;
}
}
LLMimeIndex& LLMimeIndex::operator=(const LLMimeIndex& mime)
{
// Increment use count first so that we handle self assignment
// automatically.
++mime.mImpl->mUseCount;
if(0 == --mImpl->mUseCount)
{
delete mImpl;
}
mImpl = mime.mImpl;
return *this;
}
bool LLMimeIndex::attachSubPart(LLMimeIndex sub_part)
{
// *FIX: Should we check for multi-part?
if(mImpl->mAttachments.size() < S32_MAX)
{
mImpl->mAttachments.push_back(sub_part);
return true;
}
return false;
}
/**
* LLMimeParser
*/
/**
* @class LLMimeParser::Impl
* @brief Implementation details of the mime parser class.
* @see LLMimeParser
*/
class LLMimeParser::Impl
{
public:
// @brief Constructor.
Impl();
// @brief Reset this for a new parse.
void reset();
/**
* @brief Parse a mime entity to find the index information.
*
* This method will scan the istr until a single complete mime
* entity is read, an EOF, or limit bytes have been scanned. The
* istr will be modified by this parsing, so pass in a temporary
* stream or rewind/reset the stream after this call.
* @param istr An istream which contains a mime entity.
* @param limit The maximum number of bytes to scan.
* @param separator The multipart separator if it is known.
* @param is_subpart Set true if parsing a multipart sub part.
* @param index[out] The parsed output.
* @return Returns true if an index was parsed and no errors occurred.
*/
bool parseIndex(
std::istream& istr,
S32 limit,
const std::string& separator,
bool is_subpart,
LLMimeIndex& index);
protected:
/**
* @brief parse the headers.
*
* At the end of a successful parse, mScanCount will be at the
* start of the content.
* @param istr The input stream.
* @param limit maximum number of bytes to process
* @param headers[out] A map of the headers found.
* @return Returns true if the parse was successful.
*/
bool parseHeaders(std::istream& istr, S32 limit, LLSD& headers);
/**
* @brief Figure out the separator string from a content type header.
*
* @param multipart_content_type The content type value from the headers.
* @return Returns the separator string.
*/
std::string findSeparator(std::string multipart_content_type);
/**
* @brief Scan through istr past the separator.
*
* @param istr The input stream.
* @param limit Maximum number of bytes to scan.
* @param separator The multipart separator.
*/
void scanPastSeparator(
std::istream& istr,
S32 limit,
const std::string& separator);
/**
* @brief Scan through istr past the content of the current mime part.
*
* @param istr The input stream.
* @param limit Maximum number of bytes to scan.
* @param headers The headers for this mime part.
* @param separator The multipart separator if known.
*/
void scanPastContent(
std::istream& istr,
S32 limit,
LLSD headers,
const std::string separator);
/**
* @brief Eat CRLF.
*
* This method has no concept of the limit, so ensure you have at
* least 2 characters left to eat before hitting the limit. This
* method will increment mScanCount as it goes.
* @param istr The input stream.
* @return Returns true if CRLF was found and consumed off of istr.
*/
bool eatCRLF(std::istream& istr);
// @brief Returns true if parsing should continue.
bool continueParse() const { return (!mError && mContinue); }
// @brief anonymous enumeration for parse buffer size.
enum
{
LINE_BUFFER_LENGTH = 1024
};
protected:
S32 mScanCount;
bool mContinue;
bool mError;
char mBuffer[LINE_BUFFER_LENGTH];
};
LLMimeParser::Impl::Impl()
{
reset();
}
void LLMimeParser::Impl::reset()
{
mScanCount = 0;
mContinue = true;
mError = false;
mBuffer[0] = '\0';
}
bool LLMimeParser::Impl::parseIndex(
std::istream& istr,
S32 limit,
const std::string& separator,
bool is_subpart,
LLMimeIndex& index)
{
LLSD headers;
bool parsed_something = false;
if(parseHeaders(istr, limit, headers))
{
parsed_something = true;
LLMimeIndex mime(headers, mScanCount);
index = mime;
if(index.isMultipart())
{
// Figure out the separator, scan past it, and recurse.
std::string ct = headers[CONTENT_TYPE].asString();
std::string sep = findSeparator(ct);
scanPastSeparator(istr, limit, sep);
while(continueParse() && parseIndex(istr, limit, sep, true, mime))
{
index.attachSubPart(mime);
}
}
else
{
// Scan to the end of content.
scanPastContent(istr, limit, headers, separator);
if(is_subpart)
{
scanPastSeparator(istr, limit, separator);
}
}
}
if(mError) return false;
return parsed_something;
}
bool LLMimeParser::Impl::parseHeaders(
std::istream& istr,
S32 limit,
LLSD& headers)
{
while(continueParse())
{
// Get the next line.
// We subtract 1 from the limit so that we make sure
// not to read past limit when we get() the newline.
S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
istr.getline(mBuffer, max_get, '\r');
mScanCount += (S32)istr.gcount();
int c = istr.get();
if(EOF == c)
{
mContinue = false;
return false;
}
++mScanCount;
if(c != '\n')
{
mError = true;
return false;
}
if(mScanCount >= limit)
{
mContinue = false;
}
// Check if that's the end of headers.
if('\0' == mBuffer[0])
{
break;
}
// Split out the name and value.
// *NOTE: The use of strchr() here is safe since mBuffer is
// guaranteed to be NULL terminated from the call to getline()
// above.
char* colon = strchr(mBuffer, ':');
if(!colon)
{
mError = true;
return false;
}
// Cononicalize the name part, and store the name: value in
// the headers structure. We do this by iterating through
// 'known' headers and replacing the value found with the
// correct one.
// *NOTE: Not so efficient, but iterating through a small
// subset should not be too much of an issue.
std::string name(mBuffer, colon++ - mBuffer);
while(isspace(*colon)) ++colon;
std::string value(colon);
for(S32 ii = 0; ii < KNOWN_HEADER_COUNT; ++ii)
{
if(0 == LLStringUtil::compareInsensitive(name, KNOWN_HEADER[ii]))
{
name = KNOWN_HEADER[ii];
break;
}
}
headers[name] = value;
}
if(headers.isUndefined()) return false;
return true;
}
std::string LLMimeParser::Impl::findSeparator(std::string header)
{
// 01234567890
//Content-Type: multipart/mixed; boundary="segment"
std::string separator;
std::string::size_type pos = header.find(BOUNDARY);
if(std::string::npos == pos) return separator;
pos += BOUNDARY.size() + 1;
std::string::size_type end;
if(header[pos] == '"')
{
// the boundary is quoted, find the end from pos, and take the
// substring.
end = header.find('"', ++pos);
if(std::string::npos == end)
{
// poorly formed boundary.
mError = true;
}
}
else
{
// otherwise, it's every character until a whitespace, end of
// line, or another parameter begins.
end = header.find_first_of(END_OF_CONTENT_PARAMETER, pos);
if(std::string::npos == end)
{
// it goes to the end of the string.
end = header.size();
}
}
if(!mError) separator = header.substr(pos, end - pos);
return separator;
}
void LLMimeParser::Impl::scanPastSeparator(
std::istream& istr,
S32 limit,
const std::string& sep)
{
std::ostringstream ostr;
ostr << SEPARATOR_PREFIX << sep;
std::string separator = ostr.str();
bool found_separator = false;
while(!found_separator && continueParse())
{
// Subtract 1 from the limit so that we make sure not to read
// past limit when we get() the newline.
S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
istr.getline(mBuffer, max_get, '\r');
mScanCount += (S32)istr.gcount();
if(istr.gcount() >= LINE_BUFFER_LENGTH - 1)
{
// that's way too long to be a separator, so ignore it.
continue;
}
int c = istr.get();
if(EOF == c)
{
mContinue = false;
return;
}
++mScanCount;
if(c != '\n')
{
mError = true;
return;
}
if(mScanCount >= limit)
{
mContinue = false;
}
if(0 == LLStringUtil::compareStrings(std::string(mBuffer), separator))
{
found_separator = true;
}
}
}
void LLMimeParser::Impl::scanPastContent(
std::istream& istr,
S32 limit,
LLSD headers,
const std::string separator)
{
if(headers.has(CONTENT_LENGTH))
{
S32 content_length = headers[CONTENT_LENGTH].asInteger();
// Subtract 2 here for the \r\n after the content.
S32 max_skip = llmin(content_length, limit - mScanCount - 2);
istr.ignore(max_skip);
mScanCount += max_skip;
// *NOTE: Check for hitting the limit and eof here before
// checking for the trailing EOF, because our mime parser has
// to gracefully handle incomplete mime entites.
if((mScanCount >= limit) || istr.eof())
{
mContinue = false;
}
else if(!eatCRLF(istr))
{
mError = true;
return;
}
}
}
bool LLMimeParser::Impl::eatCRLF(std::istream& istr)
{
int c = istr.get();
++mScanCount;
if(c != '\r')
{
return false;
}
c = istr.get();
++mScanCount;
if(c != '\n')
{
return false;
}
return true;
}
LLMimeParser::LLMimeParser() : mImpl(* new LLMimeParser::Impl)
{
}
LLMimeParser::~LLMimeParser()
{
delete & mImpl;
}
void LLMimeParser::reset()
{
mImpl.reset();
}
bool LLMimeParser::parseIndex(std::istream& istr, LLMimeIndex& index)
{
std::string separator;
return mImpl.parseIndex(istr, S32_MAX, separator, false, index);
}
bool LLMimeParser::parseIndex(
const std::vector<U8>& buffer,
LLMimeIndex& index)
{
LLMemoryStream mstr(&buffer[0], buffer.size());
return parseIndex(mstr, buffer.size() + 1, index);
}
bool LLMimeParser::parseIndex(
std::istream& istr,
S32 limit,
LLMimeIndex& index)
{
std::string separator;
return mImpl.parseIndex(istr, limit, separator, false, index);
}
bool LLMimeParser::parseIndex(const U8* buffer, S32 length, LLMimeIndex& index)
{
LLMemoryStream mstr(buffer, length);
return parseIndex(mstr, length + 1, index);
}
/*
bool LLMimeParser::verify(std::istream& isr, LLMimeIndex& index) const
{
return false;
}
bool LLMimeParser::verify(U8* buffer, S32 length, LLMimeIndex& index) const
{
LLMemoryStream mstr(buffer, length);
return verify(mstr, index);
}
*/

View File

@@ -1,292 +0,0 @@
/**
* @file llmime.h
* @author Phoenix
* @date 2006-12-20
* @brief Declaration of mime tools.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLMIME_H
#define LL_LLMIME_H
#include <string>
#include "llsd.h"
/**
* This file declares various tools for parsing and creating MIME
* objects as described in RFCs 2045, 2046, 2047, 2048, and 2049.
*/
/**
* @class LLMimeIndex
* @brief Skeletal information useful for handling mime packages.
* @see LLMimeParser
*
* An instance of this class is the parsed output from a LLMimeParser
* which then allows for easy access into a data stream to find and
* get what you want out of it.
*
* This class meant as a tool to quickly find what you seek in a
* parsed mime entity. As such, it does not have useful support for
* modification of a mime entity and specializes the interface toward
* querying data from a fixed mime entity. Modifying an instance of
* LLMimeIndx does not alter a mime entity and changes to a mime
* entity itself are not propogated into an instance of a LLMimeIndex.
*
* Usage:<br>
* LLMimeIndex mime_index;<br>
* std::ifstream fstr("package.mime", ios::binary);<br>
* LLMimeParser parser;<br>
* if(parser.parseIndex(fstr, mime_index))<br>
* {<br>
* std::vector<U8> content;<br>
* content.resize(mime_index.contentLength());<br>
* fstr.seekg(mime_index.offset(), ios::beg);<br>
* // ...do work on fstr and content<br>
* }<br>
*/
class LLMimeIndex
{
public:
/* @name Client interface.
*/
//@{
/**
* @brief Get the full parsed headers for this.
*
* If there are any headers, it will be a map of header name to
* the value found on the line. The name is everything before the
* colon, and the value is the string found after the colon to the
* end of the line after trimming leading whitespace. So, for
* example:
* Content-Type: text/plain
* would become an entry in the headers of:
* headers["Content-Type"] == "text/plain"
*
* If this instance of an index was generated by the
* LLMimeParser::parseIndex() call, all header names in rfc2045
* will be capitalized as in rfc, eg Content-Length and
* MIME-Version, not content-length and mime-version.
* @return Returns an LLSD map of header name to value. Returns
* undef if there are no headers.
*/
LLSD headers() const;
/**
* @brief Get the content offset.
*
* @return Returns the number of bytes to the start of the data
* segment from the start of serialized mime entity. Returns -1 if
* offset is not known.
*/
S32 offset() const;
/**
* @brief Get the length of the data segment for this mime part.
*
* @return Returns the content length in bytes. Returns -1 if
* length is not known.
*/
S32 contentLength() const;
/**
* @brief Get the mime type associated with this node.
*
* @return Returns the mimetype.
*/
std::string contentType() const;
/**
* @brief Helper method which simplifies parsing the return from type()
*
* @return Returns true if this is a multipart mime, and therefore
* getting subparts will succeed.
*/
bool isMultipart() const;
/**
* @brief Get the number of atachments.
*
* @return Returns the number of sub-parts for this.
*/
S32 subPartCount() const;
/**
* @brief Get the indicated attachment.
*
* @param index Value from 0 to (subPartCount() - 1).
* @return Returns the indicated sub-part, or an invalid mime
* index on failure.
*/
LLMimeIndex subPart(S32 index) const;
//@}
/* @name Interface for building, testing, and helpers for typical use.
*/
//@{
/**
* @brief Default constructor - creates a useless LLMimeIndex.
*/
LLMimeIndex();
/**
* @brief Full constructor.
*
* @param headers The complete headers.
* @param content_offset The number of bytes to the start of the
* data segment of this mime entity from the start of the stream
* or buffer.
*/
LLMimeIndex(LLSD headers, S32 content_offset);
/**
* @brief Copy constructor.
*
* @param mime The other mime object.
*/
LLMimeIndex(const LLMimeIndex& mime);
// @brief Destructor.
~LLMimeIndex();
/*
* @breif Assignment operator.
*
* @param mime The other mime object.
* @return Returns this after assignment.
*/
LLMimeIndex& operator=(const LLMimeIndex& mime);
/**
* @brief Add attachment information as a sub-part to a multipart mime.
*
* @param sub_part the part to attach.
* @return Returns true on success, false on failure.
*/
bool attachSubPart(LLMimeIndex sub_part);
//@}
protected:
// Implementation.
class Impl;
Impl* mImpl;
};
/**
* @class LLMimeParser
* @brief This class implements a MIME parser and verifier.
*
* THOROUGH_DESCRIPTION
*/
class LLMimeParser
{
public:
// @brief Make a new mime parser.
LLMimeParser();
// @brief Mime parser Destructor.
~LLMimeParser();
// @brief Reset internal state of this parser.
void reset();
/* @name Index generation interface.
*/
//@{
/**
* @brief Parse a stream to find the mime index information.
*
* This method will scan the istr until a single complete mime
* entity is read or EOF. The istr will be modified by this
* parsing, so pass in a temporary stream or rewind/reset the
* stream after this call.
* @param istr An istream which contains a mime entity.
* @param index[out] The parsed output.
* @return Returns true if an index was parsed and no errors occurred.
*/
bool parseIndex(std::istream& istr, LLMimeIndex& index);
/**
* @brief Parse a vector to find the mime index information.
*
* @param buffer A vector with data to parse.
* @param index[out] The parsed output.
* @return Returns true if an index was parsed and no errors occurred.
*/
bool parseIndex(const std::vector<U8>& buffer, LLMimeIndex& index);
/**
* @brief Parse a stream to find the mime index information.
*
* This method will scan the istr until a single complete mime
* entity is read, an EOF, or limit bytes have been scanned. The
* istr will be modified by this parsing, so pass in a temporary
* stream or rewind/reset the stream after this call.
* @param istr An istream which contains a mime entity.
* @param limit The maximum number of bytes to scan.
* @param index[out] The parsed output.
* @return Returns true if an index was parsed and no errors occurred.
*/
bool parseIndex(std::istream& istr, S32 limit, LLMimeIndex& index);
/**
* @brief Parse a memory bufffer to find the mime index information.
*
* @param buffer The start of the buffer to parse.
* @param buffer_length The length of the buffer.
* @param index[out] The parsed output.
* @return Returns true if an index was parsed and no errors occurred.
*/
bool parseIndex(const U8* buffer, S32 buffer_length, LLMimeIndex& index);
//@}
/**
* @brief
*
* @return
*/
//bool verify(std::istream& istr, LLMimeIndex& index) const;
/**
* @brief
*
* @return
*/
//bool verify(U8* buffer, S32 buffer_length, LLMimeIndex& index) const;
protected:
// Implementation.
class Impl;
Impl& mImpl;
private:
// @brief Not implemneted to prevent copy consturction.
LLMimeParser(const LLMimeParser& parser);
// @brief Not implemneted to prevent assignment.
LLMimeParser& operator=(const LLMimeParser& mime);
};
#endif // LL_LLMIME_H

View File

@@ -1,445 +0,0 @@
/**
* @file llmime_test.cpp
* @author Phoenix
* @date 2006-12-24
* @brief BRIEF_DESC of llmime_test.cpp
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llsdserialize.h"
#include "../llmime.h"
#include "../test/lltut.h"
namespace tut
{
struct mime_index
{
};
typedef test_group<mime_index> mime_index_t;
typedef mime_index_t::object mime_index_object_t;
tut::mime_index_t tut_mime_index("LLMime");
template<> template<>
void mime_index_object_t::test<1>()
{
LLMimeIndex mime;
ensure("no headers", mime.headers().isUndefined());
ensure_equals("invalid offset", mime.offset(), -1);
ensure_equals("invalid content length", mime.contentLength(), -1);
ensure("no content type", mime.contentType().empty());
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<2>()
{
const S32 CONTENT_LENGTH = 6000;
const S32 CONTENT_OFFSET = 100;
const std::string CONTENT_TYPE = std::string("image/j2c");
LLSD headers;
headers["Content-Length"] = CONTENT_LENGTH;
headers["Content-Type"] = CONTENT_TYPE;
LLMimeIndex mime(headers, CONTENT_OFFSET);
ensure("headers are map", mime.headers().isMap());
ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<3>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
LL_INFOS() << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
<< LL_ENDL;
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"text/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// make sure we have a valid multi-part
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
// make sure ranged gets do the right thing with out of bounds
// sub-parts.
LLMimeIndex invalid_child(mime.subPart(-1));
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
invalid_child = mime.subPart(2);
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<4>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"application/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// check what we have
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
LLMimeIndex actual_meta = mime.subPart(0);
ensure_equals(
"meta type", actual_meta.contentType(), META_CONTENT_TYPE);
ensure_equals(
"meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
ensure_equals(
"meta content length",
actual_meta.contentLength(),
META_CONTENT_LENGTH);
LLMimeIndex actual_image = mime.subPart(1);
ensure_equals(
"image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
ensure_equals(
"image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
ensure_equals(
"image content length",
actual_image.contentLength(),
IMAGE_CONTENT_LENGTH);
}
/*
template<> template<>
void mime_index_object_t::test<5>()
{
}
template<> template<>
void mime_index_object_t::test<6>()
{
}
template<> template<>
void mime_index_object_t::test<7>()
{
}
template<> template<>
void mime_index_object_t::test<8>()
{
}
template<> template<>
void mime_index_object_t::test<>()
{
}
*/
}
namespace tut
{
struct mime_parse
{
};
typedef test_group<mime_parse> mime_parse_t;
typedef mime_parse_t::object mime_parse_object_t;
tut::mime_parse_t tut_mime_parse("LLMimeParse");
template<> template<>
void mime_parse_object_t::test<1>()
{
// parse one mime object
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<2>()
{
// make sure we only parse one.
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("not multipart.", !mime.isMultipart());
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<3>()
{
// test multi-part and lack of content length for some of it.
/*
Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 150);
ensure_equals("data offset for multipart", mime.offset(), 74);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length not known.",
mime_plain.contentLength(),
-1);
ensure_equals("first part offset", mime_plain.offset(), 113);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 198);
}
template<> template<>
void mime_parse_object_t::test<4>()
{
// test multi-part, unquoted separator, and premature eof conditions
/*
Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn */
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
ensure_equals("data offset for multipart", mime.offset(), 72);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 131);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 262);
}
template<> template<>
void mime_parse_object_t::test<5>()
{
// test multi-part with multiple params
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
}
template<> template<>
void mime_parse_object_t::test<6>()
{
// test multi-part with no specified boundary and eof
/*
Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 500);
ensure_equals("data offset for multipart", mime.offset(), 56);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 108);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 232);
}
/*
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
*/
}

View File

@@ -34,9 +34,6 @@
#ifndef LLMIMETYPES_H
#define LLMIMETYPES_H
#include <string>
#include <map>
class LLMIMETypes
{
public:

View File

@@ -41,7 +41,6 @@ set(test_SOURCE_FILES
llinventoryparcel_tut.cpp
lliohttpserver_tut.cpp
lljoint_tut.cpp
llmime_tut.cpp
llmessageconfig_tut.cpp
llmodularmath_tut.cpp
llnamevalue_tut.cpp

View File

@@ -1,448 +0,0 @@
/**
* @file llmime_tut.cpp
* @author Phoenix
* @date 2006-12-24
* @brief BRIEF_DESC of llmime_tut.cpp
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include <tut/tut.hpp>
#include "linden_common.h"
#include "llmime.h"
#include "llsdserialize.h"
namespace tut
{
struct mime_index
{
};
typedef test_group<mime_index> mime_index_t;
typedef mime_index_t::object mime_index_object_t;
tut::mime_index_t tut_mime_index("mime_index");
template<> template<>
void mime_index_object_t::test<1>()
{
LLMimeIndex mime;
ensure("no headers", mime.headers().isUndefined());
ensure_equals("invalid offset", mime.offset(), -1);
ensure_equals("invalid content length", mime.contentLength(), -1);
ensure("no content type", mime.contentType().empty());
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<2>()
{
const S32 CONTENT_LENGTH = 6000;
const S32 CONTENT_OFFSET = 100;
const std::string CONTENT_TYPE = std::string("image/j2c");
LLSD headers;
headers["Content-Length"] = CONTENT_LENGTH;
headers["Content-Type"] = CONTENT_TYPE;
LLMimeIndex mime(headers, CONTENT_OFFSET);
ensure("headers are map", mime.headers().isMap());
ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
ensure("not multipart", !mime.isMultipart());
ensure_equals("no attachments", mime.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<3>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
LL_INFOS() << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
<< LL_ENDL;
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"text/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// make sure we have a valid multi-part
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
// make sure ranged gets do the right thing with out of bounds
// sub-parts.
LLMimeIndex invalid_child(mime.subPart(-1));
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
invalid_child = mime.subPart(2);
ensure("no headers", invalid_child.headers().isUndefined());
ensure_equals("invalid offset", invalid_child.offset(), -1);
ensure_equals(
"invalid content length", invalid_child.contentLength(), -1);
ensure("no content type", invalid_child.contentType().empty());
ensure("not multipart", !invalid_child.isMultipart());
ensure_equals("no attachments", invalid_child.subPartCount(), 0);
}
template<> template<>
void mime_index_object_t::test<4>()
{
const S32 MULTI_CONTENT_LENGTH = 8000;
const S32 MULTI_CONTENT_OFFSET = 100;
const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
LLSD headers;
headers["Content-Length"] = MULTI_CONTENT_LENGTH;
headers["Content-Type"] = MULTI_CONTENT_TYPE;
LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
const S32 META_CONTENT_LENGTH = 700;
const S32 META_CONTENT_OFFSET = 69;
const std::string META_CONTENT_TYPE = std::string(
"application/llsd+xml");
headers = LLSD::emptyMap();
headers["Content-Length"] = META_CONTENT_LENGTH;
headers["Content-Type"] = META_CONTENT_TYPE;
LLMimeIndex meta(headers, META_CONTENT_OFFSET);
mime.attachSubPart(meta);
const S32 IMAGE_CONTENT_LENGTH = 6000;
const S32 IMAGE_CONTENT_OFFSET = 200;
const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
headers = LLSD::emptyMap();
headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
headers["Content-Type"] = IMAGE_CONTENT_TYPE;
LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
mime.attachSubPart(image);
// check what we have
ensure("is multipart", mime.isMultipart());
ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
ensure_equals(
"multi content length",
mime.contentLength(),
MULTI_CONTENT_LENGTH);
ensure_equals("two attachments", mime.subPartCount(), 2);
LLMimeIndex actual_meta = mime.subPart(0);
ensure_equals(
"meta type", actual_meta.contentType(), META_CONTENT_TYPE);
ensure_equals(
"meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
ensure_equals(
"meta content length",
actual_meta.contentLength(),
META_CONTENT_LENGTH);
LLMimeIndex actual_image = mime.subPart(1);
ensure_equals(
"image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
ensure_equals(
"image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
ensure_equals(
"image content length",
actual_image.contentLength(),
IMAGE_CONTENT_LENGTH);
}
/*
template<> template<>
void mime_index_object_t::test<5>()
{
}
template<> template<>
void mime_index_object_t::test<6>()
{
}
template<> template<>
void mime_index_object_t::test<7>()
{
}
template<> template<>
void mime_index_object_t::test<8>()
{
}
template<> template<>
void mime_index_object_t::test<>()
{
}
*/
}
namespace tut
{
struct mime_parse
{
};
typedef test_group<mime_parse> mime_parse_t;
typedef mime_parse_t::object mime_parse_object_t;
tut::mime_parse_t tut_mime_parse("mime_parse");
template<> template<>
void mime_parse_object_t::test<1>()
{
// parse one mime object
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<2>()
{
// make sure we only parse one.
const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("not multipart.", !mime.isMultipart());
ensure_equals("content type", mime.contentType(), "text/plain");
ensure_equals("content length", mime.contentLength(), 200);
ensure_equals("offset", mime.offset(), 49);
}
template<> template<>
void mime_parse_object_t::test<3>()
{
// test multi-part and lack of content length for some of it.
/*
Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 150);
ensure_equals("data offset for multipart", mime.offset(), 74);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length not known.",
mime_plain.contentLength(),
-1);
ensure_equals("first part offset", mime_plain.offset(), 113);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 198);
}
template<> template<>
void mime_parse_object_t::test<4>()
{
// test multi-part, unquoted separator, and premature eof conditions
/*
Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn */
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
ensure_equals("data offset for multipart", mime.offset(), 72);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 131);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 262);
}
template<> template<>
void mime_parse_object_t::test<5>()
{
// test multi-part with multiple params
const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 220);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
}
template<> template<>
void mime_parse_object_t::test<6>()
{
// test multi-part with no specified boundary and eof
/*
Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
*/
const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
std::stringstream istr;
istr.str(SERIALIZED_MIME);
LLMimeIndex mime;
LLMimeParser parser;
bool ok = parser.parseIndex(istr, mime);
ensure("Parse successful.", ok);
ensure("is multipart.", mime.isMultipart());
ensure_equals("sub-part count", mime.subPartCount(), 2);
ensure_equals("content length", mime.contentLength(), 500);
ensure_equals("data offset for multipart", mime.offset(), 56);
LLMimeIndex mime_plain(mime.subPart(0));
ensure_equals(
"first part type",
mime_plain.contentType(),
"text/plain");
ensure_equals(
"first part content length",
mime_plain.contentLength(),
55);
ensure_equals("first part offset", mime_plain.offset(), 108);
LLMimeIndex mime_xml(mime.subPart(1));
ensure_equals(
"second part type",
mime_xml.contentType(),
"text/xml; charset=UTF-8");
ensure_equals(
"second part content length",
mime_xml.contentLength(),
22);
ensure_equals("second part offset", mime_xml.offset(), 232);
}
/*
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
template<> template<>
void mime_parse_object_t::test<>()
{
}
*/
}