diff --git a/exch/ews/context.cpp b/exch/ews/context.cpp index ba37afafb..d96e810ab 100644 --- a/exch/ews/context.cpp +++ b/exch/ews/context.cpp @@ -322,13 +322,12 @@ void Cleaner::operator()(MESSAGE_CONTENT *x) {message_content_free(x);} /////////////////////////////////////////////////////////////////////////////////////////////////// EWSContext::EWSContext(int id, HTTP_AUTH_INFO ai, const char *data, uint64_t length, - const std::vector &srvver, EWSPlugin &p) : - m_server_version(srvver), + EWSPlugin &p) : m_ID(id), m_orig(*get_request(id)), m_auth_info(ai), m_request(data, length), - m_response(m_server_version), + m_response(p.server_version()), m_plugin(p) { tinyxml2::XMLElement* imp = nullptr; diff --git a/exch/ews/ews.cpp b/exch/ews/ews.cpp index f27e35d72..22046408c 100644 --- a/exch/ews/ews.cpp +++ b/exch/ews/ews.cpp @@ -348,8 +348,7 @@ http_status EWSPlugin::dispatch(int ctx_id, HTTP_AUTH_INFO& auth_info, const voi using namespace std::string_literals; auto &pc = contexts[ctx_id] = std::make_unique(ctx_id, - auth_info, static_cast(data), len, m_server_version, - *this); + auth_info, static_cast(data), len, *this); EWSContext& context = *pc; const XMLElement* request = context.request().body->FirstChildElement(); if(!request) @@ -479,6 +478,7 @@ static constexpr cfg_directive ews_cfg_defaults[] = { {"ews_pretty_response", "0", CFG_BOOL}, {"ews_request_logging", "0"}, {"ews_response_logging", "0"}, + {"ews_schema_version", "V2017_07_11"}, {"smtp_server_ip", "::1", CFG_DEPRECATED}, {"smtp_server_port", "25", CFG_DEPRECATED}, CFG_TABLE_END, @@ -501,9 +501,7 @@ void EWSPlugin::loadConfig() } auto str = gxcfg->get_value("reported_server_version"); auto &ver = m_server_version; - ver.clear(); - ver.resize(4); - sscanf(str, "%hu.%hu.%hu.%hu", &ver[0], &ver[1], &ver[2], &ver[3]); + sscanf(str, "%hu.%hu.%hu.%hu", &ver.server[0], &ver.server[1], &ver.server[2], &ver.server[3]); auto cfg = config_file_initd("exmdb_provider.cfg", get_config_path(), x500_defaults); if(!cfg) @@ -526,6 +524,7 @@ void EWSPlugin::loadConfig() event_stream_interval = std::chrono::milliseconds(cfg->get_ll("ews_event_stream_interval")); cache_embedded_instance_lifetime = std::chrono::milliseconds(cfg->get_ll("ews_cache_embedded_instance_lifetime")); max_user_photo_size = cfg->get_ll("ews_max_user_photo_size"); + ver.schema = cfg->get_value("ews_schema_version"); str = gxcfg->get_value("outgoing_smtp_url"); if (str != nullptr) { @@ -654,7 +653,7 @@ int EWSContext::notify() mGetStreamingEventsResponse data; mGetStreamingEventsResponseMessage& msg = data.ResponseMessages.emplace_back(); - SOAP::Envelope envelope(m_server_version); + SOAP::Envelope envelope(m_plugin.server_version()); tinyxml2::XMLElement* response = envelope.body->InsertNewChildElement("m:GetStreamingEventsResponse"); response->SetAttribute("xmlns:m", Structures::NS_EWS_Messages::NS_URL); response->SetAttribute("xmlns:t", Structures::NS_EWS_Types::NS_URL); diff --git a/exch/ews/ews.hpp b/exch/ews/ews.hpp index e2d7a6068..7ba6904bf 100644 --- a/exch/ews/ews.hpp +++ b/exch/ews/ews.hpp @@ -175,6 +175,8 @@ class EWSPlugin { void unsubscribe(const detail::ExmdbSubscriptionKey&) const; void wakeContext(int, std::chrono::milliseconds) const; + inline const SOAP::VersionInfo& server_version() const {return m_server_version;} + std::string x500_org_name; ///< organization name or empty string if not configured std::string smtp_url; std::string timestampFormat = " "; ///< format specification for log timestamps or empty to disable timestamps @@ -219,7 +221,7 @@ class EWSPlugin { std::unique_ptr debug; std::vector logFilters; - std::vector m_server_version; + SOAP::VersionInfo m_server_version; bool invertFilter = true; bool teardown = false; @@ -236,7 +238,7 @@ class EWSContext { enum State : uint8_t {S_DEFAULT, S_WRITE, S_DONE, S_STREAM_NOTIFY}; - EWSContext(int, HTTP_AUTH_INFO, const char *, uint64_t, const std::vector &ver, EWSPlugin &); + EWSContext(int, HTTP_AUTH_INFO, const char *, uint64_t, EWSPlugin &); ~EWSContext(); EWSContext(const EWSContext&) = delete; @@ -361,7 +363,6 @@ class EWSContext { PROPERTY_NAME* getPropertyName(const std::string&, uint16_t) const; - std::vector m_server_version; int m_ID = 0; http_status m_code = http_status::ok; State m_state = S_DEFAULT; diff --git a/exch/ews/serialization.cpp b/exch/ews/serialization.cpp index c4c1e1fea..47c5339dd 100644 --- a/exch/ews/serialization.cpp +++ b/exch/ews/serialization.cpp @@ -1719,8 +1719,8 @@ void mMoveItemResponse::serialize(tinyxml2::XMLElement* xml) const void mResponseMessageType::serialize(tinyxml2::XMLElement* xml) const { XMLDUMPA(ResponseClass); - XMLDUMPM(ResponseCode); XMLDUMPM(MessageText); + XMLDUMPM(ResponseCode); XMLDUMPM(DescriptiveLinkKey); } diff --git a/exch/ews/soaputil.cpp b/exch/ews/soaputil.cpp index 13159e8c1..814a0e116 100644 --- a/exch/ews/soaputil.cpp +++ b/exch/ews/soaputil.cpp @@ -22,7 +22,7 @@ namespace gromox::EWS::SOAP /** * @brief Generate empty SOAP Envelope */ -Envelope::Envelope(const std::vector &ver) +Envelope::Envelope(const VersionInfo &ver) { auto decl = doc.NewDeclaration(); doc.InsertEndChild(decl); @@ -36,11 +36,11 @@ Envelope::Envelope(const std::vector &ver) XMLElement* ServerVersionInfo = header->InsertNewChildElement("t:ServerVersionInfo"); ServerVersionInfo->SetAttribute("xmlns:t", NS_TYPS); - assert(ver.size() >= 4); - ServerVersionInfo->SetAttribute("MajorVersion", ver[0]); - ServerVersionInfo->SetAttribute("MinorVersion", ver[1]); - ServerVersionInfo->SetAttribute("MajorBuildNumber", ver[2]); - ServerVersionInfo->SetAttribute("MinorBuildNumber", ver[3]); + ServerVersionInfo->SetAttribute("MajorVersion", ver.server[0]); + ServerVersionInfo->SetAttribute("MinorVersion", ver.server[1]); + ServerVersionInfo->SetAttribute("MajorBuildNumber", ver.server[2]); + ServerVersionInfo->SetAttribute("MinorBuildNumber", ver.server[3]); + ServerVersionInfo->SetAttribute("Version", ver.schema.c_str()); } /** diff --git a/exch/ews/soaputil.hpp b/exch/ews/soaputil.hpp index 0b2753c70..8fa01f37b 100644 --- a/exch/ews/soaputil.hpp +++ b/exch/ews/soaputil.hpp @@ -3,9 +3,9 @@ // This file is part of Gromox. #pragma once +#include #include #include -#include namespace gromox::EWS::SOAP { @@ -15,13 +15,18 @@ static constexpr char NS_XSI[] = "http://www.w3.org/2001/XMLSchema-instance"; static constexpr char NS_XSD[] = "http://www.w3.org/2001/XMLSchema"; static constexpr char NS_TYPS[] = "http://schemas.microsoft.com/exchange/services/2006/types"; +struct VersionInfo { + std::array server; ///< Server version + std::string schema; ///< EWS schema version string +}; + /** * @brief Basic class to manage SOAP Envelopes */ class Envelope { public: - Envelope(const std::vector &); + explicit Envelope(const VersionInfo &); explicit Envelope(const char*, size_t=static_cast< size_t >(-1)); tinyxml2::XMLDocument doc; ///< XML document containing the envelope diff --git a/exch/ews/structures.hpp b/exch/ews/structures.hpp index e201ab151..464e3a6d0 100644 --- a/exch/ews/structures.hpp +++ b/exch/ews/structures.hpp @@ -1458,7 +1458,7 @@ struct tSingleRecipient /** * Types.xsd:4419 */ -struct tAttendee +struct tAttendee : public NS_EWS_Types { static constexpr char NAME[] = "Attendee";