Changed rules to parse specific headers directly

This commit is contained in:
Mickaël Turnel 2018-04-25 15:02:44 +02:00 committed by Ghislain MARY
parent 6e0a7ae397
commit 4ec0c6eda4
3 changed files with 507 additions and 287 deletions

View file

@ -53,20 +53,10 @@ namespace Cpim {
HeaderNode () = default;
explicit HeaderNode (const Header &header) : mName(header.getName()), mValue(header.getValue()) {
// Generic header.
const GenericHeader *genericHeader = dynamic_cast<const GenericHeader *>(&header);
if (genericHeader) {
for (const auto &parameter : *genericHeader->getParameters())
mParameters += ";" + parameter.first + "=" + parameter.second;
return;
}
// Subject header.
const SubjectHeader *subjectHeader = dynamic_cast<const SubjectHeader *>(&header);
if (subjectHeader) {
const string language = subjectHeader->getLanguage();
if (!language.empty())
mParameters = ";lang=" + language;
}
}
@ -94,67 +84,425 @@ namespace Cpim {
mValue = value;
}
shared_ptr<Header> createHeader (bool force) const;
virtual shared_ptr<Header> createHeader () const;
virtual bool isValid () const;
private:
template<typename T>
shared_ptr<Header> createCoreHeader (bool force) const {
shared_ptr<T> header = make_shared<T>();
if (force)
header->force(mValue);
else if (!header->setValue(mValue)) {
lWarning() << "Unable to set value on core header: `" << mName << "` => `" << mValue << "`.";
return nullptr;
}
return header;
}
string mName;
string mValue;
string mParameters;
};
template<>
shared_ptr<Header> HeaderNode::createCoreHeader<SubjectHeader>(bool force) const {
shared_ptr<SubjectHeader> header = make_shared<SubjectHeader>();
const string language = mParameters.length() >= 6 ? mParameters.substr(6) : "";
if (force)
header->force(mValue, language);
else if (!header->setValue(mValue) || (!language.empty() && !header->setLanguage(language))) {
lWarning() << "Unable to set value on subject header: `" <<
mName << "` => `" << mValue << "`, `" << language << "`.";
return nullptr;
}
return header;
bool HeaderNode::isValid () const {
return !mName.empty() && !mValue.empty();
}
shared_ptr<Header> HeaderNode::createHeader (bool force = false) const {
static const unordered_map<string, shared_ptr<Header>(HeaderNode::*)(bool)const> reservedHandlers = {
{ "From", &HeaderNode::createCoreHeader<FromHeader> },
{ "To", &HeaderNode::createCoreHeader<ToHeader> },
{ "cc", &HeaderNode::createCoreHeader<CcHeader> },
{ "DateTime", &HeaderNode::createCoreHeader<DateTimeHeader> },
{ "Subject", &HeaderNode::createCoreHeader<SubjectHeader> },
{ "NS", &HeaderNode::createCoreHeader<NsHeader> },
{ "Require", &HeaderNode::createCoreHeader<RequireHeader> }
};
shared_ptr<Header> HeaderNode::createHeader () const {
if (!isValid())
return nullptr;
// Core Header.
const auto it = reservedHandlers.find(mName);
if (it != reservedHandlers.cend())
return (this->*it->second)(force);
// Generic Header
shared_ptr<GenericHeader> genericHeader = make_shared<GenericHeader>();
genericHeader->force(mName, mValue, mParameters);
genericHeader->setName(mName);
for (const auto &parameter : Utils::split(mParameters, ';')) {
size_t equalIndex = parameter.find('=');
if (equalIndex != string::npos)
genericHeader->addParameter(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1));
}
genericHeader->setValue(mValue);
return genericHeader;
}
// -------------------------------------------------------------------------
class ContactHeaderNode : public HeaderNode {
public:
ContactHeaderNode () = default;
string getFormalName () const {
return mFormalName;
}
void setFormalName (const string &formalName) {
mFormalName = formalName;
}
string getUri () const {
return mUri;
}
void setUri (const string &uri) {
mUri = uri;
}
bool isValid () const override;
private:
string mFormalName;
string mUri;
};
bool ContactHeaderNode::isValid () const {
return !mUri.empty();
}
// -------------------------------------------------------------------------
class FromHeaderNode : public ContactHeaderNode {
public:
FromHeaderNode () = default;
explicit FromHeaderNode (const Header &header) {
const FromHeader *fromHeader = dynamic_cast<const FromHeader *>(&header);
if (fromHeader) {
setFormalName(fromHeader->getFormalName());
setUri(fromHeader->getUri());
}
}
shared_ptr<Header> createHeader () const override;
};
shared_ptr<Header> FromHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<FromHeader>(getUri(), getFormalName());
}
// -------------------------------------------------------------------------
class ToHeaderNode : public ContactHeaderNode {
public:
ToHeaderNode () = default;
explicit ToHeaderNode (const Header &header) {
const ToHeader *toHeader = dynamic_cast<const ToHeader *>(&header);
if (toHeader) {
setFormalName(toHeader->getFormalName());
setUri(toHeader->getUri());
}
}
shared_ptr<Header> createHeader () const override;
};
shared_ptr<Header> ToHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<ToHeader>(getUri(), getFormalName());
}
// -------------------------------------------------------------------------
class CcHeaderNode : public ContactHeaderNode {
public:
CcHeaderNode () = default;
explicit CcHeaderNode (const Header &header) {
const CcHeader *ccHeader = dynamic_cast<const CcHeader *>(&header);
if (ccHeader) {
setFormalName(ccHeader->getFormalName());
setUri(ccHeader->getUri());
}
}
shared_ptr<Header> createHeader () const override;
};
shared_ptr<Header> CcHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<CcHeader>(getUri(), getFormalName());
}
// -------------------------------------------------------------------------
class DateTimeOffsetNode : public Node {
friend class DateTimeHeaderNode;
public:
DateTimeOffsetNode () {
mSign = "Z";
}
void setHour (const string &value) {
mHour = Utils::stoi(value);
}
void setMinute (const string &value) {
mMinute = Utils::stoi(value);
}
void setSign (const string &value) {
mSign = value;
}
private:
string mSign;
int mHour;
int mMinute;
};
class DateTimeHeaderNode : public HeaderNode {
public:
DateTimeHeaderNode () = default;
explicit DateTimeHeaderNode (const Header &header) {
const DateTimeHeader *dateTimeHeader = dynamic_cast<const DateTimeHeader *>(&header);
if (dateTimeHeader) {
setTime(dateTimeHeader->getTimeStruct());
setTimeOffset(dateTimeHeader->getTimeOffset());
setSignOffset(dateTimeHeader->getSignOffset());
}
}
struct tm getTime () const {
return mTime;
}
void setTime (const struct tm &time) {
mTime = time;
}
struct tm getTimeOffset () const {
return mTimeOffset;
}
void setTimeOffset (const struct tm &timeOffset) {
mTimeOffset = timeOffset;
}
string getSignOffset () const {
return mSignOffset;
}
void setSignOffset (const string &signOffset) {
mSignOffset = signOffset;
}
void setYear (const string &value) {
mTime.tm_year = Utils::stoi(value);
}
void setMonth (const string &value) {
mTime.tm_mon = Utils::stoi(value);
}
void setMonthDay (const string &value) {
mTime.tm_mday = Utils::stoi(value);
}
void setHour (const string &value) {
mTime.tm_hour = Utils::stoi(value);
}
void setMinute (const string &value) {
mTime.tm_min = Utils::stoi(value);
}
void setSecond (const string &value) {
mTime.tm_sec = Utils::stoi(value);
}
void setOffset (const shared_ptr<DateTimeOffsetNode> &offset) {
mTimeOffset.tm_hour = offset->mHour;
mTimeOffset.tm_min = offset->mMinute;
mSignOffset = offset->mSign;
}
bool isValid () const override;
shared_ptr<Header> createHeader() const override;
private:
tm mTime;
tm mTimeOffset;
string mSignOffset;
};
bool DateTimeHeaderNode::isValid () const {
static const int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// Check date.
const bool isLeapYear = (mTime.tm_year % 4 == 0 && mTime.tm_year % 100 != 0) || mTime.tm_year % 400 == 0;
if (mTime.tm_mon < 1 || mTime.tm_mon > 12)
return false;
if (mTime.tm_mday < 1 || (mTime.tm_mon == 2 && isLeapYear ? mTime.tm_mday > 29 : mTime.tm_mday > daysInMonth[mTime.tm_mon - 1]))
return false;
// Check time.
if (mTime.tm_hour > 24 || mTime.tm_min > 59 || mTime.tm_sec > 60)
return false;
// Check num offset.
if (mSignOffset != "Z") {
if (mTimeOffset.tm_hour > 24 || mTime.tm_min > 59)
return false;
}
return true;
}
shared_ptr<Header> DateTimeHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<DateTimeHeader>(getTime(), getTimeOffset(), getSignOffset());
}
// -------------------------------------------------------------------------
class SubjectHeaderNode : public HeaderNode {
public:
SubjectHeaderNode () = default;
explicit SubjectHeaderNode (const Header &header) {
const SubjectHeader *subjectHeader = dynamic_cast<const SubjectHeader *>(&header);
if (subjectHeader) {
setLanguage(subjectHeader->getLanguage());
setSubject(subjectHeader->getSubject());
}
}
string getLanguage () const {
return mLanguage;
}
void setLanguage (const string &language) {
mLanguage = language;
}
string getSubject () const {
return mSubject;
}
void setSubject (const string &subject) {
mSubject = subject;
}
bool isValid () const override;
shared_ptr<Header> createHeader () const override;
private:
string mLanguage;
string mSubject;
};
bool SubjectHeaderNode::isValid () const {
return !mSubject.empty();
}
shared_ptr<Header> SubjectHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<SubjectHeader>(getSubject(), getLanguage());
}
// -------------------------------------------------------------------------
class NsHeaderNode : public HeaderNode {
public:
NsHeaderNode () = default;
explicit NsHeaderNode (const Header &header) {
const NsHeader *nsHeader = dynamic_cast<const NsHeader *>(&header);
if (nsHeader) {
setPrefixName(nsHeader->getPrefixName());
setUri(nsHeader->getUri());
}
}
string getPrefixName () const {
return mPrefixName;
}
void setPrefixName (const string &prefixName) {
mPrefixName = prefixName;
}
string getUri () const {
return mUri;
}
void setUri (const string &uri) {
mUri = uri;
}
bool isValid () const override;
shared_ptr<Header> createHeader () const override;
private:
string mPrefixName;
string mUri;
};
bool NsHeaderNode::isValid () const {
return !mUri.empty();
}
shared_ptr<Header> NsHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<NsHeader>(getUri(), getPrefixName());
}
// -------------------------------------------------------------------------
class RequireHeaderNode : public HeaderNode {
public:
RequireHeaderNode () = default;
explicit RequireHeaderNode (const Header &header) {
const RequireHeader *requireHeader = dynamic_cast<const RequireHeader *>(&header);
if (requireHeader) {
for (const auto &header : requireHeader->getHeaderNames()) {
if (header != requireHeader->getHeaderNames().front())
mHeaderNames += ",";
mHeaderNames += header;
}
}
}
string getHeaderNames () const {
return mHeaderNames;
}
void setHeaderNames (const string &headerNames) {
mHeaderNames = headerNames;
}
bool isValid () const override;
shared_ptr<Header> createHeader () const override;
private:
string mHeaderNames;
};
bool RequireHeaderNode::isValid () const {
return !mHeaderNames.empty();
}
shared_ptr<Header> RequireHeaderNode::createHeader () const {
if (!isValid())
return nullptr;
return make_shared<RequireHeader>(mHeaderNames);
}
// -------------------------------------------------------------------------
class ListHeaderNode :
public Node,
public list<shared_ptr<HeaderNode> > {};
@ -163,57 +511,38 @@ namespace Cpim {
class MessageNode : public Node {
public:
void addHeaders (const shared_ptr<ListHeaderNode> &headers) {
mHeaders->push_back(headers);
void addMessageHeaders (const shared_ptr<ListHeaderNode> &headers) {
for (const auto &headerNode : *headers) {
mMessageHeaders.push_back(headerNode);
}
}
void addContentHeaders (const shared_ptr<ListHeaderNode> &headers) {
for (const auto &headerNode : *headers) {
mContentHeaders.push_back(headerNode);
}
}
// Warning: Call this function one time!
shared_ptr<Message> createMessage () const {
size_t size = mHeaders->size();
if (size < 2 || size > 3) { // TODO: Check that size is == 2
if (mContentHeaders.empty() || mMessageHeaders.empty()) {
lWarning() << "Bad headers lists size.";
return nullptr;
}
//TODO: Verify all headers from other namespaces
const shared_ptr<Message> message = make_shared<Message>();
// TODO: To remove
if (size == 3) {
const shared_ptr<ListHeaderNode> cpimHeaders = mHeaders->front();
if (find_if(cpimHeaders->cbegin(), cpimHeaders->cend(),
[](const shared_ptr<const HeaderNode> &headerNode) {
return Utils::iequals(headerNode->getName(), "content-type") && (ContentType(headerNode->getValue()) == ContentType::Cpim);
}) == cpimHeaders->cend()) {
lWarning() << "No MIME `Content-Type` found!";
// Add message headers.
for (const auto &headerNode : mMessageHeaders) {
const shared_ptr<const Header> header = headerNode->createHeader();
if (!header || !message->addMessageHeader(*header))
return nullptr;
}
// Add MIME headers.
for (const auto &headerNode : *cpimHeaders) {
const shared_ptr<const Header> header = headerNode->createHeader();
if (!header || !message->addCpimHeader(*header))
return nullptr;
}
// Add message headers.
for (const auto &headerNode : **(++mHeaders->cbegin())) {
const shared_ptr<const Header> header = headerNode->createHeader();
if (!header || !message->addMessageHeader(*header))
return nullptr;
}
}
// TODO: To remove
else {
// Add message headers.
for (const auto &headerNode : *mHeaders->front()) {
const shared_ptr<const Header> header = headerNode->createHeader();
if (!header || !message->addMessageHeader(*header))
return nullptr;
}
}
// Add content headers.
for (const auto &headerNode : *mHeaders->back()) {
for (const auto &headerNode : mContentHeaders) {
const shared_ptr<const Header> header = headerNode->createHeader();
if (!header || !message->addContentHeader(*header))
return nullptr;
@ -223,7 +552,8 @@ namespace Cpim {
}
private:
shared_ptr<list<shared_ptr<ListHeaderNode> > > mHeaders = make_shared<list<shared_ptr<ListHeaderNode> > >();
list<shared_ptr<HeaderNode>> mContentHeaders;
list<shared_ptr<HeaderNode>> mMessageHeaders;
};
}
@ -260,27 +590,64 @@ shared_ptr<Cpim::Message> Cpim::Parser::parseMessage (const string &input) {
typedef void (list<shared_ptr<HeaderNode> >::*pushPtr)(const shared_ptr<HeaderNode> &value);
belr::Parser<shared_ptr<Node> > parser(d->grammar);
parser.setHandler(
"Message", belr::make_fn(make_shared<MessageNode> )
)->setCollector(
"Headers", belr::make_sfn(&MessageNode::addHeaders)
);
parser.setHandler("Message", belr::make_fn(make_shared<MessageNode>))
->setCollector("Message-headers", belr::make_sfn(&MessageNode::addMessageHeaders))
->setCollector("Content-headers", belr::make_sfn(&MessageNode::addContentHeaders));
parser.setHandler(
"Headers", belr::make_fn(make_shared<ListHeaderNode> )
)->setCollector(
"Header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back))
);
parser.setHandler("Message-headers", belr::make_fn(make_shared<ListHeaderNode>))
->setCollector("Header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("From-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("To-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("DateTime-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("cc-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("Subject-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("NS-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)))
->setCollector("Require-header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)));
parser.setHandler(
"Header", belr::make_fn(make_shared<HeaderNode> )
)->setCollector(
"Header-name", belr::make_sfn(&HeaderNode::setName)
)->setCollector(
"Header-value", belr::make_sfn(&HeaderNode::setValue)
)->setCollector(
"Header-parameters", belr::make_sfn(&HeaderNode::setParameters)
);
parser.setHandler("Content-headers", belr::make_fn(make_shared<ListHeaderNode>))
->setCollector("Header", belr::make_sfn(static_cast<pushPtr>(&ListHeaderNode::push_back)));
parser.setHandler("Header", belr::make_fn(make_shared<HeaderNode>))
->setCollector("Header-name", belr::make_sfn(&HeaderNode::setName))
->setCollector("Header-value", belr::make_sfn(&HeaderNode::setValue))
->setCollector("Header-parameters", belr::make_sfn(&HeaderNode::setParameters));
parser.setHandler("From-header", belr::make_fn(make_shared<FromHeaderNode>))
->setCollector("Formal-name", belr::make_sfn(&FromHeaderNode::setFormalName))
->setCollector("URI", belr::make_sfn(&FromHeaderNode::setUri));
parser.setHandler("To-header", belr::make_fn(make_shared<ToHeaderNode>))
->setCollector("Formal-name", belr::make_sfn(&ToHeaderNode::setFormalName))
->setCollector("URI", belr::make_sfn(&ToHeaderNode::setUri));
parser.setHandler("cc-header", belr::make_fn(make_shared<CcHeaderNode>))
->setCollector("Formal-name", belr::make_sfn(&CcHeaderNode::setFormalName))
->setCollector("URI", belr::make_sfn(&CcHeaderNode::setUri));
parser.setHandler("DateTime-header", belr::make_fn(make_shared<DateTimeHeaderNode>))
->setCollector("date-fullyear", belr::make_sfn(&DateTimeHeaderNode::setYear))
->setCollector("date-month", belr::make_sfn(&DateTimeHeaderNode::setMonth))
->setCollector("date-mday", belr::make_sfn(&DateTimeHeaderNode::setMonthDay))
->setCollector("time-hour", belr::make_sfn(&DateTimeHeaderNode::setHour))
->setCollector("time-minute", belr::make_sfn(&DateTimeHeaderNode::setMinute))
->setCollector("time-second", belr::make_sfn(&DateTimeHeaderNode::setSecond))
->setCollector("time-offset", belr::make_sfn(&DateTimeHeaderNode::setOffset));
parser.setHandler("time-offset", belr::make_fn(make_shared<DateTimeOffsetNode>))
->setCollector("time-sign", belr::make_sfn(&DateTimeOffsetNode::setSign))
->setCollector("time-hour", belr::make_sfn(&DateTimeOffsetNode::setHour))
->setCollector("time-minute", belr::make_sfn(&DateTimeOffsetNode::setMinute));
parser.setHandler("Subject-header", belr::make_fn(make_shared<SubjectHeaderNode>))
->setCollector("Language-tag", belr::make_sfn(&SubjectHeaderNode::setLanguage))
->setCollector("Header-value", belr::make_sfn(&SubjectHeaderNode::setSubject));
parser.setHandler("Ns-header", belr::make_fn(make_shared<NsHeaderNode>))
->setCollector("Name-prefix", belr::make_sfn(&NsHeaderNode::setPrefixName))
->setCollector("URI", belr::make_sfn(&NsHeaderNode::setUri));
parser.setHandler("Require-header", belr::make_fn(make_shared<RequireHeaderNode>))
->setCollector("Require-header-value", belr::make_sfn(&RequireHeaderNode::setHeaderNames));
size_t parsedSize;
shared_ptr<Node> node = parser.parseInput("Message", input, &parsedSize);
@ -305,143 +672,28 @@ shared_ptr<Cpim::Message> Cpim::Parser::parseMessage (const string &input) {
// -----------------------------------------------------------------------------
shared_ptr<Cpim::Header> Cpim::Parser::cloneHeader (const Header &header) {
return HeaderNode(header).createHeader(true);
}
if (header.getName() == "From")
return FromHeaderNode(header).createHeader();
// -----------------------------------------------------------------------------
if (header.getName() == "To")
return ToHeaderNode(header).createHeader();
class EmptyObject {};
if (header.getName() == "cc")
return CcHeaderNode(header).createHeader();
static bool headerIsValid (const shared_ptr<belr::Grammar> &grammar, const string &input) {
belr::Parser<shared_ptr<EmptyObject> > parser(grammar);
parser.setHandler(
"Header", belr::make_fn(make_shared<EmptyObject> )
);
if (header.getName() == "DateTime")
return DateTimeHeaderNode(header).createHeader();
size_t parsedSize;
shared_ptr<EmptyObject> node = parser.parseInput("Header", input, &parsedSize);
return node && parsedSize == input.length();
}
if (header.getName() == "Subject")
return SubjectHeaderNode(header).createHeader();
bool Cpim::Parser::headerNameIsValid (const string &headerName) const {
L_D();
return headerIsValid(d->grammar, headerName + ": value\r\n");
}
if (header.getName() == "NS")
return NsHeaderNode(header).createHeader();
bool Cpim::Parser::headerValueIsValid (const string &headerValue) const {
L_D();
return headerIsValid(d->grammar, "key: " + headerValue + "\r\n");
}
if (header.getName() == "Require")
return RequireHeaderNode(header).createHeader();
bool Cpim::Parser::headerParameterIsValid (const string &headerParameter) const {
L_D();
return headerIsValid(d->grammar, "key:;" + headerParameter + " value\r\n");
}
// -----------------------------------------------------------------------------
static bool coreHeaderIsValid (
const shared_ptr<belr::Grammar> &grammar,
const string &headerName,
const string &headerValue,
const string &headerParams = string()
) {
const string mainRule = headerName + "-header";
belr::Parser<shared_ptr<EmptyObject> > parser(grammar);
parser.setHandler(
mainRule, belr::make_fn(make_shared<EmptyObject> )
);
const string input = headerName + ":" + headerParams + " " + headerValue;
size_t parsedSize;
shared_ptr<EmptyObject> node = parser.parseInput(mainRule, input, &parsedSize);
return node && parsedSize == input.length();
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::FromHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "From", headerValue);
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::ToHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "To", headerValue);
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::CcHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "cc", headerValue);
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::DateTimeHeader> (const string &headerValue) const {
static const int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
L_D();
if (!LinphonePrivate::coreHeaderIsValid(d->grammar, "DateTime", headerValue))
return false;
// Check date.
const int year = Utils::stoi(headerValue.substr(0, 4));
const bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
const int month = Utils::stoi(headerValue.substr(5, 2));
if (month < 1 || month > 12)
return false;
const int day = Utils::stoi(headerValue.substr(8, 2));
if (day < 1 || (month == 2 && isLeapYear ? day > 29 : day > daysInMonth[month - 1]))
return false;
// Check time.
if (
Utils::stoi(headerValue.substr(11, 2)) > 24 ||
Utils::stoi(headerValue.substr(14, 2)) > 59 ||
Utils::stoi(headerValue.substr(17, 2)) > 60
)
return false;
// Check num offset.
if (headerValue.back() != 'Z') {
size_t length = headerValue.length();
if (
Utils::stoi(headerValue.substr(length - 5, 2)) > 24 ||
Utils::stoi(headerValue.substr(length - 2, 2)) > 59
)
return false;
}
return true;
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::SubjectHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "Subject", headerValue);
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::NsHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "NS", headerValue);
}
template<>
bool Cpim::Parser::coreHeaderIsValid<Cpim::RequireHeader> (const string &headerValue) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "Require", headerValue);
}
// -----------------------------------------------------------------------------
bool Cpim::Parser::subjectHeaderLanguageIsValid (const string &language) const {
L_D();
return LinphonePrivate::coreHeaderIsValid(d->grammar, "Subject", "SubjectValue", ";lang=" + language);
return HeaderNode(header).createHeader();
}
LINPHONE_END_NAMESPACE

View file

@ -38,46 +38,12 @@ namespace Cpim {
std::shared_ptr<Header> cloneHeader (const Header &header);
bool headerNameIsValid (const std::string &headerName) const;
bool headerValueIsValid (const std::string &headerValue) const;
bool headerParameterIsValid (const std::string &headerParameter) const;
template<typename>
bool coreHeaderIsValid (const std::string &headerValue) const {
return false;
}
bool subjectHeaderLanguageIsValid (const std::string &language) const;
private:
Parser ();
L_DECLARE_PRIVATE(Parser);
L_DISABLE_COPY(Parser);
};
// ---------------------------------------------------------------------------
template<>
bool Parser::coreHeaderIsValid<FromHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<ToHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<CcHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<DateTimeHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<SubjectHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<NsHeader>(const std::string &headerValue) const;
template<>
bool Parser::coreHeaderIsValid<RequireHeader>(const std::string &headerValue) const;
}
LINPHONE_END_NAMESPACE

View file

@ -1,6 +1,7 @@
Message = Headers CRLF Headers CRLF [Headers CRLF]
Message = Message-headers CRLF Content-headers CRLF
Headers = *Header
Message-headers = *( From-header / To-header / DateTime-header / cc-header / Subject-header / NS-header / Require-header / Header )
Content-headers = *Header
Header = Header-name ":" Header-parameters SP Header-value CRLF
Header-name = [ Name-prefix "." ] Name
@ -16,25 +17,25 @@ Param-value = Token / Number / String
Header-value = *HEADERCHAR
From-header = %d70.114.111.109 ": " From-header-value
From-header = %d70.114.111.109 ": " From-header-value CRLF
From-header-value = [ Formal-name ] "<" URI ">"
To-header = %d84.111 ": " To-header-value
To-header = %d84.111 ": " To-header-value CRLF
To-header-value = [ Formal-name ] "<" URI ">"
DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value
DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value CRLF
DateTime-header-value = date-time
cc-header = %d99.99 ": " cc-header-value
cc-header = %d99.99 ": " cc-header-value CRLF
cc-header-value = [ Formal-name ] "<" URI ">"
Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value
Subject-header-value = [ ";" Lang-param ] SP *HEADERCHAR
Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value CRLF
Subject-header-value = [ ";" Lang-param ] SP Header-value
NS-header = %d78.83 ": " NS-header-value
NS-header = %d78.83 ": " NS-header-value CRLF
NS-header-value = [ Name-prefix SP ] "<" URI ">"
Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value
Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value CRLF
Require-header-value = Header-name *( "," Header-name )
Name = 1*NAMECHAR
@ -134,7 +135,8 @@ time-minute = 2DIGIT
time-second = 2DIGIT
time-secfrac = "." 1*DIGIT
time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
time-sign = "+" / "-"
time-numoffset = time-sign time-hour ":" time-minute
time-offset = "Z" / time-numoffset
partial-time = time-hour ":" time-minute ":" time-second [ time-secfrac ]