Add specific headers

This commit is contained in:
Mickaël Turnel 2018-04-25 15:02:03 +02:00 committed by Ghislain MARY
parent 728574a549
commit 6e0a7ae397
7 changed files with 522 additions and 119 deletions

View file

@ -17,6 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <iomanip>
#include <sstream>
#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<CLASS_PREFIX ## Header>(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<string> 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<string> &headerNames) : RequireHeader() {
L_D();
d->headerNames = headerNames;
}
list<string> 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<SubjectHeader>(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

View file

@ -20,60 +20,188 @@
#ifndef _L_CPIM_CORE_HEADERS_H_
#define _L_CPIM_CORE_HEADERS_H_
#include <ctime>
#include <list>
#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<std::string> &headerNames);
inline std::string getName () const override {
return "Require";
}
std::list<std::string> 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

View file

@ -37,11 +37,24 @@ public:
GenericHeaderPrivate () : parameters(make_shared<list<pair<string, string> > >()) {}
string name;
string value;
shared_ptr<list<pair<string, string> > > 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 &parameter : 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 &parameters) {
L_D();
// Set name/value.
d->name = name;
Header::setValue(value);
// Parse and build parameters list.
for (const auto &parameter : 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

View file

@ -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<const std::list<std::pair<std::string, std::string> > > 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 &parameters);
private:
L_DECLARE_PRIVATE(GenericHeader);
L_DISABLE_COPY(GenericHeader);

View file

@ -30,8 +30,6 @@ LINPHONE_BEGIN_NAMESPACE
namespace Cpim {
class HeaderPrivate : public ObjectPrivate {
private:
std::string value;
L_DECLARE_PUBLIC(Header);
};
}

View file

@ -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

View file

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