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);