Add parsing feedback via parsingContext (#280)

* Add parsing feedback via parsingContext

Changes the parsing context to be modifiable to be able to provide
feedback on the parsing. This allows the user to check if header
recovery was necessary, for example, while parsing the current message.

Signed-off-by: Ben Magistro <koncept1@gmail.com>
Co-authored-by: Vincent Richard <vincent@vincent-richard.net>
This commit is contained in:
bmagistro 2023-12-31 10:10:18 -05:00 committed by GitHub
parent 9b65b4de6c
commit 6fd4de8fb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 112 additions and 77 deletions

View File

@ -66,7 +66,7 @@ address-list = (address *("," address)) / obs-addr-list
*/
shared_ptr <address> address::parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -73,7 +73,7 @@ public:
* @return a new address object, or null if no more address is available in the input buffer
*/
static shared_ptr <address> parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -50,7 +50,7 @@ addressList::~addressList() {
void addressList::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -176,7 +176,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -122,7 +122,7 @@ size_t body::findNextBoundaryPosition(
void body::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,

View File

@ -343,7 +343,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,

View File

@ -37,7 +37,7 @@ bodyPart::bodyPart()
void bodyPart::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,

View File

@ -133,7 +133,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,

View File

@ -64,7 +64,7 @@ charset::charset(const charset& other)
void charset::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -155,7 +155,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -65,7 +65,7 @@ void component::parse(
void component::parse(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::inputStream>& inputStream,
const size_t position,
const size_t end,
@ -106,7 +106,7 @@ void component::parse(const string& buffer) {
}
void component::parse(const parsingContext& ctx, const string& buffer) {
void component::parse(parsingContext& ctx, const string& buffer) {
m_parsedOffset = m_parsedLength = 0;
@ -128,7 +128,7 @@ void component::parse(
void component::parse(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end, size_t* newPosition
@ -157,7 +157,7 @@ void component::offsetParsedBounds(const size_t offset) {
void component::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,
@ -181,7 +181,7 @@ void component::parseImpl(
void component::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -59,7 +59,7 @@ public:
* @param ctx parsing context
* @param buffer input buffer
*/
void parse(const parsingContext& ctx, const string& buffer);
void parse(parsingContext& ctx, const string& buffer);
/** Parse RFC-822/MIME data for this component. If stream is not seekable,
* or if length is not specified, entire contents of the stream will
@ -94,7 +94,7 @@ public:
* @param newPosition will receive the new position in the input buffer
*/
void parse(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -129,7 +129,7 @@ public:
* @param newPosition will receive the new position in the input stream
*/
void parse(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::inputStream>& inputStream,
const size_t position,
const size_t end,
@ -228,7 +228,7 @@ protected:
// AT LEAST ONE of these parseImpl() functions MUST be implemented in derived class
virtual void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const shared_ptr <utility::parserInputStreamAdapter>& parser,
const size_t position,
const size_t end,
@ -236,7 +236,7 @@ protected:
);
virtual void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -47,7 +47,7 @@ contentDisposition::contentDisposition(const contentDisposition& type)
void contentDisposition::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -77,7 +77,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -76,7 +76,7 @@ static const char* monthNames[] = {
};
void datetime::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -253,7 +253,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -187,7 +187,7 @@ const std::vector <string> disposition::getModifierList() const {
void disposition::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -142,7 +142,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -176,7 +176,7 @@ emailAddress::emailAddress(const word& localName, const word& domainName)
void emailAddress::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -113,7 +113,7 @@ public:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -62,7 +62,7 @@ encoding::encoding(const encoding& enc)
void encoding::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -158,7 +158,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -62,7 +62,7 @@ field-body-contents =
*/
void header::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -340,7 +340,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -75,7 +75,7 @@ headerField& headerField::operator=(const headerField& other) {
shared_ptr <headerField> headerField::parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -125,6 +125,8 @@ shared_ptr <headerField> headerField::parseNext(
if (buffer[pos] != ':') {
// header field recovery is necessary, update flag in parsing context
ctx.setHeaderRecoveryNeeded(true);
switch (ctx.getHeaderParseErrorRecoveryMethod()) {
case vmime::headerParseRecoveryMethod::SKIP_LINE:
@ -261,7 +263,7 @@ shared_ptr <headerField> headerField::parseNext(
void headerField::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -153,7 +153,7 @@ public:
* in the input buffer
*/
static shared_ptr <headerField> parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -165,7 +165,7 @@ public:
protected:
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -69,7 +69,7 @@ angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
*/
void mailbox::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -101,7 +101,7 @@ public:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -43,7 +43,7 @@ mailboxField::mailboxField(const mailboxField&)
void mailboxField::parse(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -51,7 +51,7 @@ protected:
public:
void parse(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -54,7 +54,7 @@ mailboxGroup::~mailboxGroup() {
void mailboxGroup::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -184,7 +184,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -191,7 +191,7 @@ const std::vector <shared_ptr <component> > mailboxList::getChildComponents() {
void mailboxList::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -162,7 +162,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -56,7 +56,7 @@ mediaType::mediaType(const mediaType& other)
void mediaType::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -98,7 +98,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -64,7 +64,7 @@ messageId::messageId(const string& left, const string& right)
*/
void messageId::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,
@ -158,7 +158,7 @@ void messageId::parseImpl(
shared_ptr <messageId> messageId::parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -106,7 +106,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -129,7 +129,7 @@ protected:
* @return a new message-id object, or null if no more message-id can be parsed from the input buffer
*/
static shared_ptr <messageId> parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -84,7 +84,7 @@ const std::vector <shared_ptr <component> > messageIdSequence::getChildComponent
void messageIdSequence::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -153,7 +153,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -116,7 +116,7 @@ void parameter::setValue(const word& value) {
void parameter::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -138,7 +138,7 @@ void parameter::parseImpl(
void parameter::parse(
const parsingContext& ctx,
parsingContext& ctx,
const std::vector <valueChunk>& chunks
) {

View File

@ -143,7 +143,7 @@ public:
protected:
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -160,7 +160,7 @@ protected:
private:
void parse(
const parsingContext& ctx,
parsingContext& ctx,
const std::vector <valueChunk>& chunks
);

View File

@ -78,7 +78,7 @@ struct paramInfo {
void parameterizedHeaderField::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -200,7 +200,7 @@ private:
protected:
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -61,6 +61,18 @@ void parsingContext::setHeaderParseErrorRecoveryMethod(
}
bool parsingContext::getHeaderRecoveryNeeded() const {
return m_headerParseRecoveryNeeded;
}
void parsingContext::setHeaderRecoveryNeeded(bool needed) {
m_headerParseRecoveryNeeded = needed;
}
bool parsingContext::getUseMyHostname() const {
return m_useMyHostname;

View File

@ -51,6 +51,8 @@ struct headerParseRecoveryMethod {
*/
class VMIME_EXPORT parsingContext : public context {
friend class headerField;
public:
parsingContext();
@ -77,7 +79,15 @@ public:
*/
headerParseRecoveryMethod::headerLineError getHeaderParseErrorRecoveryMethod() const;
/** Return the current hostname adding behavior when parsing/creating a header field that
/** Returns a boolean indicating if utilizing the header recovery mechanism
* was necessary.
*
* @retval true The header recovery mechanism was necessary when parsing
* @retval false The header recovery mechanism was not necessary when parsing
*/
bool getHeaderRecoveryNeeded() const;
/** Return the current hostname adding behavior when parsing/creating a header field that
* utilizes a domain name.
*
* @retval true The local hostname will be appended if a domain is not present
@ -95,6 +105,17 @@ protected:
headerParseRecoveryMethod::headerLineError m_headerParseErrorRecovery;
/** Flag to indicate if the header recovery mechanism was used while parsing
* as only one method is ever in use, a simple boolean is sufficent
*/
bool m_headerParseRecoveryNeeded{false};
/** Sets a flag indicating that the header recovery mechanism was required
*
* This should only be called from headerField::parseNext
*/
void setHeaderRecoveryNeeded(bool needed);
/** Flag to indicate if the local hostname should be used/appended
* for header fields when one is not present.
*/

View File

@ -115,7 +115,7 @@ const std::vector <shared_ptr <component> > path::getChildComponents() {
void path::parseImpl(
const parsingContext& /* ctx */,
parsingContext& /* ctx */,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -84,7 +84,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -58,7 +58,7 @@ relay::relay(const relay& r)
*/
void relay::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -86,7 +86,7 @@ private:
protected:
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -67,7 +67,7 @@ text::~text() {
void text::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -401,7 +401,7 @@ shared_ptr <text> text::decodeAndUnfold(const string& in) {
}
shared_ptr <text> text::decodeAndUnfold(const parsingContext& ctx, const string& in) {
shared_ptr <text> text::decodeAndUnfold(parsingContext& ctx, const string& in) {
shared_ptr <text> t = make_shared <text>();
@ -417,7 +417,7 @@ text* text::decodeAndUnfold(const string& in, text* generateInExisting) {
}
text* text::decodeAndUnfold(const parsingContext& ctx, const string& in, text* generateInExisting) {
text* text::decodeAndUnfold(parsingContext& ctx, const string& in, text* generateInExisting) {
text* out = generateInExisting ? generateInExisting : new text();

View File

@ -229,7 +229,7 @@ public:
* @param in input string
* @return new text object
*/
static shared_ptr <text> decodeAndUnfold(const parsingContext& ctx, const string& in);
static shared_ptr <text> decodeAndUnfold(parsingContext& ctx, const string& in);
/** Decode and unfold text (RFC-2047), using the default parsing context.
*
@ -253,7 +253,7 @@ public:
* @return new text object or existing object if generateInExisting != NULL
*/
static text* decodeAndUnfold(
const parsingContext& ctx,
parsingContext& ctx,
const string& in,
text* generateInExisting
);
@ -265,7 +265,7 @@ protected:
// Component parsing & assembling
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -78,7 +78,7 @@ word::word(const string& buffer, const charset& charset, const string& lang)
shared_ptr <word> word::parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -255,7 +255,7 @@ shared_ptr <word> word::parseNext(
const std::vector <shared_ptr <word> > word::parseMultiple(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -282,7 +282,7 @@ const std::vector <shared_ptr <word> > word::parseMultiple(
void word::parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -294,7 +294,7 @@ void word::parseImpl(
void word::parseWithState(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,

View File

@ -198,7 +198,7 @@ public:
protected:
void parseImpl(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -213,7 +213,7 @@ protected:
) const;
void parseWithState(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -241,7 +241,7 @@ public:
private:
static shared_ptr <word> parseNext(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,
@ -250,7 +250,7 @@ private:
);
static const std::vector <shared_ptr <word> > parseMultiple(
const parsingContext& ctx,
parsingContext& ctx,
const string& buffer,
const size_t position,
const size_t end,