mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-30 17:59:21 +00:00
Changed rules to parse specific headers directly
This commit is contained in:
parent
6e0a7ae397
commit
4ec0c6eda4
3 changed files with 507 additions and 287 deletions
|
|
@ -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 ¶meter : *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 ¶meter : 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue