From 6e0a7ae397463ae5176098489f39d04d5c0bf36c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:02:03 +0200 Subject: [PATCH 01/15] Add specific headers --- src/chat/cpim/header/cpim-core-headers.cpp | 359 +++++++++++++++++-- src/chat/cpim/header/cpim-core-headers.h | 190 ++++++++-- src/chat/cpim/header/cpim-generic-header.cpp | 57 ++- src/chat/cpim/header/cpim-generic-header.h | 10 +- src/chat/cpim/header/cpim-header-p.h | 2 - src/chat/cpim/header/cpim-header.cpp | 16 - src/chat/cpim/header/cpim-header.h | 7 +- 7 files changed, 522 insertions(+), 119 deletions(-) diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp index 1a85d7e81..0da0b2721 100644 --- a/src/chat/cpim/header/cpim-core-headers.cpp +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -17,6 +17,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include + +#include "linphone/utils/utils.h" + +#include "logger/logger.h" + #include "chat/cpim/parser/cpim-parser.h" #include "cpim-header-p.h" @@ -28,50 +35,348 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -Cpim::CoreHeader::CoreHeader () : Header(*new HeaderPrivate) {} +class Cpim::ContactHeaderPrivate : public HeaderPrivate { +public: + string uri; + string formalName; +}; -Cpim::CoreHeader::CoreHeader (HeaderPrivate &p) : Header(p) {} +Cpim::ContactHeader::ContactHeader () : Header(*new ContactHeaderPrivate) {} -Cpim::CoreHeader::~CoreHeader () {} +Cpim::ContactHeader::ContactHeader (const string &uri, const string &formalName) : ContactHeader() { + setUri(uri); + setFormalName(formalName); +} -bool Cpim::CoreHeader::isValid () const { - return !getValue().empty(); +string Cpim::ContactHeader::getUri () const { + L_D(); + return d->uri; +} + +bool Cpim::ContactHeader::setUri (const string &uri) { + if (uri.empty()) + return false; + + L_D(); + d->uri = uri; + + return true; +} + +string Cpim::ContactHeader::getFormalName () const { + L_D(); + return d->formalName; +} + +bool Cpim::ContactHeader::setFormalName (const string &formalName) { + if (formalName.empty()) + return false; + + L_D(); + if (formalName.front() == '\"' && formalName.back() == '\"') + d->formalName = formalName.substr(1, formalName.size() - 2); + else if (formalName.back() == ' ') + d->formalName = formalName.substr(0, formalName.size() - 1); + else + d->formalName = formalName; + + return true; +} + +string Cpim::ContactHeader::getValue () const { + L_D(); + return "\"" + d->formalName + "\"" + "<" + d->uri + ">"; +} + +string Cpim::ContactHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; } // ----------------------------------------------------------------------------- -#define MAKE_CORE_HEADER_IMPL(CLASS_PREFIX) \ - bool Cpim::CLASS_PREFIX ## Header::setValue(const string &value) { \ - return Parser::getInstance()->coreHeaderIsValid(value) && Header::setValue(value); \ - } +class Cpim::MessageIdHeaderPrivate : public HeaderPrivate { +public: + string token; +}; -MAKE_CORE_HEADER_IMPL(From); -MAKE_CORE_HEADER_IMPL(To); -MAKE_CORE_HEADER_IMPL(Cc); -MAKE_CORE_HEADER_IMPL(DateTime); +Cpim::MessageIdHeader::MessageIdHeader () : Header(*new MessageIdHeaderPrivate) {} -MAKE_CORE_HEADER_IMPL(Ns); -MAKE_CORE_HEADER_IMPL(Require); +Cpim::MessageIdHeader::MessageIdHeader (const string &token) : MessageIdHeader() { + L_D(); + d->token = token; +} -#undef MAKE_CORE_HEADER_IMPL +string Cpim::MessageIdHeader::getToken () const { + L_D(); + return d->token; +} + +bool Cpim::MessageIdHeader::setToken (string token) { + if (token.empty()) + return false; + + L_D(); + d->token = token; + + return true; +} + +string Cpim::MessageIdHeader::getValue () const { + return getToken(); +} + +string Cpim::MessageIdHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} // ----------------------------------------------------------------------------- -void Cpim::CoreHeader::force (const string &value) { - Header::setValue(value); +class Cpim::DateTimeHeaderPrivate : public HeaderPrivate { +public: + tm timeT; + tm timeTOffset; + string signOffset; +}; + +Cpim::DateTimeHeader::DateTimeHeader () : Header(*new DateTimeHeaderPrivate) {} + +Cpim::DateTimeHeader::DateTimeHeader (time_t time) : DateTimeHeader() { + setTime(time); +} + +Cpim::DateTimeHeader::DateTimeHeader (const tm &time, const tm &timeOffset, const string &signOffset) : DateTimeHeader() { + setTime(time, timeOffset, signOffset); +} + +time_t Cpim::DateTimeHeader::getTime () const { + L_D(); + + tm result = d->timeT; + result.tm_year -= 1900; + result.tm_isdst = 0; + + if (d->signOffset == "+") { + result.tm_hour += d->timeTOffset.tm_hour; + result.tm_min += d->timeTOffset.tm_min; + + while (result.tm_min > 59) { + result.tm_hour++; + result.tm_min -= 60; + } + } + else if (d->signOffset == "-") { + result.tm_hour -= d->timeTOffset.tm_hour; + result.tm_hour -= d->timeTOffset.tm_min; + + while (result.tm_min < 0) { + result.tm_hour--; + result.tm_min += 60; + } + } + + return Utils::getTmAsTimeT(result); +} + +bool Cpim::DateTimeHeader::setTime (const time_t time) { + L_D(); + + d->signOffset = "Z"; + d->timeT = Utils::getTimeTAsTm(time); + d->timeT.tm_year += 1900; + + return true; +} + +bool Cpim::DateTimeHeader::setTime (const tm &time, const tm &timeOffset, const string &signOffset) { + L_D(); + + d->timeT = time; + d->timeTOffset = timeOffset; + d->signOffset = signOffset; + + return true; +} + +string Cpim::DateTimeHeader::getValue () const { + L_D(); + + stringstream ss; + ss << setfill('0') << setw(4) << d->timeT.tm_year << "-" + << setfill('0') << setw(2) << d->timeT.tm_mon << "-" + << setfill('0') << setw(2) << d->timeT.tm_mday << "T" + << setfill('0') << setw(2) << d->timeT.tm_hour << ":" + << setfill('0') << setw(2) << d->timeT.tm_min << ":" + << setfill('0') << setw(2) << d->timeT.tm_sec; + + ss << d->signOffset; + if (d->signOffset != "Z") + ss << setfill('0') << setw(2) << d->timeTOffset.tm_hour << ":" + << setfill('0') << setw(2) << d->timeTOffset.tm_min; + + return ss.str(); +} + +string Cpim::DateTimeHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +struct tm Cpim::DateTimeHeader::getTimeStruct () const { + L_D(); + return d->timeT; +} + +struct tm Cpim::DateTimeHeader::getTimeOffset () const { + L_D(); + return d->timeTOffset; +} + +string Cpim::DateTimeHeader::getSignOffset () const { + L_D(); + return d->signOffset; +} + +// ----------------------------------------------------------------------------- + +class Cpim::NsHeaderPrivate : public HeaderPrivate { +public: + string uri; + string prefixName; +}; + +Cpim::NsHeader::NsHeader () : Header(*new NsHeaderPrivate) {} + +Cpim::NsHeader::NsHeader (const string &uri, const string &prefixName) : NsHeader() { + L_D(); + d->uri = uri; + d->prefixName = prefixName; +} + +string Cpim::NsHeader::getUri () const { + L_D(); + return d->uri; +} + +bool Cpim::NsHeader::setUri (const string &uri) { + if (uri.empty()) + return false; + + L_D(); + d->uri = uri; + + return true; +} + +string Cpim::NsHeader::getPrefixName () const { + L_D(); + return d->prefixName; +} + +bool Cpim::NsHeader::setPrefixName (const string &prefixName) { + if (prefixName.empty()) + return false; + + L_D(); + d->prefixName = prefixName; + + return true; +} + +string Cpim::NsHeader::getValue () const { + L_D(); + + string ns; + if (!d->prefixName.empty()) + ns = d->prefixName + " "; + + return ns + "<" + d->uri + ">"; +} + +string Cpim::NsHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +// ----------------------------------------------------------------------------- + +class Cpim::RequireHeaderPrivate : public HeaderPrivate { +public: + list headerNames; +}; + +Cpim::RequireHeader::RequireHeader () : Header(*new RequireHeaderPrivate) {} + +Cpim::RequireHeader::RequireHeader (const string &headerNames) : RequireHeader() { + L_D(); + for (const string &header : Utils::split(headerNames, ",")) { + d->headerNames.push_back(header); + } +} + +Cpim::RequireHeader::RequireHeader (const list &headerNames) : RequireHeader() { + L_D(); + d->headerNames = headerNames; +} + +list Cpim::RequireHeader::getHeaderNames () const { + L_D(); + return d->headerNames; +} + +bool Cpim::RequireHeader::addHeaderName (const string &headerName) { + if (headerName.empty()) + return false; + + L_D(); + d->headerNames.push_back(headerName); + + return true; +} + +string Cpim::RequireHeader::getValue () const { + L_D(); + + string requires; + for (const string &header : d->headerNames) { + if (header != d->headerNames.front()) + requires += ","; + requires += header; + } + + return requires; +} + +string Cpim::RequireHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; } // ----------------------------------------------------------------------------- class Cpim::SubjectHeaderPrivate : public HeaderPrivate { public: + string subject; string language; }; -Cpim::SubjectHeader::SubjectHeader () : CoreHeader(*new SubjectHeaderPrivate) {} +Cpim::SubjectHeader::SubjectHeader () : Header(*new SubjectHeaderPrivate) {} -bool Cpim::SubjectHeader::setValue (const string &value) { - return Parser::getInstance()->coreHeaderIsValid(value) && Header::setValue(value); +Cpim::SubjectHeader::SubjectHeader (const string &subject, const string &language) : SubjectHeader() { + L_D(); + d->subject = subject; + d->language = language; +} + +string Cpim::SubjectHeader::getSubject () const { + L_D(); + return d->subject; +} + +bool Cpim::SubjectHeader::setSubject (const string &subject) { + if (subject.empty()) + return false; + + L_D(); + d->subject = subject; + + return true; } string Cpim::SubjectHeader::getLanguage () const { @@ -80,7 +385,7 @@ string Cpim::SubjectHeader::getLanguage () const { } bool Cpim::SubjectHeader::setLanguage (const string &language) { - if (!language.empty() && !Parser::getInstance()->subjectHeaderLanguageIsValid(language)) + if (!language.empty()) return false; L_D(); @@ -89,20 +394,18 @@ bool Cpim::SubjectHeader::setLanguage (const string &language) { return true; } -string Cpim::SubjectHeader::asString () const { +string Cpim::SubjectHeader::getValue () const { L_D(); string languageParam; if (!d->language.empty()) languageParam = ";lang=" + d->language; - return getName() + ":" + languageParam + " " + getValue() + "\r\n"; + return languageParam + " " + d->subject; } -void Cpim::SubjectHeader::force (const string &value, const string &language) { - L_D(); - CoreHeader::force(value); - d->language = language; +string Cpim::SubjectHeader::asString () const { + return getName() + ":" + getValue() + "\r\n"; } LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/header/cpim-core-headers.h b/src/chat/cpim/header/cpim-core-headers.h index 1c7321ce4..89971cac0 100644 --- a/src/chat/cpim/header/cpim-core-headers.h +++ b/src/chat/cpim/header/cpim-core-headers.h @@ -20,60 +20,188 @@ #ifndef _L_CPIM_CORE_HEADERS_H_ #define _L_CPIM_CORE_HEADERS_H_ +#include +#include + #include "cpim-header.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -#define MAKE_CORE_HEADER(CLASS_PREFIX, NAME) \ - class LINPHONE_PUBLIC CLASS_PREFIX ## Header : public CoreHeader { \ +#define MAKE_CONTACT_HEADER(CLASS_PREFIX, NAME) \ + class LINPHONE_PUBLIC CLASS_PREFIX ## Header : public ContactHeader { \ public: \ - CLASS_PREFIX ## Header() = default; \ - inline std::string getName() const override { \ + CLASS_PREFIX ## Header () = default; \ + CLASS_PREFIX ## Header (const std::string &uri, const std::string &formalName = "") : ContactHeader (uri, formalName) {} \ + inline std::string getName () const override { \ return NAME; \ } \ - bool setValue(const std::string &value) override; \ private: \ L_DISABLE_COPY(CLASS_PREFIX ## Header); \ }; namespace Cpim { - class HeaderNode; + class DateTimeHeaderNode; // ------------------------------------------------------------------------- - // Generic core header. + // Specific Contact headers declaration. // ------------------------------------------------------------------------- - class LINPHONE_PUBLIC CoreHeader : public Header { - friend class HeaderNode; + class ContactHeaderPrivate; + class LINPHONE_PUBLIC ContactHeader : public Header { public: - CoreHeader (); + ContactHeader (); - virtual ~CoreHeader () = 0; + ContactHeader (const std::string &uri, const std::string &formalName = ""); - bool isValid () const override; + std::string getUri () const; + bool setUri (const std::string &uri); - protected: - explicit CoreHeader (HeaderPrivate &p); + std::string getFormalName () const; + bool setFormalName (const std::string &formalName); - void force (const std::string &value); + std::string getValue () const override; + + std::string asString () const override; private: - L_DISABLE_COPY(CoreHeader); + L_DECLARE_PRIVATE(ContactHeader); + L_DISABLE_COPY(ContactHeader); }; // ------------------------------------------------------------------------- - // Core headers. + + MAKE_CONTACT_HEADER(From, "From"); + MAKE_CONTACT_HEADER(To, "To"); + MAKE_CONTACT_HEADER(Cc, "cc"); + + // ------------------------------------------------------------------------- + // Specific MessageId declaration. // ------------------------------------------------------------------------- - MAKE_CORE_HEADER(From, "From"); - MAKE_CORE_HEADER(To, "To"); - MAKE_CORE_HEADER(Cc, "cc"); - MAKE_CORE_HEADER(DateTime, "DateTime"); - MAKE_CORE_HEADER(Ns, "NS"); - MAKE_CORE_HEADER(Require, "Require"); + class MessageIdHeaderPrivate; + + class LINPHONE_PUBLIC MessageIdHeader : public Header { + public: + MessageIdHeader (); + + MessageIdHeader (const std::string &token); + + inline std::string getName() const override { + return "Message-ID"; + } + + std::string getToken () const; + bool setToken (std::string token); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(MessageIdHeader); + L_DISABLE_COPY(MessageIdHeader); + }; + + // ------------------------------------------------------------------------- + // Specific DateTime declaration. + // ------------------------------------------------------------------------- + + class DateTimeHeaderPrivate; + + class LINPHONE_PUBLIC DateTimeHeader : public Header { + friend class DateTimeHeaderNode; + + public: + DateTimeHeader (); + + DateTimeHeader (time_t time); + + DateTimeHeader (const tm &time, const tm &timeOffset, const std::string &signOffset); + + inline std::string getName () const override { + return "DateTime"; + } + + time_t getTime () const; + bool setTime (const time_t time); + + bool setTime (const tm &time, const tm &timeOffset, const std::string &signOffset); + + std::string getValue () const override; + + std::string asString () const override; + + private: + tm getTimeStruct () const; + tm getTimeOffset () const; + std::string getSignOffset () const; + + L_DECLARE_PRIVATE(DateTimeHeader); + L_DISABLE_COPY(DateTimeHeader); + }; + + // ------------------------------------------------------------------------- + // Specific Ns declaration. + // ------------------------------------------------------------------------- + + class NsHeaderPrivate; + + class LINPHONE_PUBLIC NsHeader : public Header { + public: + NsHeader (); + + NsHeader (const std::string &uri, const std::string &prefixName = ""); + + inline std::string getName () const override { + return "NS"; + } + + std::string getPrefixName () const; + bool setPrefixName (const std::string &prefixName); + + std::string getUri () const; + bool setUri (const std::string &uri); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(NsHeader); + L_DISABLE_COPY(NsHeader); + }; + + // ------------------------------------------------------------------------- + // Specific Require declaration. + // ------------------------------------------------------------------------- + + class RequireHeaderPrivate; + + class LINPHONE_PUBLIC RequireHeader : public Header { + public: + RequireHeader (); + + RequireHeader (const std::string &headerNames); + RequireHeader (const std::list &headerNames); + + inline std::string getName () const override { + return "Require"; + } + + std::list getHeaderNames () const; + bool addHeaderName (const std::string &headerName); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(RequireHeader); + L_DISABLE_COPY(RequireHeader); + }; // ------------------------------------------------------------------------- // Specific Subject declaration. @@ -81,25 +209,25 @@ namespace Cpim { class SubjectHeaderPrivate; - class LINPHONE_PUBLIC SubjectHeader : public CoreHeader { - friend class HeaderNode; - + class LINPHONE_PUBLIC SubjectHeader : public Header { public: SubjectHeader (); + SubjectHeader (const std::string &subject, const std::string &language = ""); + inline std::string getName () const override { return "Subject"; } - bool setValue (const std::string &value) override; + std::string getSubject () const; + bool setSubject (const std::string &subject); std::string getLanguage () const; bool setLanguage (const std::string &language); - std::string asString () const override; + std::string getValue () const override; - protected: - void force (const std::string &value, const std::string &language); + std::string asString () const override; private: L_DECLARE_PRIVATE(SubjectHeader); @@ -107,7 +235,7 @@ namespace Cpim { }; } -#undef MAKE_CORE_HEADER +#undef MAKE_CONTACT_HEADER LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/header/cpim-generic-header.cpp b/src/chat/cpim/header/cpim-generic-header.cpp index 67a7b81d4..8e4bc57ab 100644 --- a/src/chat/cpim/header/cpim-generic-header.cpp +++ b/src/chat/cpim/header/cpim-generic-header.cpp @@ -37,11 +37,24 @@ public: GenericHeaderPrivate () : parameters(make_shared > >()) {} string name; + string value; shared_ptr > > parameters; }; Cpim::GenericHeader::GenericHeader () : Header(*new GenericHeaderPrivate) {} +Cpim::GenericHeader::GenericHeader (string name, string value, string parameters) : GenericHeader() { + L_D(); + d->name = name; + d->value = value; + + for (const auto ¶meter : Utils::split(parameters, ';')) { + size_t equalIndex = parameter.find('='); + if (equalIndex != string::npos) + d->parameters->push_back(make_pair(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1))); + } +} + string Cpim::GenericHeader::getName () const { L_D(); return d->name; @@ -54,18 +67,26 @@ bool Cpim::GenericHeader::setName (const string &name) { "From", "To", "cc", "DateTime", "Subject", "NS", "Require" }; - if ( - reserved.find(name) != reserved.end() || - !Parser::getInstance()->headerNameIsValid(name) - ) + if (reserved.find(name) != reserved.end()) return false; d->name = name; return true; } +string Cpim::GenericHeader::getValue () const { + L_D(); + return d->value; +} + bool Cpim::GenericHeader::setValue (const string &value) { - return Parser::getInstance()->headerValueIsValid(value) && Header::setValue(value); + if (value.empty()) + return false; + + L_D(); + d->value = value; + + return true; } Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { @@ -75,10 +96,6 @@ Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { bool Cpim::GenericHeader::addParameter (const string &key, const string &value) { L_D(); - - if (!Parser::getInstance()->headerParameterIsValid(key + "=" + value)) - return false; - d->parameters->push_back(make_pair(key, value)); return true; } @@ -88,11 +105,6 @@ void Cpim::GenericHeader::removeParameter (const string &key, const string &valu d->parameters->remove(make_pair(key, value)); } -bool Cpim::GenericHeader::isValid () const { - L_D(); - return !d->name.empty() && !getValue().empty(); -} - string Cpim::GenericHeader::asString () const { L_D(); @@ -103,21 +115,4 @@ string Cpim::GenericHeader::asString () const { return d->name + ":" + parameters + " " + getValue() + "\r\n"; } -// ----------------------------------------------------------------------------- - -void Cpim::GenericHeader::force (const string &name, const string &value, const string ¶meters) { - L_D(); - - // Set name/value. - d->name = name; - Header::setValue(value); - - // Parse and build parameters list. - for (const auto ¶meter : Utils::split(parameters, ';')) { - size_t equalIndex = parameter.find('='); - if (equalIndex != string::npos) - d->parameters->push_back(make_pair(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1))); - } -} - LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/header/cpim-generic-header.h b/src/chat/cpim/header/cpim-generic-header.h index 2433a9cb7..711b3c641 100644 --- a/src/chat/cpim/header/cpim-generic-header.h +++ b/src/chat/cpim/header/cpim-generic-header.h @@ -38,10 +38,13 @@ namespace Cpim { public: GenericHeader (); + GenericHeader (std::string name, std::string value, std::string parameters = ""); + std::string getName () const override; bool setName (const std::string &name); - bool setValue (const std::string &value) override; + std::string getValue () const override; + bool setValue (const std::string &value); typedef std::shared_ptr > > ParameterList; @@ -49,13 +52,8 @@ namespace Cpim { bool addParameter (const std::string &key, const std::string &value); void removeParameter (const std::string &key, const std::string &value); - bool isValid () const override; - std::string asString () const override; - protected: - void force (const std::string &name, const std::string &value, const std::string ¶meters); - private: L_DECLARE_PRIVATE(GenericHeader); L_DISABLE_COPY(GenericHeader); diff --git a/src/chat/cpim/header/cpim-header-p.h b/src/chat/cpim/header/cpim-header-p.h index 048e91309..2aaea0acb 100644 --- a/src/chat/cpim/header/cpim-header-p.h +++ b/src/chat/cpim/header/cpim-header-p.h @@ -30,8 +30,6 @@ LINPHONE_BEGIN_NAMESPACE namespace Cpim { class HeaderPrivate : public ObjectPrivate { private: - std::string value; - L_DECLARE_PUBLIC(Header); }; } diff --git a/src/chat/cpim/header/cpim-header.cpp b/src/chat/cpim/header/cpim-header.cpp index 8141d7811..6a3b83470 100644 --- a/src/chat/cpim/header/cpim-header.cpp +++ b/src/chat/cpim/header/cpim-header.cpp @@ -29,20 +29,4 @@ LINPHONE_BEGIN_NAMESPACE Cpim::Header::Header (HeaderPrivate &p) : Object(p) {} -string Cpim::Header::getValue () const { - L_D(); - return d->value; -} - -bool Cpim::Header::setValue (const string &value) { - L_D(); - d->value = value; - return true; -} - -string Cpim::Header::asString () const { - L_D(); - return getName() + ": " + d->value + "\r\n"; -} - LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/header/cpim-header.h b/src/chat/cpim/header/cpim-header.h index 13dcfdce8..f71d115b0 100644 --- a/src/chat/cpim/header/cpim-header.h +++ b/src/chat/cpim/header/cpim-header.h @@ -35,12 +35,9 @@ namespace Cpim { virtual std::string getName () const = 0; - std::string getValue () const; - virtual bool setValue (const std::string &value); + virtual std::string getValue () const = 0; - virtual bool isValid () const = 0; - - virtual std::string asString () const; + virtual std::string asString () const = 0; protected: explicit Header (HeaderPrivate &p); From 4ec0c6eda4f267a65fb5381cf7792652c7122027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:02:44 +0200 Subject: [PATCH 02/15] Changed rules to parse specific headers directly --- src/chat/cpim/parser/cpim-parser.cpp | 736 ++++++++++++++++++--------- src/chat/cpim/parser/cpim-parser.h | 34 -- src/chat/cpim/parser/cpim-rules | 24 +- 3 files changed, 507 insertions(+), 287 deletions(-) diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp index 3d34fcd71..a918a802a 100644 --- a/src/chat/cpim/parser/cpim-parser.cpp +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -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(&header); if (genericHeader) { for (const auto ¶meter : *genericHeader->getParameters()) mParameters += ";" + parameter.first + "=" + parameter.second; - return; - } - - // Subject header. - const SubjectHeader *subjectHeader = dynamic_cast(&header); - if (subjectHeader) { - const string language = subjectHeader->getLanguage(); - if (!language.empty()) - mParameters = ";lang=" + language; } } @@ -94,67 +84,425 @@ namespace Cpim { mValue = value; } - shared_ptr
createHeader (bool force) const; + virtual shared_ptr
createHeader () const; + + virtual bool isValid () const; private: - template - shared_ptr
createCoreHeader (bool force) const { - shared_ptr header = make_shared(); - 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
HeaderNode::createCoreHeader(bool force) const { - shared_ptr header = make_shared(); - 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
HeaderNode::createHeader (bool force = false) const { - static const unordered_map(HeaderNode::*)(bool)const> reservedHandlers = { - { "From", &HeaderNode::createCoreHeader }, - { "To", &HeaderNode::createCoreHeader }, - { "cc", &HeaderNode::createCoreHeader }, - { "DateTime", &HeaderNode::createCoreHeader }, - { "Subject", &HeaderNode::createCoreHeader }, - { "NS", &HeaderNode::createCoreHeader }, - { "Require", &HeaderNode::createCoreHeader } - }; + shared_ptr
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 = make_shared(); - 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(&header); + if (fromHeader) { + setFormalName(fromHeader->getFormalName()); + setUri(fromHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
FromHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getFormalName()); + } + + // ------------------------------------------------------------------------- + + class ToHeaderNode : public ContactHeaderNode { + public: + ToHeaderNode () = default; + + explicit ToHeaderNode (const Header &header) { + const ToHeader *toHeader = dynamic_cast(&header); + if (toHeader) { + setFormalName(toHeader->getFormalName()); + setUri(toHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
ToHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getFormalName()); + } + + // ------------------------------------------------------------------------- + + class CcHeaderNode : public ContactHeaderNode { + public: + CcHeaderNode () = default; + + explicit CcHeaderNode (const Header &header) { + const CcHeader *ccHeader = dynamic_cast(&header); + if (ccHeader) { + setFormalName(ccHeader->getFormalName()); + setUri(ccHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
CcHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(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(&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 &offset) { + mTimeOffset.tm_hour = offset->mHour; + mTimeOffset.tm_min = offset->mMinute; + mSignOffset = offset->mSign; + } + + bool isValid () const override; + + shared_ptr
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
DateTimeHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getTime(), getTimeOffset(), getSignOffset()); + } + + // ------------------------------------------------------------------------- + + class SubjectHeaderNode : public HeaderNode { + public: + SubjectHeaderNode () = default; + + explicit SubjectHeaderNode (const Header &header) { + const SubjectHeader *subjectHeader = dynamic_cast(&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
createHeader () const override; + + private: + string mLanguage; + string mSubject; + }; + + bool SubjectHeaderNode::isValid () const { + return !mSubject.empty(); + } + + shared_ptr
SubjectHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getSubject(), getLanguage()); + } + + // ------------------------------------------------------------------------- + + class NsHeaderNode : public HeaderNode { + public: + NsHeaderNode () = default; + + explicit NsHeaderNode (const Header &header) { + const NsHeader *nsHeader = dynamic_cast(&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
createHeader () const override; + + private: + string mPrefixName; + string mUri; + }; + + bool NsHeaderNode::isValid () const { + return !mUri.empty(); + } + + shared_ptr
NsHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getPrefixName()); + } + + // ------------------------------------------------------------------------- + + class RequireHeaderNode : public HeaderNode { + public: + RequireHeaderNode () = default; + + explicit RequireHeaderNode (const Header &header) { + const RequireHeader *requireHeader = dynamic_cast(&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
createHeader () const override; + + private: + string mHeaderNames; + }; + + bool RequireHeaderNode::isValid () const { + return !mHeaderNames.empty(); + } + + shared_ptr
RequireHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(mHeaderNames); + } + + // ------------------------------------------------------------------------- + class ListHeaderNode : public Node, public list > {}; @@ -163,57 +511,38 @@ namespace Cpim { class MessageNode : public Node { public: - void addHeaders (const shared_ptr &headers) { - mHeaders->push_back(headers); + void addMessageHeaders (const shared_ptr &headers) { + for (const auto &headerNode : *headers) { + mMessageHeaders.push_back(headerNode); + } + } + + void addContentHeaders (const shared_ptr &headers) { + for (const auto &headerNode : *headers) { + mContentHeaders.push_back(headerNode); + } } // Warning: Call this function one time! shared_ptr 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 = make_shared(); - // TODO: To remove - if (size == 3) { - const shared_ptr cpimHeaders = mHeaders->front(); - if (find_if(cpimHeaders->cbegin(), cpimHeaders->cend(), - [](const shared_ptr &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 header = headerNode->createHeader(); + if (!header || !message->addMessageHeader(*header)) return nullptr; - } - - // Add MIME headers. - for (const auto &headerNode : *cpimHeaders) { - const shared_ptr header = headerNode->createHeader(); - if (!header || !message->addCpimHeader(*header)) - return nullptr; - } - - // Add message headers. - for (const auto &headerNode : **(++mHeaders->cbegin())) { - const shared_ptr 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 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 header = headerNode->createHeader(); if (!header || !message->addContentHeader(*header)) return nullptr; @@ -223,7 +552,8 @@ namespace Cpim { } private: - shared_ptr > > mHeaders = make_shared > >(); + list> mContentHeaders; + list> mMessageHeaders; }; } @@ -260,27 +590,64 @@ shared_ptr Cpim::Parser::parseMessage (const string &input) { typedef void (list >::*pushPtr)(const shared_ptr &value); belr::Parser > parser(d->grammar); - parser.setHandler( - "Message", belr::make_fn(make_shared ) - )->setCollector( - "Headers", belr::make_sfn(&MessageNode::addHeaders) - ); + parser.setHandler("Message", belr::make_fn(make_shared)) + ->setCollector("Message-headers", belr::make_sfn(&MessageNode::addMessageHeaders)) + ->setCollector("Content-headers", belr::make_sfn(&MessageNode::addContentHeaders)); - parser.setHandler( - "Headers", belr::make_fn(make_shared ) - )->setCollector( - "Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back)) - ); + parser.setHandler("Message-headers", belr::make_fn(make_shared)) + ->setCollector("Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("From-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("To-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("DateTime-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("cc-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("Subject-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("NS-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("Require-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))); - parser.setHandler( - "Header", belr::make_fn(make_shared ) - )->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)) + ->setCollector("Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))); + + parser.setHandler("Header", belr::make_fn(make_shared)) + ->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)) + ->setCollector("Formal-name", belr::make_sfn(&FromHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&FromHeaderNode::setUri)); + + parser.setHandler("To-header", belr::make_fn(make_shared)) + ->setCollector("Formal-name", belr::make_sfn(&ToHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&ToHeaderNode::setUri)); + + parser.setHandler("cc-header", belr::make_fn(make_shared)) + ->setCollector("Formal-name", belr::make_sfn(&CcHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&CcHeaderNode::setUri)); + + parser.setHandler("DateTime-header", belr::make_fn(make_shared)) + ->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)) + ->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)) + ->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)) + ->setCollector("Name-prefix", belr::make_sfn(&NsHeaderNode::setPrefixName)) + ->setCollector("URI", belr::make_sfn(&NsHeaderNode::setUri)); + + parser.setHandler("Require-header", belr::make_fn(make_shared)) + ->setCollector("Require-header-value", belr::make_sfn(&RequireHeaderNode::setHeaderNames)); size_t parsedSize; shared_ptr node = parser.parseInput("Message", input, &parsedSize); @@ -305,143 +672,28 @@ shared_ptr Cpim::Parser::parseMessage (const string &input) { // ----------------------------------------------------------------------------- shared_ptr 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 &grammar, const string &input) { - belr::Parser > parser(grammar); - parser.setHandler( - "Header", belr::make_fn(make_shared ) - ); + if (header.getName() == "DateTime") + return DateTimeHeaderNode(header).createHeader(); - size_t parsedSize; - shared_ptr 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 &grammar, - const string &headerName, - const string &headerValue, - const string &headerParams = string() -) { - const string mainRule = headerName + "-header"; - - belr::Parser > parser(grammar); - parser.setHandler( - mainRule, belr::make_fn(make_shared ) - ); - - const string input = headerName + ":" + headerParams + " " + headerValue; - - size_t parsedSize; - shared_ptr node = parser.parseInput(mainRule, input, &parsedSize); - return node && parsedSize == input.length(); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (const string &headerValue) const { - L_D(); - return LinphonePrivate::coreHeaderIsValid(d->grammar, "From", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (const string &headerValue) const { - L_D(); - return LinphonePrivate::coreHeaderIsValid(d->grammar, "To", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (const string &headerValue) const { - L_D(); - return LinphonePrivate::coreHeaderIsValid(d->grammar, "cc", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (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 (const string &headerValue) const { - L_D(); - return LinphonePrivate::coreHeaderIsValid(d->grammar, "Subject", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (const string &headerValue) const { - L_D(); - return LinphonePrivate::coreHeaderIsValid(d->grammar, "NS", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid (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 diff --git a/src/chat/cpim/parser/cpim-parser.h b/src/chat/cpim/parser/cpim-parser.h index bdb32f7e4..076400841 100644 --- a/src/chat/cpim/parser/cpim-parser.h +++ b/src/chat/cpim/parser/cpim-parser.h @@ -38,46 +38,12 @@ namespace Cpim { std::shared_ptr
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 - 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(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; } LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/parser/cpim-rules b/src/chat/cpim/parser/cpim-rules index bba8e019c..d2837db2a 100644 --- a/src/chat/cpim/parser/cpim-rules +++ b/src/chat/cpim/parser/cpim-rules @@ -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 ] From b687bf9d684651c77a5a191d56b61b30686ac21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:03:01 +0200 Subject: [PATCH 03/15] Removed CPIM headers --- src/chat/cpim/message/cpim-message.cpp | 50 ------------------- src/chat/cpim/message/cpim-message.h | 8 --- .../modifier/cpim-chat-message-modifier.cpp | 33 +++++------- .../modifier/cpim-chat-message-modifier.h | 3 +- 4 files changed, 14 insertions(+), 80 deletions(-) diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 123ef6c66..d6fb78080 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -38,7 +38,6 @@ class Cpim::MessagePrivate : public ObjectPrivate { public: typedef list > PrivHeaderList; - shared_ptr cpimHeaders = make_shared(); // TODO: Remove this useless variable shared_ptr messageHeaders = make_shared(); shared_ptr contentHeaders = make_shared(); string content; @@ -48,30 +47,6 @@ Cpim::Message::Message () : Object(*new MessagePrivate) {} // ----------------------------------------------------------------------------- -Cpim::Message::HeaderList Cpim::Message::getCpimHeaders () const { - L_D(); - return d->cpimHeaders; -} - -bool Cpim::Message::addCpimHeader (const Header &cpimHeader) { - L_D(); - - if (!cpimHeader.isValid()) - return false; - - d->cpimHeaders->push_back(Parser::getInstance()->cloneHeader(cpimHeader)); - return true; -} - -void Cpim::Message::removeCpimHeader (const Header &cpimHeader) { - L_D(); - d->cpimHeaders->remove_if([&cpimHeader](const shared_ptr &header) { - return cpimHeader.getName() == header->getName() && cpimHeader.getValue() == header->getValue(); - }); -} - -// ----------------------------------------------------------------------------- - Cpim::Message::HeaderList Cpim::Message::getMessageHeaders () const { L_D(); return d->messageHeaders; @@ -80,9 +55,6 @@ Cpim::Message::HeaderList Cpim::Message::getMessageHeaders () const { bool Cpim::Message::addMessageHeader (const Header &messageHeader) { L_D(); - if (!messageHeader.isValid()) - return false; - d->messageHeaders->push_back(Parser::getInstance()->cloneHeader(messageHeader)); return true; } @@ -104,9 +76,6 @@ Cpim::Message::HeaderList Cpim::Message::getContentHeaders () const { bool Cpim::Message::addContentHeader (const Header &contentHeader) { L_D(); - if (!contentHeader.isValid()) - return false; - d->contentHeaders->push_back(Parser::getInstance()->cloneHeader(contentHeader)); return true; } @@ -133,29 +102,10 @@ bool Cpim::Message::setContent (const string &content) { // ----------------------------------------------------------------------------- -bool Cpim::Message::isValid () const { - L_D(); - - return find_if(d->cpimHeaders->cbegin(), d->cpimHeaders->cend(), - [](const shared_ptr &header) { - return Utils::iequals(header->getName(), "content-type") && (ContentType(header->getValue()) == ContentType::Cpim); - }) != d->cpimHeaders->cend(); -} - -// ----------------------------------------------------------------------------- - string Cpim::Message::asString () const { L_D(); string output; - // TODO: Remove cpimHeaders - if (d->cpimHeaders->size() > 0) { - for (const auto &cpimHeader : *d->cpimHeaders) - output += cpimHeader->asString(); - output += "\r\n"; - } - // TODO Remove cpimHeaders - if (d->messageHeaders->size() > 0) { for (const auto &messageHeader : *d->messageHeaders) output += messageHeader->asString(); diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h index c7778c929..7c4ce693c 100644 --- a/src/chat/cpim/message/cpim-message.h +++ b/src/chat/cpim/message/cpim-message.h @@ -36,12 +36,6 @@ namespace Cpim { typedef std::shared_ptr > > HeaderList; - // TODO: Remove these useless methods - HeaderList getCpimHeaders () const; - bool addCpimHeader (const Header &cpimHeader); - void removeCpimHeader (const Header &cpimHeader); - // TODO: Remove these useless methods - HeaderList getMessageHeaders () const; bool addMessageHeader (const Header &messageHeader); void removeMessageHeader (const Header &messageHeader); @@ -53,8 +47,6 @@ namespace Cpim { std::string getContent () const; bool setContent (const std::string &content); - bool isValid () const; // TODO: Remove this useless method - std::string asString () const; static std::shared_ptr createFromString (const std::string &str); diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 9c7d48f6b..04c73f9c1 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -38,11 +38,9 @@ LINPHONE_BEGIN_NAMESPACE ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr &message, int &errorCode) { Cpim::Message cpimMessage; - Cpim::FromHeader cpimFromHeader; - cpimFromHeader.setValue(cpimAddressAsString(message->getFromAddress())); + Cpim::FromHeader cpimFromHeader(cpimAddressUri(message->getFromAddress()), cpimAddressDisplayName(message->getFromAddress())); cpimMessage.addMessageHeader(cpimFromHeader); - Cpim::ToHeader cpimToHeader; - cpimToHeader.setValue(cpimAddressAsString(message->getToAddress())); + Cpim::ToHeader cpimToHeader(cpimAddressUri(message->getToAddress()), cpimAddressDisplayName(message->getToAddress())); cpimMessage.addMessageHeader(cpimToHeader); if (message->getPrivate()->getPositiveDeliveryNotificationRequired() @@ -50,8 +48,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetPrivate()->getDisplayNotificationRequired() ) { const string imdnNamespace = "imdn"; - Cpim::NsHeader cpimNsHeader; - cpimNsHeader.setValue(imdnNamespace + " "); + Cpim::NsHeader cpimNsHeader(imdnNamespace, ""); cpimMessage.addMessageHeader(cpimNsHeader); char token[13]; @@ -88,18 +85,12 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetBodyAsString(); if (content->getContentDisposition().isValid()) { - Cpim::GenericHeader contentDispositionHeader; - contentDispositionHeader.setName("Content-Disposition"); - contentDispositionHeader.setValue(content->getContentDisposition().asString()); + Cpim::GenericHeader contentDispositionHeader("Content-Disposition", content->getContentDisposition().asString()); cpimMessage.addContentHeader(contentDispositionHeader); } - Cpim::GenericHeader contentTypeHeader; - contentTypeHeader.setName("Content-Type"); - contentTypeHeader.setValue(content->getContentType().asString()); + Cpim::GenericHeader contentTypeHeader("Content-Type", content->getContentType().asString()); cpimMessage.addContentHeader(contentTypeHeader); - Cpim::GenericHeader contentLengthHeader; - contentLengthHeader.setName("Content-Length"); - contentLengthHeader.setValue(to_string(contentBody.size())); + Cpim::GenericHeader contentLengthHeader("Content-Length", to_string(contentBody.size())); cpimMessage.addContentHeader(contentLengthHeader); cpimMessage.setContent(contentBody); @@ -203,12 +194,12 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptr"; - return os.str(); +string CpimChatMessageModifier::cpimAddressDisplayName (const Address &addr) const { + return addr.getDisplayName(); +} + +string CpimChatMessageModifier::cpimAddressUri (const Address &addr) const { + return addr.asStringUriOnly(); } LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/cpim-chat-message-modifier.h b/src/chat/modifier/cpim-chat-message-modifier.h index ab63c74e6..04dab858a 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.h +++ b/src/chat/modifier/cpim-chat-message-modifier.h @@ -34,7 +34,8 @@ public: Result decode (const std::shared_ptr &message, int &errorCode) override; private: - std::string cpimAddressAsString (const Address &addr) const; + std::string cpimAddressDisplayName (const Address &addr) const; + std::string cpimAddressUri (const Address &addr) const; }; LINPHONE_END_NAMESPACE From ec400bfe4a931f4126694cda0081b08ab0e137fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:04:22 +0200 Subject: [PATCH 04/15] Adapted tm to time_t and time_t to tm conversions for windows --- src/utils/utils.cpp | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 897f5dc8f..a2eda88c3 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -27,6 +27,10 @@ #include "linphone/utils/utils.h" +#include "logger/logger.h" + +#include "private.h" + // ============================================================================= using namespace std; @@ -184,12 +188,42 @@ string Utils::trim (const string &str) { // ----------------------------------------------------------------------------- tm Utils::getTimeTAsTm (time_t time) { - tm result; - return *gmtime_r(&time, &result); + #ifndef _WIN32 + tm result; + return *gmtime_r(&time, &result); + #else + return *gmtime(&time); + #endif } time_t Utils::getTmAsTimeT (const tm &time) { - return timegm(&const_cast(time)); + time_t result; + + #if defined(LINPHONE_WINDOWS_UNIVERSAL) || defined(LINPHONE_MSC_VER_GREATER_19) + long adjust_timezone; + #else + time_t adjust_timezone; + #endif + + #if TARGET_IPHONE_SIMULATOR + result = timegm(&const_cast(time)); + adjust_timezone = 0; + #else + result = mktime(&const_cast(time)); + + #if defined(LINPHONE_WINDOWS_UNIVERSAL) || defined(LINPHONE_MSC_VER_GREATER_19) + _get_timezone(&adjust_timezone); + #else + adjust_timezone = timezone; + #endif + #endif + + if (result == (time_t)-1) { + lError() << "mktime failed: " << strerror(errno); + return (time_t)-1; + } + + return result - (time_t)adjust_timezone; } // ----------------------------------------------------------------------------- From df89ba16f74eed3fb66955f8049f64b31286d446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:04:38 +0200 Subject: [PATCH 05/15] Adapted test to new changes --- tester/cpim-tester.cpp | 247 +++++++---------------------------------- 1 file changed, 40 insertions(+), 207 deletions(-) diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 83a45430e..51d8c1776 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -37,7 +37,7 @@ using namespace std; using namespace LinphonePrivate; static void parse_minimal_message () { - const string str = "Content-type: Message/CPIM\r\n" + const string str = "Subject: the weather will be fine today\r\n" "\r\n" "Content-Type: text/plain; charset=utf-8\r\n" "\r\n"; @@ -54,13 +54,6 @@ static void parse_minimal_message () { static void set_generic_header_name () { const list > entries = { - { "toto", true }, - { "george.abitbol", true }, - { "tata/titi", false }, - { "hey ho", false }, - { " fail", false }, - { "fail2 ", false }, - // Reserved. { "From", false }, { "To", false }, @@ -68,59 +61,21 @@ static void set_generic_header_name () { { "DateTime", false }, { "Subject", false }, { "NS", false }, - { "Require", false }, - - // Case sensitivity. - { "FROM", true }, - { "to", true }, - { "cC", true }, - { "Datetime", true }, - { "SuBject", true }, - { "nS", true }, - { "requirE", true } + { "Require", false } }; for (const auto &entry : entries) { - Cpim::GenericHeader genericHeader; - - const bool result = genericHeader.setName(entry.first); - BC_ASSERT_EQUAL(result, entry.second, bool, "%d"); + Cpim::GenericHeader genericHeader(entry.first, ""); + genericHeader.setName(entry.first); const string name = genericHeader.getName(); - if (result) - BC_ASSERT_STRING_EQUAL(name.c_str(), entry.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(name.c_str(), ""); - } -} - -static void set_generic_header_value () { - const list > entries = { - { "MyFeatures ", true }, - { "2000-12-13T13:40:00-08:00", true }, - { "2000-12-13T13:40:00-08:00", true }, - { "text/xml; charset=utf-8", true }, - { "text/xml; charset=ut\r\nf-8", false } - }; - - for (const auto &entry : entries) { - Cpim::GenericHeader genericHeader; - - const bool result = genericHeader.setValue(entry.first); - BC_ASSERT_EQUAL(result, entry.second, bool, "%d"); - - const string value = genericHeader.getValue(); - - if (result) - BC_ASSERT_STRING_EQUAL(value.c_str(), entry.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(value.c_str(), ""); + BC_ASSERT_STRING_EQUAL(name.c_str(), entry.first.c_str()); } } static void check_core_header_names () { - const list, string> > entries = { + const list, string> > entries = { { make_shared(), "From" }, { make_shared(), "To" }, { make_shared(), "cc" }, @@ -136,118 +91,13 @@ static void check_core_header_names () { } } -static void set_core_header_values () { - const list, list > > > entries = { - { make_shared(), { - { "Winnie the Pooh ", true }, - { "", true }, - { "", true }, - { "toto", false } - } }, - { make_shared(), { - { "", true }, - { "toto", false }, - { "", true }, - { "", true } - } }, - { make_shared(), { - { "", true }, - { "", true }, - { "", true }, - { "toto", false } - } }, - { make_shared(), { - { "abcd", false }, - { "1985-04-12T23:20:50.52Z", true }, - { "1996-12-19T16:39:57-08:00", true }, - { "1990-12-31T23:59:60Z", true }, - { "1990-12-31T15:59:60-08:00", true }, - { "2001-02-29T10:10:10Z", false }, - { "2000-02-29T10:10:10Z", true }, - { "1937-01-01T12:00:27.87+00:20", true }, - { "1937-01-01T12:00:27.87Z", true }, - { "1956", false } - } }, - { make_shared(), { - { "Eeyore's feeling very depressed today", true }, - { "🤣", true }, - { "hello", true } - } }, - { make_shared(), { - { "MyAlias ", true }, - { "What is this? - Barry Burton", false }, - { "", true }, - { "(), { - { "MyAlias.VitalHeader", true }, - { "MyAlias.VitalHeader,Test", true }, - { "MyAlias.VitalHeader,🤣", false } - } } - }; - - for (const auto &entry : entries) { - const shared_ptr header = entry.first; - string previousValue; - - for (const auto &test : entry.second) { - const bool result = header->setValue(test.first); - BC_ASSERT_EQUAL(result, test.second, bool, "%d"); - - const string value = header->getValue(); - - if (result) - BC_ASSERT_STRING_EQUAL(value.c_str(), test.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(value.c_str(), previousValue.c_str()); - - previousValue = value; - } - } -} - -static void check_subject_header_language () { - Cpim::SubjectHeader subjectHeader; - - // Check for not defined language. - { - const string language = subjectHeader.getLanguage(); - BC_ASSERT_STRING_EQUAL(language.c_str(), ""); - } - - // Set valid language. - { - const string languageToSet = "fr"; - - BC_ASSERT_TRUE(subjectHeader.setLanguage(languageToSet)); - BC_ASSERT_TRUE(languageToSet == subjectHeader.getLanguage()); - - const string str = subjectHeader.asString(); - const string expected = "Subject:;lang=" + languageToSet + " \r\n"; - BC_ASSERT_STRING_EQUAL(str.c_str(), expected.c_str()); - } - - // Set invalid language. - { - const string languageToSet = "fr--"; - BC_ASSERT_FALSE(subjectHeader.setLanguage(languageToSet)); - BC_ASSERT_FALSE(languageToSet == subjectHeader.getLanguage()); - BC_ASSERT_FALSE(subjectHeader.isValid()); - } -} - static void parse_rfc_example () { const string body = "" "Here is the text of my message." ""; - const string str = "Content-type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" - "To: Depressed Donkey \r\n" + const string str = "From: \"MR SANDERS\"\r\n" + "To: \"Depressed Donkey\"\r\n" "DateTime: 2000-12-13T13:40:00-08:00\r\n" "Subject: the weather will be fine today\r\n" "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" @@ -275,9 +125,7 @@ static void parse_message_with_generic_header_parameters () { "Here is the text of my message." ""; - const string str = "Content-type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" + const string str = "From: \"MR SANDERS\"\r\n" "Test:;aaa=bbb;yes=no CheckMe\r\n" "yaya: coucou\r\n" "yepee:;good=bad ugly\r\n" @@ -298,50 +146,41 @@ static void parse_message_with_generic_header_parameters () { static void build_message () { Cpim::Message message; - if (!BC_ASSERT_FALSE(message.isValid())) - return; - - // Set CPIM headers. - Cpim::GenericHeader cpimContentTypeHeader; - if (!BC_ASSERT_TRUE(cpimContentTypeHeader.setName("Content-Type"))) return; - if (!BC_ASSERT_TRUE(cpimContentTypeHeader.setValue("Message/CPIM"))) return; - - if (!BC_ASSERT_TRUE(message.addCpimHeader(cpimContentTypeHeader))) return; // Set message headers. - Cpim::FromHeader fromHeader; - if (!BC_ASSERT_TRUE(fromHeader.setValue("MR SANDERS "))) return; + Cpim::FromHeader fromHeader("im:piglet@100akerwood.com", "MR SANDERS"); + //if (!BC_ASSERT_TRUE(fromHeader.setValue("MR SANDERS "))) return; - Cpim::ToHeader toHeader; - if (!BC_ASSERT_TRUE(toHeader.setValue("Depressed Donkey "))) return; + Cpim::ToHeader toHeader("im:eeyore@100akerwood.com", "Depressed Donkey"); + //if (!BC_ASSERT_TRUE(toHeader.setValue("Depressed Donkey "))) return; - Cpim::DateTimeHeader dateTimeHeader; - if (!BC_ASSERT_TRUE(dateTimeHeader.setValue("2000-12-13T13:40:00-08:00"))) return; + //Cpim::DateTimeHeader dateTimeHeader; //TODO value + //if (!BC_ASSERT_TRUE(dateTimeHeader.setValue("2000-12-13T13:40:00-08:00"))) return; - Cpim::SubjectHeader subjectHeader; - if (!BC_ASSERT_TRUE(subjectHeader.setValue("the weather will be fine today"))) return; + Cpim::SubjectHeader subjectHeader("the weather will be fine today"); + //if (!BC_ASSERT_TRUE(subjectHeader.setValue("the weather will be fine today"))) return; - Cpim::SubjectHeader subjectWithLanguageHeader; - if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setValue("beau temps prevu pour aujourd'hui"))) return; - if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setLanguage("fr"))) return; + Cpim::SubjectHeader subjectWithLanguageHeader("beau temps prevu pour aujourd'hui", "fr"); + //if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setValue("beau temps prevu pour aujourd'hui"))) return; + //if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setLanguage("fr"))) return; - Cpim::NsHeader nsHeader; - if (!BC_ASSERT_TRUE(nsHeader.setValue("MyFeatures "))) return; + Cpim::NsHeader nsHeader("mid:MessageFeatures@id.foo.com", "MyFeatures"); + //if (!BC_ASSERT_TRUE(nsHeader.setValue("MyFeatures "))) return; - Cpim::RequireHeader requireHeader; - if (!BC_ASSERT_TRUE(requireHeader.setValue("MyFeatures.VitalMessageOption"))) return; + Cpim::RequireHeader requireHeader("MyFeatures.VitalMessageOption"); + //if (!BC_ASSERT_TRUE(requireHeader.setValue("MyFeatures.VitalMessageOption"))) return; - Cpim::GenericHeader vitalMessageHeader; - if (!BC_ASSERT_TRUE(vitalMessageHeader.setName("MyFeatures.VitalMessageOption"))) return; - if (!BC_ASSERT_TRUE(vitalMessageHeader.setValue("Confirmation-requested"))) return; + Cpim::GenericHeader vitalMessageHeader("MyFeatures.VitalMessageOption", "Confirmation-requested"); + //if (!BC_ASSERT_TRUE(vitalMessageHeader.setName("MyFeatures.VitalMessageOption"))) return; + //if (!BC_ASSERT_TRUE(vitalMessageHeader.setValue("Confirmation-requested"))) return; - Cpim::GenericHeader wackyMessageHeader; - if (!BC_ASSERT_TRUE(wackyMessageHeader.setName("MyFeatures.WackyMessageOption"))) return; - if (!BC_ASSERT_TRUE(wackyMessageHeader.setValue("Use-silly-font"))) return; + Cpim::GenericHeader wackyMessageHeader("MyFeatures.WackyMessageOption", "Use-silly-font"); + //if (!BC_ASSERT_TRUE(wackyMessageHeader.setName("MyFeatures.WackyMessageOption"))) return; + //if (!BC_ASSERT_TRUE(wackyMessageHeader.setValue("Use-silly-font"))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; + //if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; @@ -350,14 +189,14 @@ static void build_message () { if (!BC_ASSERT_TRUE(message.addMessageHeader(wackyMessageHeader))) return; // Set Content headers. - Cpim::GenericHeader contentTypeHeader; - if (!BC_ASSERT_TRUE(contentTypeHeader.setName("Content-Type"))) return; - if (!BC_ASSERT_TRUE( contentTypeHeader.setValue("text/xml; charset=utf-8"))) return; + Cpim::GenericHeader contentTypeHeader("Content-Type", "text/xml; charset=utf-8"); + //if (!BC_ASSERT_TRUE(contentTypeHeader.setName("Content-Type"))) return; + //if (!BC_ASSERT_TRUE( contentTypeHeader.setValue("text/xml; charset=utf-8"))) return; if (!BC_ASSERT_TRUE(message.addContentHeader(contentTypeHeader))) return; - Cpim::GenericHeader contentIdHeader; - if (!BC_ASSERT_TRUE(contentIdHeader.setName("Content-ID"))) return; - if (!BC_ASSERT_TRUE( contentIdHeader.setValue("<1234567890@foo.com>"))) return; + Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); + //if (!BC_ASSERT_TRUE(contentIdHeader.setName("Content-ID"))) return; + //if (!BC_ASSERT_TRUE( contentIdHeader.setValue("<1234567890@foo.com>"))) return; if (!BC_ASSERT_TRUE(message.addContentHeader(contentIdHeader))) return; const string content = "" @@ -365,14 +204,11 @@ static void build_message () { ""; if (!BC_ASSERT_TRUE(message.setContent(content))) return; - if (!BC_ASSERT_TRUE(message.isValid())) return; const string strMessage = message.asString(); - const string expectedMessage = "Content-Type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" - "To: Depressed Donkey \r\n" - "DateTime: 2000-12-13T13:40:00-08:00\r\n" + const string expectedMessage = "From: \"MR SANDERS\"\r\n" + "To: \"Depressed Donkey\"\r\n" + //"DateTime: 2000-12-13T13:40:00-08:00\r\n" "Subject: the weather will be fine today\r\n" "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" "NS: MyFeatures \r\n" @@ -471,10 +307,7 @@ static void cpim_chat_message_modifier_with_multipart_body () { test_t cpim_tests[] = { TEST_NO_TAG("Parse minimal CPIM message", parse_minimal_message), TEST_NO_TAG("Set generic header name", set_generic_header_name), - TEST_NO_TAG("Set generic header value", set_generic_header_value), TEST_NO_TAG("Check core header names", check_core_header_names), - TEST_NO_TAG("Set core header values", set_core_header_values), - TEST_NO_TAG("Check Subject header language", check_subject_header_language), TEST_NO_TAG("Parse RFC example", parse_rfc_example), TEST_NO_TAG("Parse Message with generic header parameters", parse_message_with_generic_header_parameters), TEST_NO_TAG("Build Message", build_message), From aaec49c6da4890b36f347bf29ad0b00d047fda70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:05:16 +0200 Subject: [PATCH 06/15] Updated the new cpim_grammar binary --- share/cpim_grammar | Bin 5158 -> 5340 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/share/cpim_grammar b/share/cpim_grammar index 7ea914ca5fe9dc16205704b241c8649960421b6c..b3f2a560f3d2caa03421e09fcddbe7b7996e8e9a 100644 GIT binary patch delta 462 zcmZ3caYu8)BSw~qk5xFil8bWE7+8{%CpQY3O?F`9P-IQc&nrpIE78qJO-xBGDrNwI z|3JV65n!0?!MKZ&Wim696FWpV=VW~*vCT0|1&l!9v&?$jP(#y-@^eAPZZ=~{WZb-g zwT!u*g)29;xHvIA6>d62Ef>0_5Mfqy)iAd(F)#v|99$qPphhupmE^;jDTyViC7HP} zYZ$nalR2tZuNdet znawF&G0Z@TgS@t^U>UTE;?mL=wtrcQPjDB$J- vyRbMjJ&$4XF@aWfCIlbkJ0?a3ZAL~0T}Bp!$AH2tlcNMxpw`t2u4DoLH?@vv delta 251 zcmcbkxlCiiBSz+lk5wk~GCEGqXWYfeJXwp$X>$=%J0p17 From 31b9e4589f3deb1e08ceef7a7f914068c6b1c564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:16:08 +0200 Subject: [PATCH 07/15] Removed useless asserts --- src/chat/cpim/header/cpim-core-headers.cpp | 42 +++++++++++----------- tester/cpim-tester.cpp | 29 ++++++--------- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp index 0da0b2721..908c99a50 100644 --- a/src/chat/cpim/header/cpim-core-headers.cpp +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -133,8 +133,8 @@ string Cpim::MessageIdHeader::asString () const { class Cpim::DateTimeHeaderPrivate : public HeaderPrivate { public: - tm timeT; - tm timeTOffset; + tm dateTime; + tm dateTimeOffset; string signOffset; }; @@ -151,13 +151,13 @@ Cpim::DateTimeHeader::DateTimeHeader (const tm &time, const tm &timeOffset, cons time_t Cpim::DateTimeHeader::getTime () const { L_D(); - tm result = d->timeT; + tm result = d->dateTime; result.tm_year -= 1900; result.tm_isdst = 0; if (d->signOffset == "+") { - result.tm_hour += d->timeTOffset.tm_hour; - result.tm_min += d->timeTOffset.tm_min; + result.tm_hour += d->dateTimeOffset.tm_hour; + result.tm_min += d->dateTimeOffset.tm_min; while (result.tm_min > 59) { result.tm_hour++; @@ -165,8 +165,8 @@ time_t Cpim::DateTimeHeader::getTime () const { } } else if (d->signOffset == "-") { - result.tm_hour -= d->timeTOffset.tm_hour; - result.tm_hour -= d->timeTOffset.tm_min; + result.tm_hour -= d->dateTimeOffset.tm_hour; + result.tm_hour -= d->dateTimeOffset.tm_min; while (result.tm_min < 0) { result.tm_hour--; @@ -181,8 +181,8 @@ bool Cpim::DateTimeHeader::setTime (const time_t time) { L_D(); d->signOffset = "Z"; - d->timeT = Utils::getTimeTAsTm(time); - d->timeT.tm_year += 1900; + d->dateTime = Utils::getTimeTAsTm(time); + d->dateTime.tm_year += 1900; return true; } @@ -190,8 +190,8 @@ bool Cpim::DateTimeHeader::setTime (const time_t time) { bool Cpim::DateTimeHeader::setTime (const tm &time, const tm &timeOffset, const string &signOffset) { L_D(); - d->timeT = time; - d->timeTOffset = timeOffset; + d->dateTime = time; + d->dateTimeOffset = timeOffset; d->signOffset = signOffset; return true; @@ -201,17 +201,17 @@ string Cpim::DateTimeHeader::getValue () const { L_D(); stringstream ss; - ss << setfill('0') << setw(4) << d->timeT.tm_year << "-" - << setfill('0') << setw(2) << d->timeT.tm_mon << "-" - << setfill('0') << setw(2) << d->timeT.tm_mday << "T" - << setfill('0') << setw(2) << d->timeT.tm_hour << ":" - << setfill('0') << setw(2) << d->timeT.tm_min << ":" - << setfill('0') << setw(2) << d->timeT.tm_sec; + ss << setfill('0') << setw(4) << d->dateTime.tm_year << "-" + << setfill('0') << setw(2) << d->dateTime.tm_mon << "-" + << setfill('0') << setw(2) << d->dateTime.tm_mday << "T" + << setfill('0') << setw(2) << d->dateTime.tm_hour << ":" + << setfill('0') << setw(2) << d->dateTime.tm_min << ":" + << setfill('0') << setw(2) << d->dateTime.tm_sec; ss << d->signOffset; if (d->signOffset != "Z") - ss << setfill('0') << setw(2) << d->timeTOffset.tm_hour << ":" - << setfill('0') << setw(2) << d->timeTOffset.tm_min; + ss << setfill('0') << setw(2) << d->dateTimeOffset.tm_hour << ":" + << setfill('0') << setw(2) << d->dateTimeOffset.tm_min; return ss.str(); } @@ -222,12 +222,12 @@ string Cpim::DateTimeHeader::asString () const { struct tm Cpim::DateTimeHeader::getTimeStruct () const { L_D(); - return d->timeT; + return d->dateTime; } struct tm Cpim::DateTimeHeader::getTimeOffset () const { L_D(); - return d->timeTOffset; + return d->dateTimeOffset; } string Cpim::DateTimeHeader::getSignOffset () const { diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 51d8c1776..edca28a64 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -149,38 +149,33 @@ static void build_message () { // Set message headers. Cpim::FromHeader fromHeader("im:piglet@100akerwood.com", "MR SANDERS"); - //if (!BC_ASSERT_TRUE(fromHeader.setValue("MR SANDERS "))) return; Cpim::ToHeader toHeader("im:eeyore@100akerwood.com", "Depressed Donkey"); - //if (!BC_ASSERT_TRUE(toHeader.setValue("Depressed Donkey "))) return; - //Cpim::DateTimeHeader dateTimeHeader; //TODO value - //if (!BC_ASSERT_TRUE(dateTimeHeader.setValue("2000-12-13T13:40:00-08:00"))) return; + tm dateTime = { 0 }, offset = { 0 }; + dateTime.tm_year = 2000; + dateTime.tm_mon = 12; + dateTime.tm_mday = 13; + dateTime.tm_hour = 13; + dateTime.tm_min = 40; + offset.tm_hour = 8; + Cpim::DateTimeHeader dateTimeHeader(dateTime, offset, "-"); Cpim::SubjectHeader subjectHeader("the weather will be fine today"); - //if (!BC_ASSERT_TRUE(subjectHeader.setValue("the weather will be fine today"))) return; Cpim::SubjectHeader subjectWithLanguageHeader("beau temps prevu pour aujourd'hui", "fr"); - //if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setValue("beau temps prevu pour aujourd'hui"))) return; - //if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setLanguage("fr"))) return; Cpim::NsHeader nsHeader("mid:MessageFeatures@id.foo.com", "MyFeatures"); - //if (!BC_ASSERT_TRUE(nsHeader.setValue("MyFeatures "))) return; Cpim::RequireHeader requireHeader("MyFeatures.VitalMessageOption"); - //if (!BC_ASSERT_TRUE(requireHeader.setValue("MyFeatures.VitalMessageOption"))) return; Cpim::GenericHeader vitalMessageHeader("MyFeatures.VitalMessageOption", "Confirmation-requested"); - //if (!BC_ASSERT_TRUE(vitalMessageHeader.setName("MyFeatures.VitalMessageOption"))) return; - //if (!BC_ASSERT_TRUE(vitalMessageHeader.setValue("Confirmation-requested"))) return; Cpim::GenericHeader wackyMessageHeader("MyFeatures.WackyMessageOption", "Use-silly-font"); - //if (!BC_ASSERT_TRUE(wackyMessageHeader.setName("MyFeatures.WackyMessageOption"))) return; - //if (!BC_ASSERT_TRUE(wackyMessageHeader.setValue("Use-silly-font"))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; - //if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; @@ -190,13 +185,9 @@ static void build_message () { // Set Content headers. Cpim::GenericHeader contentTypeHeader("Content-Type", "text/xml; charset=utf-8"); - //if (!BC_ASSERT_TRUE(contentTypeHeader.setName("Content-Type"))) return; - //if (!BC_ASSERT_TRUE( contentTypeHeader.setValue("text/xml; charset=utf-8"))) return; if (!BC_ASSERT_TRUE(message.addContentHeader(contentTypeHeader))) return; Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); - //if (!BC_ASSERT_TRUE(contentIdHeader.setName("Content-ID"))) return; - //if (!BC_ASSERT_TRUE( contentIdHeader.setValue("<1234567890@foo.com>"))) return; if (!BC_ASSERT_TRUE(message.addContentHeader(contentIdHeader))) return; const string content = "" @@ -208,7 +199,7 @@ static void build_message () { const string strMessage = message.asString(); const string expectedMessage = "From: \"MR SANDERS\"\r\n" "To: \"Depressed Donkey\"\r\n" - //"DateTime: 2000-12-13T13:40:00-08:00\r\n" + "DateTime: 2000-12-13T13:40:00-08:00\r\n" "Subject: the weather will be fine today\r\n" "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" "NS: MyFeatures \r\n" From 17d196447e4af2fba2e7973cb7fa711e181a2c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 15:53:48 +0200 Subject: [PATCH 08/15] struct tm month is 0 to 11 --- src/chat/cpim/header/cpim-core-headers.cpp | 2 +- src/chat/cpim/parser/cpim-parser.cpp | 2 +- tester/cpim-tester.cpp | 13 ++++--------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp index 908c99a50..2c5b5be6b 100644 --- a/src/chat/cpim/header/cpim-core-headers.cpp +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -202,7 +202,7 @@ string Cpim::DateTimeHeader::getValue () const { stringstream ss; ss << setfill('0') << setw(4) << d->dateTime.tm_year << "-" - << setfill('0') << setw(2) << d->dateTime.tm_mon << "-" + << setfill('0') << setw(2) << d->dateTime.tm_mon + 1 << "-" << setfill('0') << setw(2) << d->dateTime.tm_mday << "T" << setfill('0') << setw(2) << d->dateTime.tm_hour << ":" << setfill('0') << setw(2) << d->dateTime.tm_min << ":" diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp index a918a802a..bd5d32df5 100644 --- a/src/chat/cpim/parser/cpim-parser.cpp +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -290,7 +290,7 @@ namespace Cpim { } void setMonth (const string &value) { - mTime.tm_mon = Utils::stoi(value); + mTime.tm_mon = Utils::stoi(value) - 1; } void setMonthDay (const string &value) { diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index edca28a64..79586cf3a 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -152,14 +152,9 @@ static void build_message () { Cpim::ToHeader toHeader("im:eeyore@100akerwood.com", "Depressed Donkey"); - tm dateTime = { 0 }, offset = { 0 }; - dateTime.tm_year = 2000; - dateTime.tm_mon = 12; - dateTime.tm_mday = 13; - dateTime.tm_hour = 13; - dateTime.tm_min = 40; - offset.tm_hour = 8; - Cpim::DateTimeHeader dateTimeHeader(dateTime, offset, "-"); + // 976686000 is 2000-12-13T13:40:00-08:00 + Cpim::DateTimeHeader dateTimeHeader(976686000); + BC_ASSERT_EQUAL(dateTimeHeader.getTime(), 976686000, int, "%d"); Cpim::SubjectHeader subjectHeader("the weather will be fine today"); @@ -199,7 +194,7 @@ static void build_message () { const string strMessage = message.asString(); const string expectedMessage = "From: \"MR SANDERS\"\r\n" "To: \"Depressed Donkey\"\r\n" - "DateTime: 2000-12-13T13:40:00-08:00\r\n" + "DateTime: 2000-12-13T05:40:00Z\r\n" "Subject: the weather will be fine today\r\n" "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" "NS: MyFeatures \r\n" From 55909fbe162dce3be4b3571bf8cd46e1c5722302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Wed, 25 Apr 2018 16:32:08 +0200 Subject: [PATCH 09/15] Change setters from bool to void and fix crash when a specific header is malformed --- src/chat/cpim/header/cpim-core-headers.cpp | 80 ++++---------------- src/chat/cpim/header/cpim-core-headers.h | 20 ++--- src/chat/cpim/header/cpim-generic-header.cpp | 30 +++----- src/chat/cpim/header/cpim-generic-header.h | 8 +- src/chat/cpim/message/cpim-message.cpp | 8 +- src/chat/cpim/message/cpim-message.h | 4 +- src/chat/cpim/parser/cpim-parser.cpp | 16 +++- tester/cpim-tester.cpp | 28 ++++--- 8 files changed, 70 insertions(+), 124 deletions(-) diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp index 2c5b5be6b..eedcaa173 100644 --- a/src/chat/cpim/header/cpim-core-headers.cpp +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -53,14 +53,9 @@ string Cpim::ContactHeader::getUri () const { return d->uri; } -bool Cpim::ContactHeader::setUri (const string &uri) { - if (uri.empty()) - return false; - +void Cpim::ContactHeader::setUri (const string &uri) { L_D(); d->uri = uri; - - return true; } string Cpim::ContactHeader::getFormalName () const { @@ -68,10 +63,7 @@ string Cpim::ContactHeader::getFormalName () const { return d->formalName; } -bool Cpim::ContactHeader::setFormalName (const string &formalName) { - if (formalName.empty()) - return false; - +void Cpim::ContactHeader::setFormalName (const string &formalName) { L_D(); if (formalName.front() == '\"' && formalName.back() == '\"') d->formalName = formalName.substr(1, formalName.size() - 2); @@ -79,8 +71,6 @@ bool Cpim::ContactHeader::setFormalName (const string &formalName) { d->formalName = formalName.substr(0, formalName.size() - 1); else d->formalName = formalName; - - return true; } string Cpim::ContactHeader::getValue () const { @@ -102,8 +92,7 @@ public: Cpim::MessageIdHeader::MessageIdHeader () : Header(*new MessageIdHeaderPrivate) {} Cpim::MessageIdHeader::MessageIdHeader (const string &token) : MessageIdHeader() { - L_D(); - d->token = token; + setToken(token); } string Cpim::MessageIdHeader::getToken () const { @@ -111,14 +100,9 @@ string Cpim::MessageIdHeader::getToken () const { return d->token; } -bool Cpim::MessageIdHeader::setToken (string token) { - if (token.empty()) - return false; - +void Cpim::MessageIdHeader::setToken (string token) { L_D(); d->token = token; - - return true; } string Cpim::MessageIdHeader::getValue () const { @@ -177,24 +161,20 @@ time_t Cpim::DateTimeHeader::getTime () const { return Utils::getTmAsTimeT(result); } -bool Cpim::DateTimeHeader::setTime (const time_t time) { +void Cpim::DateTimeHeader::setTime (const time_t time) { L_D(); d->signOffset = "Z"; d->dateTime = Utils::getTimeTAsTm(time); d->dateTime.tm_year += 1900; - - return true; } -bool Cpim::DateTimeHeader::setTime (const tm &time, const tm &timeOffset, const string &signOffset) { +void Cpim::DateTimeHeader::setTime (const tm &time, const tm &timeOffset, const string &signOffset) { L_D(); d->dateTime = time; d->dateTimeOffset = timeOffset; d->signOffset = signOffset; - - return true; } string Cpim::DateTimeHeader::getValue () const { @@ -246,9 +226,8 @@ public: Cpim::NsHeader::NsHeader () : Header(*new NsHeaderPrivate) {} Cpim::NsHeader::NsHeader (const string &uri, const string &prefixName) : NsHeader() { - L_D(); - d->uri = uri; - d->prefixName = prefixName; + setUri(uri); + setPrefixName(prefixName); } string Cpim::NsHeader::getUri () const { @@ -256,14 +235,9 @@ string Cpim::NsHeader::getUri () const { return d->uri; } -bool Cpim::NsHeader::setUri (const string &uri) { - if (uri.empty()) - return false; - +void Cpim::NsHeader::setUri (const string &uri) { L_D(); d->uri = uri; - - return true; } string Cpim::NsHeader::getPrefixName () const { @@ -271,14 +245,9 @@ string Cpim::NsHeader::getPrefixName () const { return d->prefixName; } -bool Cpim::NsHeader::setPrefixName (const string &prefixName) { - if (prefixName.empty()) - return false; - +void Cpim::NsHeader::setPrefixName (const string &prefixName) { L_D(); d->prefixName = prefixName; - - return true; } string Cpim::NsHeader::getValue () const { @@ -305,9 +274,8 @@ public: Cpim::RequireHeader::RequireHeader () : Header(*new RequireHeaderPrivate) {} Cpim::RequireHeader::RequireHeader (const string &headerNames) : RequireHeader() { - L_D(); for (const string &header : Utils::split(headerNames, ",")) { - d->headerNames.push_back(header); + addHeaderName(header); } } @@ -321,14 +289,9 @@ list Cpim::RequireHeader::getHeaderNames () const { return d->headerNames; } -bool Cpim::RequireHeader::addHeaderName (const string &headerName) { - if (headerName.empty()) - return false; - +void Cpim::RequireHeader::addHeaderName (const string &headerName) { L_D(); d->headerNames.push_back(headerName); - - return true; } string Cpim::RequireHeader::getValue () const { @@ -359,9 +322,8 @@ public: Cpim::SubjectHeader::SubjectHeader () : Header(*new SubjectHeaderPrivate) {} Cpim::SubjectHeader::SubjectHeader (const string &subject, const string &language) : SubjectHeader() { - L_D(); - d->subject = subject; - d->language = language; + setSubject(subject); + setLanguage(language); } string Cpim::SubjectHeader::getSubject () const { @@ -369,14 +331,9 @@ string Cpim::SubjectHeader::getSubject () const { return d->subject; } -bool Cpim::SubjectHeader::setSubject (const string &subject) { - if (subject.empty()) - return false; - +void Cpim::SubjectHeader::setSubject (const string &subject) { L_D(); d->subject = subject; - - return true; } string Cpim::SubjectHeader::getLanguage () const { @@ -384,14 +341,9 @@ string Cpim::SubjectHeader::getLanguage () const { return d->language; } -bool Cpim::SubjectHeader::setLanguage (const string &language) { - if (!language.empty()) - return false; - +void Cpim::SubjectHeader::setLanguage (const string &language) { L_D(); d->language = language; - - return true; } string Cpim::SubjectHeader::getValue () const { diff --git a/src/chat/cpim/header/cpim-core-headers.h b/src/chat/cpim/header/cpim-core-headers.h index 89971cac0..d80acc869 100644 --- a/src/chat/cpim/header/cpim-core-headers.h +++ b/src/chat/cpim/header/cpim-core-headers.h @@ -57,10 +57,10 @@ namespace Cpim { ContactHeader (const std::string &uri, const std::string &formalName = ""); std::string getUri () const; - bool setUri (const std::string &uri); + void setUri (const std::string &uri); std::string getFormalName () const; - bool setFormalName (const std::string &formalName); + void setFormalName (const std::string &formalName); std::string getValue () const override; @@ -94,7 +94,7 @@ namespace Cpim { } std::string getToken () const; - bool setToken (std::string token); + void setToken (std::string token); std::string getValue () const override; @@ -126,9 +126,9 @@ namespace Cpim { } time_t getTime () const; - bool setTime (const time_t time); + void setTime (const time_t time); - bool setTime (const tm &time, const tm &timeOffset, const std::string &signOffset); + void setTime (const tm &time, const tm &timeOffset, const std::string &signOffset); std::string getValue () const override; @@ -160,10 +160,10 @@ namespace Cpim { } std::string getPrefixName () const; - bool setPrefixName (const std::string &prefixName); + void setPrefixName (const std::string &prefixName); std::string getUri () const; - bool setUri (const std::string &uri); + void setUri (const std::string &uri); std::string getValue () const override; @@ -192,7 +192,7 @@ namespace Cpim { } std::list getHeaderNames () const; - bool addHeaderName (const std::string &headerName); + void addHeaderName (const std::string &headerName); std::string getValue () const override; @@ -220,10 +220,10 @@ namespace Cpim { } std::string getSubject () const; - bool setSubject (const std::string &subject); + void setSubject (const std::string &subject); std::string getLanguage () const; - bool setLanguage (const std::string &language); + void setLanguage (const std::string &language); std::string getValue () const override; diff --git a/src/chat/cpim/header/cpim-generic-header.cpp b/src/chat/cpim/header/cpim-generic-header.cpp index 8e4bc57ab..6c5947777 100644 --- a/src/chat/cpim/header/cpim-generic-header.cpp +++ b/src/chat/cpim/header/cpim-generic-header.cpp @@ -34,24 +34,23 @@ LINPHONE_BEGIN_NAMESPACE class Cpim::GenericHeaderPrivate : public HeaderPrivate { public: - GenericHeaderPrivate () : parameters(make_shared > >()) {} + GenericHeaderPrivate () : parameters(make_shared>>()) {} string name; string value; - shared_ptr > > parameters; + shared_ptr>> parameters; }; Cpim::GenericHeader::GenericHeader () : Header(*new GenericHeaderPrivate) {} Cpim::GenericHeader::GenericHeader (string name, string value, string parameters) : GenericHeader() { - L_D(); - d->name = name; - d->value = value; + setName(name); + setValue(value); for (const auto ¶meter : Utils::split(parameters, ';')) { size_t equalIndex = parameter.find('='); if (equalIndex != string::npos) - d->parameters->push_back(make_pair(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1))); + addParameter(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1)); } } @@ -60,18 +59,15 @@ string Cpim::GenericHeader::getName () const { return d->name; } -bool Cpim::GenericHeader::setName (const string &name) { +void Cpim::GenericHeader::setName (const string &name) { L_D(); static const set reserved = { "From", "To", "cc", "DateTime", "Subject", "NS", "Require" }; - if (reserved.find(name) != reserved.end()) - return false; - - d->name = name; - return true; + if (reserved.find(name) == reserved.end()) + d->name = name; } string Cpim::GenericHeader::getValue () const { @@ -79,14 +75,9 @@ string Cpim::GenericHeader::getValue () const { return d->value; } -bool Cpim::GenericHeader::setValue (const string &value) { - if (value.empty()) - return false; - +void Cpim::GenericHeader::setValue (const string &value) { L_D(); d->value = value; - - return true; } Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { @@ -94,10 +85,9 @@ Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { return d->parameters; } -bool Cpim::GenericHeader::addParameter (const string &key, const string &value) { +void Cpim::GenericHeader::addParameter (const string &key, const string &value) { L_D(); d->parameters->push_back(make_pair(key, value)); - return true; } void Cpim::GenericHeader::removeParameter (const string &key, const string &value) { diff --git a/src/chat/cpim/header/cpim-generic-header.h b/src/chat/cpim/header/cpim-generic-header.h index 711b3c641..6ee8a3695 100644 --- a/src/chat/cpim/header/cpim-generic-header.h +++ b/src/chat/cpim/header/cpim-generic-header.h @@ -41,15 +41,15 @@ namespace Cpim { GenericHeader (std::string name, std::string value, std::string parameters = ""); std::string getName () const override; - bool setName (const std::string &name); + void setName (const std::string &name); std::string getValue () const override; - bool setValue (const std::string &value); + void setValue (const std::string &value); - typedef std::shared_ptr > > ParameterList; + typedef std::shared_ptr>> ParameterList; ParameterList getParameters () const; - bool addParameter (const std::string &key, const std::string &value); + void addParameter (const std::string &key, const std::string &value); void removeParameter (const std::string &key, const std::string &value); std::string asString () const override; diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index d6fb78080..18e148648 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -52,11 +52,9 @@ Cpim::Message::HeaderList Cpim::Message::getMessageHeaders () const { return d->messageHeaders; } -bool Cpim::Message::addMessageHeader (const Header &messageHeader) { +void Cpim::Message::addMessageHeader (const Header &messageHeader) { L_D(); - d->messageHeaders->push_back(Parser::getInstance()->cloneHeader(messageHeader)); - return true; } void Cpim::Message::removeMessageHeader (const Header &messageHeader) { @@ -73,11 +71,9 @@ Cpim::Message::HeaderList Cpim::Message::getContentHeaders () const { return d->contentHeaders; } -bool Cpim::Message::addContentHeader (const Header &contentHeader) { +void Cpim::Message::addContentHeader (const Header &contentHeader) { L_D(); - d->contentHeaders->push_back(Parser::getInstance()->cloneHeader(contentHeader)); - return true; } void Cpim::Message::removeContentHeader (const Header &contentHeader) { diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h index 7c4ce693c..4177b4972 100644 --- a/src/chat/cpim/message/cpim-message.h +++ b/src/chat/cpim/message/cpim-message.h @@ -37,11 +37,11 @@ namespace Cpim { typedef std::shared_ptr > > HeaderList; HeaderList getMessageHeaders () const; - bool addMessageHeader (const Header &messageHeader); + void addMessageHeader (const Header &messageHeader); void removeMessageHeader (const Header &messageHeader); HeaderList getContentHeaders () const; - bool addContentHeader (const Header &contentHeader); + void addContentHeader (const Header &contentHeader); void removeContentHeader (const Header &contentHeader); std::string getContent () const; diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp index bd5d32df5..a3201af22 100644 --- a/src/chat/cpim/parser/cpim-parser.cpp +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include @@ -65,7 +66,12 @@ namespace Cpim { } void setName (const string &name) { - mName = name; + static const set reserved = { + "From", "To", "cc", "DateTime", "Subject", "NS", "Require" + }; + + if (reserved.find(name) == reserved.end()) + mName = name; } string getParameters () const { @@ -537,15 +543,19 @@ namespace Cpim { // Add message headers. for (const auto &headerNode : mMessageHeaders) { const shared_ptr header = headerNode->createHeader(); - if (!header || !message->addMessageHeader(*header)) + if (!header) return nullptr; + + message->addMessageHeader(*header); } // Add content headers. for (const auto &headerNode : mContentHeaders) { const shared_ptr header = headerNode->createHeader(); - if (!header || !message->addContentHeader(*header)) + if (!header) return nullptr; + + message->addContentHeader(*header); } return message; diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 79586cf3a..147dc4209 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -67,10 +67,8 @@ static void set_generic_header_name () { for (const auto &entry : entries) { Cpim::GenericHeader genericHeader(entry.first, ""); - genericHeader.setName(entry.first); const string name = genericHeader.getName(); - - BC_ASSERT_STRING_EQUAL(name.c_str(), entry.first.c_str()); + BC_ASSERT_STRING_EQUAL(name.c_str(), ""); } } @@ -168,22 +166,22 @@ static void build_message () { Cpim::GenericHeader wackyMessageHeader("MyFeatures.WackyMessageOption", "Use-silly-font"); - if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(requireHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(vitalMessageHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(wackyMessageHeader))) return; + message.addMessageHeader(fromHeader); + message.addMessageHeader(toHeader); + message.addMessageHeader(dateTimeHeader); + message.addMessageHeader(subjectHeader); + message.addMessageHeader(subjectWithLanguageHeader); + message.addMessageHeader(nsHeader); + message.addMessageHeader(requireHeader); + message.addMessageHeader(vitalMessageHeader); + message.addMessageHeader(wackyMessageHeader); // Set Content headers. Cpim::GenericHeader contentTypeHeader("Content-Type", "text/xml; charset=utf-8"); - if (!BC_ASSERT_TRUE(message.addContentHeader(contentTypeHeader))) return; + message.addContentHeader(contentTypeHeader); - Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); - if (!BC_ASSERT_TRUE(message.addContentHeader(contentIdHeader))) return; + Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); + message.addContentHeader(contentIdHeader); const string content = "" "Here is the text of my message." From daddec29d830ab251a2b8c108940dc109a8a3ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Thu, 26 Apr 2018 09:47:46 +0200 Subject: [PATCH 10/15] Changed Cpim message to be able to return headers from a specific namespace --- src/chat/cpim/message/cpim-message.cpp | 71 +++++++++++++++++++++----- src/chat/cpim/message/cpim-message.h | 10 ++-- src/chat/cpim/parser/cpim-parser.cpp | 11 +++- tester/cpim-tester.cpp | 8 +++ 4 files changed, 81 insertions(+), 19 deletions(-) diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 18e148648..91bd670f6 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -18,6 +18,7 @@ */ #include +#include #include "linphone/utils/utils.h" @@ -36,9 +37,10 @@ LINPHONE_BEGIN_NAMESPACE class Cpim::MessagePrivate : public ObjectPrivate { public: - typedef list > PrivHeaderList; + using PrivHeaderList = list>; + using PrivHeaderMap = map>; - shared_ptr messageHeaders = make_shared(); + PrivHeaderMap messageHeaders; shared_ptr contentHeaders = make_shared(); string content; }; @@ -47,21 +49,47 @@ Cpim::Message::Message () : Object(*new MessagePrivate) {} // ----------------------------------------------------------------------------- -Cpim::Message::HeaderList Cpim::Message::getMessageHeaders () const { +Cpim::Message::HeaderList Cpim::Message::getMessageHeaders (const string &ns) const { L_D(); - return d->messageHeaders; + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + return nullptr; + + return d->messageHeaders.at(ns); } -void Cpim::Message::addMessageHeader (const Header &messageHeader) { +void Cpim::Message::addMessageHeader (const Header &messageHeader, const string &ns) { L_D(); - d->messageHeaders->push_back(Parser::getInstance()->cloneHeader(messageHeader)); + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + d->messageHeaders[ns] = make_shared(); + + auto list = d->messageHeaders.at(ns); + list->push_back(Parser::getInstance()->cloneHeader(messageHeader)); } -void Cpim::Message::removeMessageHeader (const Header &messageHeader) { +void Cpim::Message::removeMessageHeader (const Header &messageHeader, const string &ns) { L_D(); - d->messageHeaders->remove_if([&messageHeader](const shared_ptr &header) { - return messageHeader.getName() == header->getName() && messageHeader.getValue() == header->getValue(); - }); + + if (d->messageHeaders.find(ns) != d->messageHeaders.end()) + d->messageHeaders.at(ns)->remove_if([&messageHeader](const shared_ptr &header) { + return messageHeader.getName() == header->getName() && messageHeader.getValue() == header->getValue(); + }); +} + +shared_ptr Cpim::Message::getMessageHeader (const string &name, const string &ns) { + L_D(); + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + return nullptr; + + auto list = d->messageHeaders.at(ns); + for (const auto &messageHeader : *list) { + if (messageHeader->getName() == name) + return messageHeader; + } + + return nullptr; } // ----------------------------------------------------------------------------- @@ -83,6 +111,17 @@ void Cpim::Message::removeContentHeader (const Header &contentHeader) { }); } +shared_ptr Cpim::Message::getContentHeader(const string &name) { + L_D(); + + for (const auto &contentHeader : *d->contentHeaders) { + if (contentHeader->getName() == name) + return contentHeader; + } + + return nullptr; +} + // ----------------------------------------------------------------------------- string Cpim::Message::getContent () const { @@ -102,9 +141,15 @@ string Cpim::Message::asString () const { L_D(); string output; - if (d->messageHeaders->size() > 0) { - for (const auto &messageHeader : *d->messageHeaders) - output += messageHeader->asString(); + if (d->messageHeaders.size() > 0) { + for (const auto &entry : d->messageHeaders) { + auto list = entry.second; + for (const auto &messageHeader : *list) { + if (entry.first != "") + output += entry.first + "."; + output += messageHeader->asString(); + } + } output += "\r\n"; } diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h index 4177b4972..7745dfe76 100644 --- a/src/chat/cpim/message/cpim-message.h +++ b/src/chat/cpim/message/cpim-message.h @@ -34,15 +34,17 @@ namespace Cpim { public: Message (); - typedef std::shared_ptr > > HeaderList; + typedef std::shared_ptr>> HeaderList; - HeaderList getMessageHeaders () const; - void addMessageHeader (const Header &messageHeader); - void removeMessageHeader (const Header &messageHeader); + HeaderList getMessageHeaders (const std::string &ns = "") const; + void addMessageHeader (const Header &messageHeader, const std::string &ns = ""); + void removeMessageHeader (const Header &messageHeader, const std::string &ns = ""); + std::shared_ptr getMessageHeader (const std::string &name, const std::string &ns = ""); HeaderList getContentHeaders () const; void addContentHeader (const Header &contentHeader); void removeContentHeader (const Header &contentHeader); + std::shared_ptr getContentHeader (const std::string &name); std::string getContent () const; bool setContent (const std::string &content); diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp index a3201af22..23fa0a360 100644 --- a/src/chat/cpim/parser/cpim-parser.cpp +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -18,7 +18,6 @@ */ #include -#include #include #include @@ -542,11 +541,19 @@ namespace Cpim { // Add message headers. for (const auto &headerNode : mMessageHeaders) { + string ns = ""; + + string::size_type n = headerNode->getName().find("."); + if (n != string::npos) { + ns = headerNode->getName().substr(0, n); + headerNode->setName(headerNode->getName().substr(n + 1)); + } + const shared_ptr header = headerNode->createHeader(); if (!header) return nullptr; - message->addMessageHeader(*header); + message->addMessageHeader(*header, ns); } // Add content headers. diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 147dc4209..7bac7d0fc 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -116,6 +116,14 @@ static void parse_rfc_example () { string content = message->getContent(); BC_ASSERT_STRING_EQUAL(content.c_str(), body.c_str()); + + Cpim::Message::HeaderList list = message->getMessageHeaders(); + if (!BC_ASSERT_PTR_NOT_NULL(list)) return; + BC_ASSERT_EQUAL(list->size(), 7, int, "%d"); + + list = message->getMessageHeaders("MyFeatures"); + if (!BC_ASSERT_PTR_NOT_NULL(list)) return; + BC_ASSERT_EQUAL(list->size(), 2, int, "%d"); } static void parse_message_with_generic_header_parameters () { From a0e40432171a0113ac2c317cbedcfe52c873c0b5 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Apr 2018 17:05:00 +0200 Subject: [PATCH 11/15] Some cleaning in CPIM parser. --- src/chat/cpim/header/cpim-core-headers.cpp | 37 +++------------------- src/chat/cpim/header/cpim-core-headers.h | 28 ---------------- src/chat/cpim/message/cpim-message.cpp | 4 +-- src/chat/cpim/message/cpim-message.h | 6 ++-- 4 files changed, 10 insertions(+), 65 deletions(-) diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp index eedcaa173..4f35651fe 100644 --- a/src/chat/cpim/header/cpim-core-headers.cpp +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -75,7 +75,11 @@ void Cpim::ContactHeader::setFormalName (const string &formalName) { string Cpim::ContactHeader::getValue () const { L_D(); - return "\"" + d->formalName + "\"" + "<" + d->uri + ">"; + string result; + if (!d->formalName.empty()) + result += "\"" + d->formalName + "\""; + result += "<" + d->uri + ">"; + return result; } string Cpim::ContactHeader::asString () const { @@ -84,37 +88,6 @@ string Cpim::ContactHeader::asString () const { // ----------------------------------------------------------------------------- -class Cpim::MessageIdHeaderPrivate : public HeaderPrivate { -public: - string token; -}; - -Cpim::MessageIdHeader::MessageIdHeader () : Header(*new MessageIdHeaderPrivate) {} - -Cpim::MessageIdHeader::MessageIdHeader (const string &token) : MessageIdHeader() { - setToken(token); -} - -string Cpim::MessageIdHeader::getToken () const { - L_D(); - return d->token; -} - -void Cpim::MessageIdHeader::setToken (string token) { - L_D(); - d->token = token; -} - -string Cpim::MessageIdHeader::getValue () const { - return getToken(); -} - -string Cpim::MessageIdHeader::asString () const { - return getName() + ": " + getValue() + "\r\n"; -} - -// ----------------------------------------------------------------------------- - class Cpim::DateTimeHeaderPrivate : public HeaderPrivate { public: tm dateTime; diff --git a/src/chat/cpim/header/cpim-core-headers.h b/src/chat/cpim/header/cpim-core-headers.h index d80acc869..2ddd7ea29 100644 --- a/src/chat/cpim/header/cpim-core-headers.h +++ b/src/chat/cpim/header/cpim-core-headers.h @@ -77,34 +77,6 @@ namespace Cpim { MAKE_CONTACT_HEADER(To, "To"); MAKE_CONTACT_HEADER(Cc, "cc"); - // ------------------------------------------------------------------------- - // Specific MessageId declaration. - // ------------------------------------------------------------------------- - - class MessageIdHeaderPrivate; - - class LINPHONE_PUBLIC MessageIdHeader : public Header { - public: - MessageIdHeader (); - - MessageIdHeader (const std::string &token); - - inline std::string getName() const override { - return "Message-ID"; - } - - std::string getToken () const; - void setToken (std::string token); - - std::string getValue () const override; - - std::string asString () const override; - - private: - L_DECLARE_PRIVATE(MessageIdHeader); - L_DISABLE_COPY(MessageIdHeader); - }; - // ------------------------------------------------------------------------- // Specific DateTime declaration. // ------------------------------------------------------------------------- diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 91bd670f6..ca4aa3b4d 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -77,7 +77,7 @@ void Cpim::Message::removeMessageHeader (const Header &messageHeader, const stri }); } -shared_ptr Cpim::Message::getMessageHeader (const string &name, const string &ns) { +shared_ptr Cpim::Message::getMessageHeader (const string &name, const string &ns) const { L_D(); if (d->messageHeaders.find(ns) == d->messageHeaders.end()) @@ -111,7 +111,7 @@ void Cpim::Message::removeContentHeader (const Header &contentHeader) { }); } -shared_ptr Cpim::Message::getContentHeader(const string &name) { +shared_ptr Cpim::Message::getContentHeader(const string &name) const { L_D(); for (const auto &contentHeader : *d->contentHeaders) { diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h index 7745dfe76..19e91a43a 100644 --- a/src/chat/cpim/message/cpim-message.h +++ b/src/chat/cpim/message/cpim-message.h @@ -39,12 +39,12 @@ namespace Cpim { HeaderList getMessageHeaders (const std::string &ns = "") const; void addMessageHeader (const Header &messageHeader, const std::string &ns = ""); void removeMessageHeader (const Header &messageHeader, const std::string &ns = ""); - std::shared_ptr getMessageHeader (const std::string &name, const std::string &ns = ""); - + std::shared_ptr getMessageHeader (const std::string &name, const std::string &ns = "") const; + HeaderList getContentHeaders () const; void addContentHeader (const Header &contentHeader); void removeContentHeader (const Header &contentHeader); - std::shared_ptr getContentHeader (const std::string &name); + std::shared_ptr getContentHeader (const std::string &name) const; std::string getContent () const; bool setContent (const std::string &content); From 84afb118b3451c445e8446e0e28b38ea10e17d0f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Apr 2018 17:07:00 +0200 Subject: [PATCH 12/15] Improve CPIM grammar. --- share/cpim_grammar | Bin 5340 -> 5346 bytes src/chat/cpim/parser/cpim-rules | 23 +++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/share/cpim_grammar b/share/cpim_grammar index b3f2a560f3d2caa03421e09fcddbe7b7996e8e9a..066afb55811392f443765d48c539188ba12c945a 100644 GIT binary patch delta 210 zcmcbk`ABoZBSz+lk5wk~GKNYp{s#gU1|VSK%1BL2NiAaFN-oMto1DkEn~{047L(KF zBBpjmAoCZq-ef(NwT!Hj@35F{mS7EM;b+QCEiO(>Pt}F!oZQKoXN)RT3^Ezn4peEV zU0*r(0xj6grLy@hS2Z(`8OdkM$TGQ+PjvGpzQrKR!vt(L&k!gCF}Z|Pm|05lCkrr| KZO#?SX9582W1Y8-Zi7BZ?lS>$PGqOxJ zU~*ywE8JYj)WHZ8_{FRT5tyvbvW}5$@--GSr~+=*2o@>U+|=UY#Pn2Mh$+PkAOJF! zX>t)~-egfOkf9g3;I`)#18tX?tj;RDS)JRH87NuEXA3oOE#EGXjTr(q>`=E(?iUc< Tyh|V&BrGPR0##=zw2}z`SVKch diff --git a/src/chat/cpim/parser/cpim-rules b/src/chat/cpim/parser/cpim-rules index d2837db2a..b11cccb9a 100644 --- a/src/chat/cpim/parser/cpim-rules +++ b/src/chat/cpim/parser/cpim-rules @@ -1,8 +1,11 @@ Message = Message-headers CRLF Content-headers CRLF -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 +Message-headers = 1*( Message-header CRLF ) +Message-header = From-header / To-header / DateTime-header / cc-header / Subject-header / NS-header / Require-header / Header + +Content-headers = 1*( Header CRLF ) + +Header = Header-name ":" Header-parameters SP Header-value Header-name = [ Name-prefix "." ] Name Name-prefix = Name @@ -17,25 +20,25 @@ Param-value = Token / Number / String Header-value = *HEADERCHAR -From-header = %d70.114.111.109 ": " From-header-value CRLF +From-header = %d70.114.111.109 ": " From-header-value From-header-value = [ Formal-name ] "<" URI ">" -To-header = %d84.111 ": " To-header-value CRLF +To-header = %d84.111 ": " To-header-value To-header-value = [ Formal-name ] "<" URI ">" -DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value CRLF +DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value DateTime-header-value = date-time -cc-header = %d99.99 ": " cc-header-value CRLF +cc-header = %d99.99 ": " cc-header-value cc-header-value = [ Formal-name ] "<" URI ">" -Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value CRLF +Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value Subject-header-value = [ ";" Lang-param ] SP Header-value -NS-header = %d78.83 ": " NS-header-value CRLF +NS-header = %d78.83 ": " NS-header-value NS-header-value = [ Name-prefix SP ] "<" URI ">" -Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value CRLF +Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value Require-header-value = Header-name *( "," Header-name ) Name = 1*NAMECHAR From 86bd71ce3384e3fbe53516fa7cecf2355cbb4492 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Apr 2018 17:02:50 +0200 Subject: [PATCH 13/15] Fix datetime values when fetching from database. --- src/db/main-db-p.h | 2 ++ src/db/main-db.cpp | 16 +++++++++++----- src/utils/utils.cpp | 6 +++--- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/db/main-db-p.h b/src/db/main-db-p.h index bd2076407..35c93f42d 100644 --- a/src/db/main-db-p.h +++ b/src/db/main-db-p.h @@ -44,6 +44,8 @@ private: // Misc helpers. // --------------------------------------------------------------------------- + static time_t getTmAsTimeT (const tm &t); + std::shared_ptr findChatRoom (const ChatRoomId &chatRoomId) const; // --------------------------------------------------------------------------- diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index dcb589a60..bd5245f67 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -226,6 +226,12 @@ static string buildSqlEventFilter ( // Misc helpers. // ----------------------------------------------------------------------------- +time_t MainDbPrivate::getTmAsTimeT (const tm &t) { + tm t2 = t; + t2.tm_isdst = 0; + return Utils::getTmAsTimeT(t2); +} + shared_ptr MainDbPrivate::findChatRoom (const ChatRoomId &chatRoomId) const { L_Q(); shared_ptr chatRoom = q->getCore()->findChatRoom(chatRoomId); @@ -610,7 +616,7 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( dChatMessage->forceFromAddress(IdentityAddress(row.get(3))); dChatMessage->forceToAddress(IdentityAddress(row.get(4))); - dChatMessage->setTime(Utils::getTmAsTimeT(row.get(5))); + dChatMessage->setTime(MainDbPrivate::getTmAsTimeT(row.get(5))); dChatMessage->setImdnMessageId(row.get(6)); dChatMessage->setPositiveDeliveryNotificationRequired(bool(row.get(14))); dChatMessage->setDisplayNotificationRequired(bool(row.get(15))); @@ -1976,7 +1982,7 @@ list MainDb::getChatMessageParticipantsThatHaveDisplay list result; for (const auto &row : rows) - result.emplace_back(IdentityAddress(row.get(0)), ChatMessage::State::Displayed, Utils::getTmAsTimeT(row.get(1))); + result.emplace_back(IdentityAddress(row.get(0)), ChatMessage::State::Displayed, MainDbPrivate::getTmAsTimeT(row.get(1))); return result; }; } @@ -2029,7 +2035,7 @@ list MainDb::getChatMessageParticipantsThatHaveReceive list result; for (const auto &row : rows) - result.emplace_back(IdentityAddress(row.get(0)), ChatMessage::State::DeliveredToUser, Utils::getTmAsTimeT(row.get(1))); + result.emplace_back(IdentityAddress(row.get(0)), ChatMessage::State::DeliveredToUser, MainDbPrivate::getTmAsTimeT(row.get(1))); return result; }; } @@ -2483,8 +2489,8 @@ list> MainDb::getChatRooms () const { continue; // Not fetched. AbstractChatRoomPrivate *dChatRoom = chatRoom->getPrivate(); - dChatRoom->setCreationTime(Utils::getTmAsTimeT(creationTime)); - dChatRoom->setLastUpdateTime(Utils::getTmAsTimeT(lastUpdateTime)); + dChatRoom->setCreationTime(MainDbPrivate::getTmAsTimeT(creationTime)); + dChatRoom->setLastUpdateTime(MainDbPrivate::getTmAsTimeT(lastUpdateTime)); lInfo() << "Found chat room in DB: (peer=" << chatRoomId.getPeerAddress().asString() << ", local=" << chatRoomId.getLocalAddress().asString() << ")."; diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index a2eda88c3..b05174a63 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -188,11 +188,11 @@ string Utils::trim (const string &str) { // ----------------------------------------------------------------------------- tm Utils::getTimeTAsTm (time_t time) { - #ifndef _WIN32 + #ifdef _WIN32 + return *gmtime(&time); + #else tm result; return *gmtime_r(&time, &result); - #else - return *gmtime(&time); #endif } From 251147589c011d79c447fb104058759e6367c6cb Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Apr 2018 17:03:33 +0200 Subject: [PATCH 14/15] Improve CPIM chat message modifier with better use of CPIM parser. --- .../modifier/cpim-chat-message-modifier.cpp | 142 +++++++++--------- 1 file changed, 72 insertions(+), 70 deletions(-) diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 04c73f9c1..39104a674 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -38,29 +38,30 @@ LINPHONE_BEGIN_NAMESPACE ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr &message, int &errorCode) { Cpim::Message cpimMessage; - Cpim::FromHeader cpimFromHeader(cpimAddressUri(message->getFromAddress()), cpimAddressDisplayName(message->getFromAddress())); - cpimMessage.addMessageHeader(cpimFromHeader); - Cpim::ToHeader cpimToHeader(cpimAddressUri(message->getToAddress()), cpimAddressDisplayName(message->getToAddress())); - cpimMessage.addMessageHeader(cpimToHeader); + cpimMessage.addMessageHeader( + Cpim::FromHeader(cpimAddressUri(message->getFromAddress()), cpimAddressDisplayName(message->getFromAddress())) + ); + cpimMessage.addMessageHeader( + Cpim::ToHeader(cpimAddressUri(message->getToAddress()), cpimAddressDisplayName(message->getToAddress())) + ); + cpimMessage.addMessageHeader( + Cpim::DateTimeHeader(message->getTime()) + ); if (message->getPrivate()->getPositiveDeliveryNotificationRequired() || message->getPrivate()->getNegativeDeliveryNotificationRequired() || message->getPrivate()->getDisplayNotificationRequired() ) { const string imdnNamespace = "imdn"; - Cpim::NsHeader cpimNsHeader(imdnNamespace, ""); - cpimMessage.addMessageHeader(cpimNsHeader); + cpimMessage.addMessageHeader(Cpim::NsHeader("urn:ietf:params:imdn", imdnNamespace)); char token[13]; belle_sip_random_token(token, sizeof(token)); - Cpim::GenericHeader cpimMessageIdHeader; - cpimMessageIdHeader.setName("Message-ID"); // TODO: Replace by imdnNamespace + ".Message-ID"); - cpimMessageIdHeader.setValue(token); - cpimMessage.addMessageHeader(cpimMessageIdHeader); + cpimMessage.addMessageHeader( + Cpim::GenericHeader("Message-ID", token) // TODO: Replace by imdnNamespace + ".Message-ID"); + ); message->getPrivate()->setImdnMessageId(token); - Cpim::GenericHeader dispositionNotificationHeader; - dispositionNotificationHeader.setName(imdnNamespace + ".Disposition-Notification"); vector dispositionNotificationValues; if (message->getPrivate()->getPositiveDeliveryNotificationRequired()) dispositionNotificationValues.emplace_back("positive-delivery"); @@ -68,8 +69,12 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetPrivate()->getDisplayNotificationRequired()) dispositionNotificationValues.emplace_back("display"); - dispositionNotificationHeader.setValue(Utils::join(dispositionNotificationValues, ", ")); - cpimMessage.addMessageHeader(dispositionNotificationHeader); + cpimMessage.addMessageHeader( + Cpim::GenericHeader( + imdnNamespace + ".Disposition-Notification", + Utils::join(dispositionNotificationValues, ", ") + ) + ); } const Content *content; @@ -85,13 +90,16 @@ ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptrgetBodyAsString(); if (content->getContentDisposition().isValid()) { - Cpim::GenericHeader contentDispositionHeader("Content-Disposition", content->getContentDisposition().asString()); - cpimMessage.addContentHeader(contentDispositionHeader); + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Disposition", content->getContentDisposition().asString()) + ); } - Cpim::GenericHeader contentTypeHeader("Content-Type", content->getContentType().asString()); - cpimMessage.addContentHeader(contentTypeHeader); - Cpim::GenericHeader contentLengthHeader("Content-Length", to_string(contentBody.size())); - cpimMessage.addContentHeader(contentLengthHeader); + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Type", content->getContentType().asString()) + ); + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Length", to_string(contentBody.size())) + ); cpimMessage.setContent(contentBody); Content newContent; @@ -116,76 +124,70 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptrgetBodyAsString(); const shared_ptr cpimMessage = Cpim::Message::createFromString(contentBody); - if (!cpimMessage) { + if (!cpimMessage || !cpimMessage->getMessageHeader("From") || !cpimMessage->getMessageHeader("To")) { lError() << "[CPIM] Message is invalid: " << contentBody; errorCode = 500; return ChatMessageModifier::Result::Error; } Content newContent; - bool contentTypeFound = false; - Cpim::Message::HeaderList l = cpimMessage->getContentHeaders(); - if (l) { - for (const auto &header : *l.get()) { - if (header->getName() == "Content-Disposition") { - newContent.setContentDisposition(ContentDisposition(header->getValue())); - } else if (header->getName() == "Content-Type") { - contentTypeFound = true; - newContent.setContentType(ContentType(header->getValue())); - } - } - } - if (!contentTypeFound) { + auto contentTypeHeader = cpimMessage->getContentHeader("Content-Type"); + if (!contentTypeHeader) { lError() << "[CPIM] No Content-type for the content of the message"; errorCode = 500; return ChatMessageModifier::Result::Error; } + newContent.setContentType(ContentType(contentTypeHeader->getValue())); + auto contentDispositionHeader = cpimMessage->getContentHeader("Content-Disposition"); + if (contentDispositionHeader) + newContent.setContentDisposition(ContentDisposition(contentDispositionHeader->getValue())); newContent.setBody(cpimMessage->getContent()); message->getPrivate()->setPositiveDeliveryNotificationRequired(false); message->getPrivate()->setNegativeDeliveryNotificationRequired(false); message->getPrivate()->setDisplayNotificationRequired(false); - Address cpimFromAddress; - Address cpimToAddress; - l = cpimMessage->getMessageHeaders(); - if (l) { - string imdnNamespace = ""; - for (const auto &header : *l.get()) { - if (header->getName() == "NS") { - string val = header->getValue(); - size_t startPos = 0; - startPos = val.find("<", startPos); - if (startPos == string::npos) - break; - size_t endPos = 0; - endPos = val.find(">", startPos); - if (endPos == string::npos) - break; - if (val.substr(startPos, endPos) == "") - imdnNamespace = Utils::trim(val.substr(0, startPos)); - } - } - for (const auto &header : *l.get()) { - if (header->getName() == "From") - cpimFromAddress = Address(header->getValue()); - else if (header->getName() == "To") - cpimToAddress = Address(header->getValue()); - else if ((header->getName() == "Message-ID") || (header->getName() == (imdnNamespace + ".Message-ID"))) - message->getPrivate()->setImdnMessageId(header->getValue()); - else if ((header->getName() == (imdnNamespace + ".Disposition-Notification"))) { - vector values = Utils::split(header->getValue(), ", "); - for (const auto &value : values) - if (value == "positive-delivery") - message->getPrivate()->setPositiveDeliveryNotificationRequired(true); - else if (value == "negative-delivery") - message->getPrivate()->setNegativeDeliveryNotificationRequired(true); - else if (value == "display") - message->getPrivate()->setDisplayNotificationRequired(true); + string imdnNamespace = ""; + auto messageHeaders = cpimMessage->getMessageHeaders(); + if (messageHeaders) { + for (const auto &header : *messageHeaders.get()) { + if (header->getName() != "NS") + continue; + auto nsHeader = static_pointer_cast(header); + if (nsHeader->getUri() == "urn:ietf:params:imdn") { + imdnNamespace = nsHeader->getPrefixName(); + break; } } } + auto fromHeader = static_pointer_cast(cpimMessage->getMessageHeader("From")); + Address cpimFromAddress(fromHeader->getValue()); + auto toHeader = static_pointer_cast(cpimMessage->getMessageHeader("To")); + Address cpimToAddress(toHeader->getValue()); + auto dateTimeHeader = static_pointer_cast(cpimMessage->getMessageHeader("DateTime")); + if (dateTimeHeader) + message->getPrivate()->setTime(dateTimeHeader->getTime()); + + auto messageIdHeader = cpimMessage->getMessageHeader("Message-ID"); // TODO: For compatibility, to remove + if (!imdnNamespace.empty()) { + if (!messageIdHeader) + messageIdHeader = cpimMessage->getMessageHeader("Message-ID", imdnNamespace); + auto dispositionNotificationHeader = cpimMessage->getMessageHeader("Disposition-Notification", imdnNamespace); + if (dispositionNotificationHeader) { + vector values = Utils::split(dispositionNotificationHeader->getValue(), ", "); + for (const auto &value : values) + if (value == "positive-delivery") + message->getPrivate()->setPositiveDeliveryNotificationRequired(true); + else if (value == "negative-delivery") + message->getPrivate()->setNegativeDeliveryNotificationRequired(true); + else if (value == "display") + message->getPrivate()->setDisplayNotificationRequired(true); + } + } + if (messageIdHeader) + message->getPrivate()->setImdnMessageId(messageIdHeader->getValue()); + // Modify the initial message since there was no error message->setInternalContent(newContent); if (cpimFromAddress.isValid()) From 96e0a6a22898b8e41355877cf5bd492639f2c65f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 26 Apr 2018 17:03:59 +0200 Subject: [PATCH 15/15] Fix crash in CPIM tester. --- tester/cpim-tester.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 7bac7d0fc..ec1f8338a 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -281,6 +281,9 @@ static void cpim_chat_message_modifier_base (bool useMultipart) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), expected.c_str()); } + marieMessage.reset(); + marieRoom.reset(); + linphone_im_encryption_engine_unref(marie_imee); linphone_im_encryption_engine_unref(pauline_imee);