ews-cpp  0.9
ews.hpp
1 
2 // Copyright 2016-2020 otris software AG
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 // This project is hosted at https://github.com/otris
17 
18 #pragma once
19 
20 // RapidJSON derives from std::iterator causing the corresponding warnings
21 #if _MSC_VER >= 1910
22 # define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
23 #endif
24 
25 #include <algorithm>
26 #include <chrono>
27 #include <ctype.h>
28 #include <exception>
29 #include <fstream>
30 #include <functional>
31 #include <ios>
32 #include <iterator>
33 #include <limits>
34 #include <memory>
35 #include <stddef.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <time.h>
40 #ifdef EWS_HAS_OPTIONAL
41 # include <optional>
42 #endif
43 #include <sstream>
44 #include <stdexcept>
45 #include <string>
46 #include <tuple>
47 #include <type_traits>
48 #include <typeinfo>
49 #include <utility>
50 #ifdef EWS_HAS_VARIANT
51 # include <variant>
52 #endif
53 #include "rapidjson/document.h"
54 #include "rapidxml/rapidxml.hpp"
55 #include "rapidxml/rapidxml_print.hpp"
56 
57 #include <curl/curl.h>
58 #include <vector>
59 
60 // Print more detailed error messages, HTTP request/response etc to stderr
61 #ifdef EWS_ENABLE_VERBOSE
62 # include <iostream>
63 # include <ostream>
64 #endif
65 
66 #include "ews_fwd.hpp"
67 
68 #ifdef __GNUC__
69 # ifdef __clang__
70 # ifdef __has_attribute(maybe_unused)
71 # define EWS_MAYBE_UNUSED [[maybe_unused]]
72 # else
73 # define EWS_MAYBE_UNUSED
74 # endif
75 # else
76 # define EWS_MAYBE_UNUSED [[maybe_unused]]
77 # endif
78 #else
79 # define EWS_MAYBE_UNUSED
80 #endif
81 
83 namespace ews
84 {
85 
86 class contact;
87 
88 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
89 
90 # ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
91 template <typename ExceptionType = assertion_error>
92 # else
93 template <typename ExceptionType>
94 # endif
95 inline void check(bool expr, const char* msg)
96 {
97  if (!expr)
98  {
99  throw ExceptionType(msg);
100  }
101 }
102 
103 # ifndef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
104 // Add overload so template argument deduction won't fail on VS 2012
105 inline void check(bool expr, const char* msg)
106 {
107  check<assertion_error>(expr, msg);
108 }
109 # endif
110 
111 #endif // EWS_DOXYGEN_SHOULD_SKIP_THIS
112 
113 namespace internal
114 {
117  template <typename TargetType, typename SourceType>
118  TargetType numeric_cast(SourceType value)
119  {
120  if (static_cast<TargetType>(value) >
121  std::numeric_limits<TargetType>::max())
122  {
123  throw std::overflow_error("Cannot convert ");
124  }
125 
126  return static_cast<TargetType>(value);
127  }
128 
129  // Scope guard helper.
130  class on_scope_exit final
131  {
132  public:
133  template <typename Function> on_scope_exit(Function destructor_function)
134  try : func_(std::move(destructor_function))
135  {
136  }
137  catch (std::exception&)
138  {
139  destructor_function();
140  }
141 
142 #ifdef EWS_HAS_DEFAULT_AND_DELETE
143  on_scope_exit() = delete;
144  on_scope_exit(const on_scope_exit&) = delete;
145  on_scope_exit& operator=(const on_scope_exit&) = delete;
146 #else
147  private:
148  on_scope_exit(const on_scope_exit&); // Never defined
149  on_scope_exit& operator=(const on_scope_exit&); // Never defined
150 
151  public:
152 #endif
153 
154  ~on_scope_exit()
155  {
156  if (func_)
157  {
158  try
159  {
160  func_();
161  }
162  catch (std::exception&)
163  {
164  // Swallow
165  }
166  }
167  }
168 
169  void release() EWS_NOEXCEPT { func_ = nullptr; }
170 
171  private:
172  std::function<void(void)> func_;
173  };
174 
175 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
176  defined(EWS_HAS_CXX17_STATIC_ASSERT)
177  static_assert(!std::is_copy_constructible<on_scope_exit>::value);
178  static_assert(!std::is_copy_assignable<on_scope_exit>::value);
179  static_assert(!std::is_move_constructible<on_scope_exit>::value);
180  static_assert(!std::is_move_assignable<on_scope_exit>::value);
181  static_assert(!std::is_default_constructible<on_scope_exit>::value);
182 #endif
183 
184 #ifndef EWS_HAS_OPTIONAL
185  // Poor man's std::optional replacement
186  template <typename T> class optional final
187  {
188 # ifdef EWS_HAS_NON_BUGGY_TYPE_TRAITS
189  static_assert(std::is_copy_constructible<T>::value,
190  "T needs to be default constructible");
191 # endif
192 
193  public:
194  typedef T value_type;
195 
196  optional() : value_set_(false), val_() {}
197 
198  template <typename U>
199  optional(U&& val) : value_set_(true), val_(std::forward<U>(val))
200  {
201  }
202 
203  optional& operator=(T&& value)
204  {
205  val_ = std::move(value);
206  value_set_ = true;
207  return *this;
208  }
209 
210  bool has_value() const EWS_NOEXCEPT { return value_set_; }
211 
212  // Note we throw std::runtime_exception instead of
213  // std::bad_optional_access
214  const T& value() const
215  {
216  if (!has_value())
217  {
218  throw std::runtime_error("Bad ews::internal::optional access");
219  }
220  return val_;
221  }
222 
223  private:
224  bool value_set_;
225  value_type val_;
226  };
227 
228  template <typename T, typename U>
229  inline bool operator==(const optional<T>& opt, const U& value)
230  {
231  return opt.has_value() ? opt.value() == value : false;
232  }
233 #endif
234 
235  namespace base64
236  {
237  // Following code (everything in base64 namespace) is a slightly
238  // modified version of the original implementation from
239  // René Nyffenegger available at
240  //
241  // https://github.com/ReneNyffenegger/cpp-base64
242  //
243  // under the zlib License.
244  //
245  // Copyright © 2004-2017 by René Nyffenegger
246  //
247  // This source code is provided 'as-is', without any express or implied
248  // warranty. In no event will the author be held liable for any damages
249  // arising from the use of this software.
250  //
251  // Permission is granted to anyone to use this software for any purpose,
252  // including commercial applications, and to alter it and redistribute
253  // it freely, subject to the following restrictions:
254  //
255  // 1. The origin of this source code must not be misrepresented; you
256  // must not claim that you wrote the original source code. If you use
257  // this source code in a product, an acknowledgment in the product
258  // documentation would be appreciated but is not required.
259  //
260  // 2. Altered source versions must be plainly marked as such, and must
261  // not be misrepresented as being the original source code.
262  //
263  // 3. This notice may not be removed or altered from any source
264  // distribution.
265  //
266  // René Nyffenegger rene.nyffenegger@adp-gmbh.ch
267 
268  inline const std::string& valid_chars()
269  {
270  static const auto chars = std::string("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
271  "abcdefghijklmnopqrstuvwxyz"
272  "0123456789+/");
273  return chars;
274  }
275 
276  inline bool is_base64(unsigned char c) EWS_NOEXCEPT
277  {
278  return isalnum(c) || (c == '+') || (c == '/');
279  }
280 
281  inline std::string encode(const std::vector<unsigned char>& buf)
282  {
283  const auto& base64_chars = valid_chars();
284  int i = 0;
285  int j = 0;
286  unsigned char char_array_3[3];
287  unsigned char char_array_4[4];
288  auto buflen = buf.size();
289  auto bufit = begin(buf);
290  std::string ret;
291 
292  while (buflen--)
293  {
294  char_array_3[i++] = *(bufit++);
295  if (i == 3)
296  {
297  char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
298  char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
299  ((char_array_3[1] & 0xf0) >> 4);
300  char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
301  ((char_array_3[2] & 0xc0) >> 6);
302  char_array_4[3] = char_array_3[2] & 0x3f;
303 
304  for (i = 0; (i < 4); i++)
305  {
306  ret += base64_chars[char_array_4[i]];
307  }
308  i = 0;
309  }
310  }
311 
312  if (i)
313  {
314  for (j = i; j < 3; j++)
315  {
316  char_array_3[j] = '\0';
317  }
318 
319  char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
320  char_array_4[1] = ((char_array_3[0] & 0x03) << 4) +
321  ((char_array_3[1] & 0xf0) >> 4);
322  char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) +
323  ((char_array_3[2] & 0xc0) >> 6);
324 
325  for (j = 0; (j < i + 1); j++)
326  {
327  ret += base64_chars[char_array_4[j]];
328  }
329 
330  while ((i++ < 3))
331  {
332  ret += '=';
333  }
334  }
335 
336  return ret;
337  }
338 
339  inline std::vector<unsigned char>
340  decode(const std::string& encoded_string)
341  {
342  const auto& base64_chars = valid_chars();
343  auto in_len = encoded_string.size();
344  int i = 0;
345  int j = 0;
346  int in = 0;
347  unsigned char char_array_4[4];
348  unsigned char char_array_3[3];
349  std::vector<unsigned char> ret;
350 
351  while (in_len-- && (encoded_string[in] != '=') &&
352  is_base64(encoded_string[in]))
353  {
354  char_array_4[i++] = encoded_string[in];
355  in++;
356 
357  if (i == 4)
358  {
359  for (i = 0; i < 4; i++)
360  {
361  char_array_4[i] = static_cast<unsigned char>(
362  base64_chars.find(char_array_4[i]));
363  }
364 
365  char_array_3[0] = (char_array_4[0] << 2) +
366  ((char_array_4[1] & 0x30) >> 4);
367  char_array_3[1] = ((char_array_4[1] & 0xf) << 4) +
368  ((char_array_4[2] & 0x3c) >> 2);
369  char_array_3[2] =
370  ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
371 
372  for (i = 0; (i < 3); i++)
373  {
374  ret.push_back(char_array_3[i]);
375  }
376  i = 0;
377  }
378  }
379 
380  if (i)
381  {
382  for (j = 0; j < i; j++)
383  {
384  char_array_4[j] = static_cast<unsigned char>(
385  base64_chars.find(char_array_4[j]));
386  }
387 
388  char_array_3[0] =
389  (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
390  char_array_3[1] = ((char_array_4[1] & 0xf) << 4) +
391  ((char_array_4[2] & 0x3c) >> 2);
392 
393  for (j = 0; (j < i - 1); j++)
394  {
395  ret.push_back(char_array_3[j]);
396  }
397  }
398 
399  return ret;
400  }
401  } // namespace base64
402 
403  template <typename T>
404  inline bool points_within_array(T* p, T* begin, T* end)
405  {
406  // Not 100% sure if this works in each and every case
407  return std::greater_equal<T*>()(p, begin) && std::less<T*>()(p, end);
408  }
409 
410  // Forward declarations
411  class http_request;
412 } // namespace internal
413 
415 enum class response_class
416 {
418  error,
419 
421  success,
422 
424  warning
425 };
426 
428 class exception : public std::runtime_error
429 {
430 public:
431  explicit exception(const std::string& what) : std::runtime_error(what) {}
432  explicit exception(const char* what) : std::runtime_error(what) {}
433 };
434 
436 class assertion_error final : public exception
437 {
438 public:
439  explicit assertion_error(const std::string& what) : exception(what) {}
440  explicit assertion_error(const char* what) : exception(what) {}
441 };
442 
444 class xml_parse_error final : public exception
445 {
446 public:
447  explicit xml_parse_error(const std::string& what) : exception(what) {}
448  explicit xml_parse_error(const char* what) : exception(what) {}
449 
450 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
451  static std::string error_message_from(const rapidxml::parse_error& exc,
452  const std::vector<char>& xml)
453  {
454  using internal::points_within_array;
455 
456  const auto what = std::string(exc.what());
457  const auto* where = exc.where<char>();
458 
459  if ((where == nullptr) || (*where == '\0'))
460  {
461  return what;
462  }
463 
464  std::string msg = what;
465  try
466  {
467  const auto start = &xml[0];
468  if (points_within_array(where, start, (start + xml.size() + 1)))
469  {
470  enum {column_width = 79};
471  const auto idx =
472  static_cast<size_t>(std::distance(start, where));
473 
474  auto doc = std::string(start, xml.size());
475  auto lineno = 1U;
476  auto charno = 0U;
477  std::replace_if(
478  begin(doc), end(doc),
479  [&](char c) -> bool {
480  charno++;
481  if (c == '\n')
482  {
483  if (charno < idx)
484  {
485  lineno++;
486  }
487  return true;
488  }
489  return false;
490  },
491  ' ');
492 
493  // 0-termini probably got replaced by xml_document::parse
494  std::replace(begin(doc), end(doc), '\0', '>');
495 
496  // Chop off last '>'
497  doc = std::string(doc.data(), doc.length() - 1);
498 
499  // Construct message
500  msg = "in line " + std::to_string(lineno) + ":\n";
501  msg += what + '\n';
502  const auto pr = shorten(doc, idx, column_width);
503  const auto line = pr.first;
504  const auto line_index = pr.second;
505  msg += line + '\n';
506 
507  auto squiggle = std::string(column_width, ' ');
508  squiggle[line_index] = '~';
509  squiggle = remove_trailing_whitespace(squiggle);
510  msg += squiggle + '\n';
511  }
512  }
513  catch (std::exception&)
514  {
515  }
516  return msg;
517  }
518 #endif // EWS_DOXYGEN_SHOULD_SKIP_THIS
519 
520 private:
521  static std::string remove_trailing_whitespace(const std::string& str)
522  {
523  static const auto whitespace = std::string(" \t");
524  const auto end = str.find_last_not_of(whitespace);
525  return str.substr(0, end + 1);
526  }
527 
528  static std::pair<std::string, size_t> shorten(const std::string& str,
529  size_t at, size_t columns)
530  {
531  at = std::min(at, str.length());
532  if (str.length() < columns)
533  {
534  return std::make_pair(str, at);
535  }
536 
537  const auto start = std::max(at - (columns / 2), static_cast<size_t>(0));
538  const auto end = std::min(at + (columns / 2), str.length());
539  check((start < end), "Expected start to be before end");
540  std::string line;
541  std::copy(&str[start], &str[end], std::back_inserter(line));
542  const auto line_index = columns / 2;
543  return std::make_pair(line, line_index);
544  }
545 };
546 
548 enum class response_code
549 {
551  no_error,
552 
556 
559 
562 
565 
570 
574 
578 
582 
590 
593 
596 
601 
610 
617 
621 
645 
649 
663 
669 
674 
679 
683 
687 
690 
695 
700 
704 
707 
710 
713 
716 
719 
722 
725 
729 
733 
737 
742 
747 
751 
755 
760 
764 
768 
775 
779 
785 
789 
793 
797 
801 
805 
809 
813 
818 
822 
826 
832 
836 
839 
842 
846 
850 
854 
858 
862 
866 
870 
874 
878 
885 
888 
891 
894 
898 
902 
910 
915 
919 
923 
929 
933 
938 
943 
954 
958 
962 
966 
972 
976 
980 
984 
987 
990 
995 
999 
1004 
1009 
1015 
1020 
1024 
1028 
1032 
1036 
1039 
1042 
1047 
1052 
1058 
1062 
1066 
1071 
1075 
1079 
1082 
1087 
1092 
1097 
1103 
1110 
1119 
1124 
1128 
1133 
1137 
1142 
1146 
1150 
1159 
1164 
1175 
1187 
1191 
1196 
1200 
1207 
1211 
1215 
1219 
1223 
1226 
1232 
1236 
1239 
1248 
1256 
1260 
1264 
1268 
1271 
1276 
1284 
1288 
1292 
1295 
1299 
1303 
1307 
1314 
1318 
1322 
1325 
1329 
1333 
1336 
1341 
1346 
1351 
1354 
1357 
1360 
1366 
1370 
1386 
1401 
1407 
1411 
1415 
1419 
1425 
1428 
1433 
1437 
1441 
1445 
1450 
1455 
1459 
1462 
1473 
1478 
1482 
1487 
1492 
1496 
1499 
1503 
1519 
1525 
1532 
1537 
1551 
1557 
1566 
1569 
1576 
1586 
1592 
1598 
1604 
1610 
1616 
1628 
1634 
1637 
1642 
1647 
1652 
1655 
1660 
1665 
1670 
1674 
1679 
1684 
1688 
1692 
1695 
1699 
1703 
1706 
1709 
1712 
1715 
1720 
1725 
1732 
1736 
1743 
1747 
1752 
1755 
1758 
1766 
1769 
1772 
1778 
1784 
1788 
1792 
1795 
1800 
1803 
1806 
1811 
1815 
1819 
1823 
1827 
1830 
1834 
1839 
1852 
1856 
1859 
1863 
1869 
1875 
1879 
1888 
1892 
1895 
1899 
1904 
1909 
1912 
1916 
1921 
1927 
1934 
1938 
1941 
1946 
1951 
1957 
1961 
1965 
1972 
1975 
1979 
1985 
1990 
1994 
1998 
2001 
2007 
2013 
2019 
2029 
2033 
2041 
2045 
2051 
2054 
2058 
2064 
2069 
2075 
2079 
2082 
2085 
2090 
2096 
2100 
2106 
2109 
2113 
2121 
2126 
2133 
2137 
2142 
2146 
2149 
2154 
2157 
2162 
2170 
2176 
2181 
2184 
2189 
2194 
2201 
2209 
2215 
2222 
2225 
2232 
2238 
2242 
2246 
2250 
2253 
2256 
2261 
2265 
2269 
2272 
2275 
2279 
2284 
2287 
2291 
2299 
2309 
2314 
2319 
2324 
2329 
2333 
2336 
2342 
2346 
2352 
2356 
2361 
2365 
2374 
2378 
2382 
2386 
2391 
2396 
2400 
2404 
2409 
2414 
2418 
2422 
2425 
2428 
2433 
2437 
2440 
2444 
2448 
2451 
2455 
2458 
2462 
2467 
2471 
2476 
2480 
2485 
2488 
2492 
2496 
2499 
2503 
2507 
2512 
2515 
2521 
2526 
2530 
2534 
2538 
2541 
2544 
2548 
2551 
2554 
2558 
2562 
2565 
2568 
2580 
2585 
2589 
2592 
2596 
2600 
2604 
2607 
2612 
2616 
2620 
2624 
2628 
2632 
2636 
2640 
2644 
2648 
2652 
2656 
2659 
2666 
2670 
2674 
2678 
2682 
2686 
2690 
2694 
2699 
2704 
2708 
2712 
2717 
2720 
2723 
2726 
2729 
2732 
2735 
2738 };
2739 
2740 namespace internal
2741 {
2742  inline response_code str_to_response_code(const std::string& str)
2743  {
2744  if (str == "NoError")
2745  {
2746  return response_code::no_error;
2747  }
2748  if (str == "ErrorAccessDenied")
2749  {
2751  }
2752  if (str == "ErrorAccessModeSpecified")
2753  {
2755  }
2756  if (str == "ErrorAccountDisabled")
2757  {
2759  }
2760  if (str == "ErrorAddDelegatesFailed")
2761  {
2763  }
2764  if (str == "ErrorAddressSpaceNotFound")
2765  {
2767  }
2768  if (str == "ErrorADOperation")
2769  {
2771  }
2772  if (str == "ErrorADSessionFilter")
2773  {
2775  }
2776  if (str == "ErrorADUnavailable")
2777  {
2779  }
2780  if (str == "ErrorAffectedTaskOccurrencesRequired")
2781  {
2783  }
2784  if (str == "ErrorArchiveFolderPathCreation")
2785  {
2787  }
2788  if (str == "ErrorArchiveMailboxNotEnabled")
2789  {
2791  }
2792  if (str == "ErrorArchiveMailboxServiceDiscoveryFailed")
2793  {
2794  return response_code::
2796  }
2797  if (str == "ErrorAttachmentNestLevelLimitExceeded")
2798  {
2800  }
2801  if (str == "ErrorAttachmentSizeLimitExceeded")
2802  {
2804  }
2805  if (str == "ErrorAutoDiscoverFailed")
2806  {
2808  }
2809  if (str == "ErrorAvailabilityConfigNotFound")
2810  {
2812  }
2813  if (str == "ErrorBatchProcessingStopped")
2814  {
2816  }
2817  if (str == "ErrorCalendarCannotMoveOrCopyOccurrence")
2818  {
2820  }
2821  if (str == "ErrorCalendarCannotUpdateDeletedItem")
2822  {
2824  }
2825  if (str == "ErrorCalendarCannotUseIdForOccurrenceId")
2826  {
2827  return response_code::
2829  }
2830  if (str == "ErrorCalendarCannotUseIdForRecurringMasterId")
2831  {
2832  return response_code::
2834  }
2835  if (str == "ErrorCalendarDurationIsTooLong")
2836  {
2838  }
2839  if (str == "ErrorCalendarEndDateIsEarlierThanStartDate")
2840  {
2841  return response_code::
2843  }
2844  if (str == "ErrorCalendarFolderIsInvalidForCalendarView")
2845  {
2846  return response_code::
2848  }
2849  if (str == "ErrorCalendarInvalidAttributeValue")
2850  {
2852  }
2853  if (str == "ErrorCalendarInvalidDayForTimeChangePattern")
2854  {
2855  return response_code::
2857  }
2858  if (str == "ErrorCalendarInvalidDayForWeeklyRecurrence")
2859  {
2860  return response_code::
2862  }
2863  if (str == "ErrorCalendarInvalidPropertyState")
2864  {
2866  }
2867  if (str == "ErrorCalendarInvalidPropertyValue")
2868  {
2870  }
2871  if (str == "ErrorCalendarInvalidRecurrence")
2872  {
2874  }
2875  if (str == "ErrorCalendarInvalidTimeZone")
2876  {
2878  }
2879  if (str == "ErrorCalendarIsCancelledForAccept")
2880  {
2882  }
2883  if (str == "ErrorCalendarIsCancelledForDecline")
2884  {
2886  }
2887  if (str == "ErrorCalendarIsCancelledForRemove")
2888  {
2890  }
2891  if (str == "ErrorCalendarIsCancelledForTentative")
2892  {
2894  }
2895  if (str == "ErrorCalendarIsDelegatedForAccept")
2896  {
2898  }
2899  if (str == "ErrorCalendarIsDelegatedForDecline")
2900  {
2902  }
2903  if (str == "ErrorCalendarIsDelegatedForRemove")
2904  {
2906  }
2907  if (str == "ErrorCalendarIsDelegatedForTentative")
2908  {
2910  }
2911  if (str == "ErrorCalendarIsNotOrganizer")
2912  {
2914  }
2915  if (str == "ErrorCalendarIsOrganizerForAccept")
2916  {
2918  }
2919  if (str == "ErrorCalendarIsOrganizerForDecline")
2920  {
2922  }
2923  if (str == "ErrorCalendarIsOrganizerForRemove")
2924  {
2926  }
2927  if (str == "ErrorCalendarIsOrganizerForTentative")
2928  {
2930  }
2931  if (str == "ErrorCalendarMeetingRequestIsOutOfDate")
2932  {
2934  }
2935  if (str == "ErrorCalendarOccurrenceIndexIsOutOfRecurrenceRange")
2936  {
2937  return response_code::
2939  }
2940  if (str == "ErrorCalendarOccurrenceIsDeletedFromRecurrence")
2941  {
2942  return response_code::
2944  }
2945  if (str == "ErrorCalendarOutOfRange")
2946  {
2948  }
2949  if (str == "ErrorCalendarViewRangeTooBig")
2950  {
2952  }
2953  if (str == "ErrorCallerIsInvalidADAccount")
2954  {
2956  }
2957  if (str == "ErrorCannotArchiveCalendarContactTaskFolderException")
2958  {
2959  return response_code::
2961  }
2962  if (str == "ErrorCannotArchiveItemsInPublicFolders")
2963  {
2965  }
2966  if (str == "ErrorCannotArchiveItemsInArchiveMailbox")
2967  {
2969  }
2970  if (str == "ErrorCannotCreateCalendarItemInNonCalendarFolder")
2971  {
2972  return response_code::
2974  }
2975  if (str == "ErrorCannotCreateContactInNonContactFolder")
2976  {
2977  return response_code::
2979  }
2980  if (str == "ErrorCannotCreatePostItemInNonMailFolder")
2981  {
2982  return response_code::
2984  }
2985  if (str == "ErrorCannotCreateTaskInNonTaskFolder")
2986  {
2988  }
2989  if (str == "ErrorCannotDeleteObject")
2990  {
2992  }
2993  if (str == "ErrorCannotDeleteTaskOccurrence")
2994  {
2996  }
2997  if (str == "ErrorCannotDisableMandatoryExtension")
2998  {
3000  }
3001  if (str == "ErrorCannotEmptyFolder")
3002  {
3004  }
3005  if (str == "ErrorCannotGetSourceFolderPath")
3006  {
3008  }
3009  if (str == "ErrorCannotGetExternalEcpUrl")
3010  {
3012  }
3013  if (str == "ErrorCannotOpenFileAttachment")
3014  {
3016  }
3017  if (str == "ErrorCannotSetCalendarPermissionOnNonCalendarFolder")
3018  {
3019  return response_code::
3021  }
3022  if (str == "ErrorCannotSetNonCalendarPermissionOnCalendarFolder")
3023  {
3024  return response_code::
3026  }
3027  if (str == "ErrorCannotSetPermissionUnknownEntries")
3028  {
3030  }
3031  if (str == "ErrorCannotSpecifySearchFolderAsSourceFolder")
3032  {
3033  return response_code::
3035  }
3036  if (str == "ErrorCannotUseFolderIdForItemId")
3037  {
3039  }
3040  if (str == "ErrorCannotUseItemIdForFolderId")
3041  {
3043  }
3044  if (str == "ErrorChangeKeyRequired")
3045  {
3047  }
3048  if (str == "ErrorChangeKeyRequiredForWriteOperations")
3049  {
3050  return response_code::
3052  }
3053  if (str == "ErrorClientDisconnected")
3054  {
3056  }
3057  if (str == "ErrorClientIntentInvalidStateDefinition")
3058  {
3060  }
3061  if (str == "ErrorClientIntentNotFound")
3062  {
3064  }
3065  if (str == "ErrorConnectionFailed")
3066  {
3068  }
3069  if (str == "ErrorContainsFilterWrongType")
3070  {
3072  }
3073  if (str == "ErrorContentConversionFailed")
3074  {
3076  }
3077  if (str == "ErrorContentIndexingNotEnabled")
3078  {
3080  }
3081  if (str == "ErrorCorruptData")
3082  {
3084  }
3085  if (str == "ErrorCreateItemAccessDenied")
3086  {
3088  }
3089  if (str == "ErrorCreateManagedFolderPartialCompletion")
3090  {
3091  return response_code::
3093  }
3094  if (str == "ErrorCreateSubfolderAccessDenied")
3095  {
3097  }
3098  if (str == "ErrorCrossMailboxMoveCopy")
3099  {
3101  }
3102  if (str == "ErrorCrossSiteRequest")
3103  {
3105  }
3106  if (str == "ErrorDataSizeLimitExceeded")
3107  {
3109  }
3110  if (str == "ErrorDataSourceOperation")
3111  {
3113  }
3114  if (str == "ErrorDelegateAlreadyExists")
3115  {
3117  }
3118  if (str == "ErrorDelegateCannotAddOwner")
3119  {
3121  }
3122  if (str == "ErrorDelegateMissingConfiguration")
3123  {
3125  }
3126  if (str == "ErrorDelegateNoUser")
3127  {
3129  }
3130  if (str == "ErrorDelegateValidationFailed")
3131  {
3133  }
3134  if (str == "ErrorDeleteDistinguishedFolder")
3135  {
3137  }
3138  if (str == "ErrorDeleteItemsFailed")
3139  {
3141  }
3142  if (str == "ErrorDeleteUnifiedMessagingPromptFailed")
3143  {
3145  }
3146  if (str == "ErrorDistinguishedUserNotSupported")
3147  {
3149  }
3150  if (str == "ErrorDistributionListMemberNotExist")
3151  {
3153  }
3154  if (str == "ErrorDuplicateInputFolderNames")
3155  {
3157  }
3158  if (str == "ErrorDuplicateUserIdsSpecified")
3159  {
3161  }
3162  if (str == "ErrorEmailAddressMismatch")
3163  {
3165  }
3166  if (str == "ErrorEventNotFound")
3167  {
3169  }
3170  if (str == "ErrorExceededConnectionCount")
3171  {
3173  }
3174  if (str == "ErrorExceededSubscriptionCount")
3175  {
3177  }
3178  if (str == "ErrorExceededFindCountLimit")
3179  {
3181  }
3182  if (str == "ErrorExpiredSubscription")
3183  {
3185  }
3186  if (str == "ErrorExtensionNotFound")
3187  {
3189  }
3190  if (str == "ErrorFolderCorrupt")
3191  {
3193  }
3194  if (str == "ErrorFolderExists")
3195  {
3197  }
3198  if (str == "ErrorFolderNotFound")
3199  {
3201  }
3202  if (str == "ErrorFolderPropertyRequestFailed")
3203  {
3205  }
3206  if (str == "ErrorFolderSave")
3207  {
3209  }
3210  if (str == "ErrorFolderSaveFailed")
3211  {
3213  }
3214  if (str == "ErrorFolderSavePropertyError")
3215  {
3217  }
3218  if (str == "ErrorFreeBusyGenerationFailed")
3219  {
3221  }
3222  if (str == "ErrorGetServerSecurityDescriptorFailed")
3223  {
3225  }
3226  if (str == "ErrorImContactLimitReached")
3227  {
3229  }
3230  if (str == "ErrorImGroupDisplayNameAlreadyExists")
3231  {
3233  }
3234  if (str == "ErrorImGroupLimitReached")
3235  {
3237  }
3238  if (str == "ErrorImpersonateUserDenied")
3239  {
3241  }
3242  if (str == "ErrorImpersonationDenied")
3243  {
3245  }
3246  if (str == "ErrorImpersonationFailed")
3247  {
3249  }
3250  if (str == "ErrorIncorrectSchemaVersion")
3251  {
3253  }
3254  if (str == "ErrorIncorrectUpdatePropertyCount")
3255  {
3257  }
3258  if (str == "ErrorIndividualMailboxLimitReached")
3259  {
3261  }
3262  if (str == "ErrorInsufficientResources")
3263  {
3265  }
3266  if (str == "ErrorInternalServerError")
3267  {
3269  }
3270  if (str == "ErrorInternalServerTransientError")
3271  {
3273  }
3274  if (str == "ErrorInvalidAccessLevel")
3275  {
3277  }
3278  if (str == "ErrorInvalidArgument")
3279  {
3281  }
3282  if (str == "ErrorInvalidAttachmentId")
3283  {
3285  }
3286  if (str == "ErrorInvalidAttachmentSubfilter")
3287  {
3289  }
3290  if (str == "ErrorInvalidAttachmentSubfilterTextFilter")
3291  {
3292  return response_code::
3294  }
3295  if (str == "ErrorInvalidAuthorizationContext")
3296  {
3298  }
3299  if (str == "ErrorInvalidChangeKey")
3300  {
3302  }
3303  if (str == "ErrorInvalidClientSecurityContext")
3304  {
3306  }
3307  if (str == "ErrorInvalidCompleteDate")
3308  {
3310  }
3311  if (str == "ErrorInvalidContactEmailAddress")
3312  {
3314  }
3315  if (str == "ErrorInvalidContactEmailIndex")
3316  {
3318  }
3319  if (str == "ErrorInvalidCrossForestCredentials")
3320  {
3322  }
3323  if (str == "ErrorInvalidDelegatePermission")
3324  {
3326  }
3327  if (str == "ErrorInvalidDelegateUserId")
3328  {
3330  }
3331  if (str == "ErrorInvalidExchangeImpersonationHeaderData")
3332  {
3333  return response_code::
3335  }
3336  if (str == "ErrorInvalidExcludesRestriction")
3337  {
3339  }
3340  if (str == "ErrorInvalidExpressionTypeForSubFilter")
3341  {
3343  }
3344  if (str == "ErrorInvalidExtendedProperty")
3345  {
3347  }
3348  if (str == "ErrorInvalidExtendedPropertyValue")
3349  {
3351  }
3352  if (str == "ErrorInvalidExternalSharingInitiator")
3353  {
3355  }
3356  if (str == "ErrorInvalidExternalSharingSubscriber")
3357  {
3359  }
3360  if (str == "ErrorInvalidFederatedOrganizationId")
3361  {
3363  }
3364  if (str == "ErrorInvalidFolderId")
3365  {
3367  }
3368  if (str == "ErrorInvalidFolderTypeForOperation")
3369  {
3371  }
3372  if (str == "ErrorInvalidFractionalPagingParameters")
3373  {
3375  }
3376  if (str == "ErrorInvalidGetSharingFolderRequest")
3377  {
3379  }
3380  if (str == "ErrorInvalidFreeBusyViewType")
3381  {
3383  }
3384  if (str == "ErrorInvalidId")
3385  {
3387  }
3388  if (str == "ErrorInvalidIdEmpty")
3389  {
3391  }
3392  if (str == "ErrorInvalidLikeRequest")
3393  {
3395  }
3396  if (str == "ErrorInvalidIdMalformed")
3397  {
3399  }
3400  if (str == "ErrorInvalidIdMalformedEwsLegacyIdFormat")
3401  {
3402  return response_code::
3404  }
3405  if (str == "ErrorInvalidIdMonikerTooLong")
3406  {
3408  }
3409  if (str == "ErrorInvalidIdNotAnItemAttachmentId")
3410  {
3412  }
3413  if (str == "ErrorInvalidIdReturnedByResolveNames")
3414  {
3416  }
3417  if (str == "ErrorInvalidIdStoreObjectIdTooLong")
3418  {
3420  }
3421  if (str == "ErrorInvalidIdTooManyAttachmentLevels")
3422  {
3424  }
3425  if (str == "ErrorInvalidIdXml")
3426  {
3428  }
3429  if (str == "ErrorInvalidImContactId")
3430  {
3432  }
3433  if (str == "ErrorInvalidImDistributionGroupSmtpAddress")
3434  {
3435  return response_code::
3437  }
3438  if (str == "ErrorInvalidImGroupId")
3439  {
3441  }
3442  if (str == "ErrorInvalidIndexedPagingParameters")
3443  {
3445  }
3446  if (str == "ErrorInvalidInternetHeaderChildNodes")
3447  {
3449  }
3450  if (str == "ErrorInvalidItemForOperationArchiveItem")
3451  {
3453  }
3454  if (str == "ErrorInvalidItemForOperationAcceptItem")
3455  {
3457  }
3458  if (str == "ErrorInvalidItemForOperationCancelItem")
3459  {
3461  }
3462  if (str == "ErrorInvalidItemForOperationCreateItemAttachment")
3463  {
3464  return response_code::
3466  }
3467  if (str == "ErrorInvalidItemForOperationCreateItem")
3468  {
3470  }
3471  if (str == "ErrorInvalidItemForOperationDeclineItem")
3472  {
3474  }
3475  if (str == "ErrorInvalidItemForOperationExpandDL")
3476  {
3478  }
3479  if (str == "ErrorInvalidItemForOperationRemoveItem")
3480  {
3482  }
3483  if (str == "ErrorInvalidItemForOperationSendItem")
3484  {
3486  }
3487  if (str == "ErrorInvalidItemForOperationTentative")
3488  {
3490  }
3491  if (str == "ErrorInvalidLogonType")
3492  {
3494  }
3495  if (str == "ErrorInvalidMailbox")
3496  {
3498  }
3499  if (str == "ErrorInvalidManagedFolderProperty")
3500  {
3502  }
3503  if (str == "ErrorInvalidManagedFolderQuota")
3504  {
3506  }
3507  if (str == "ErrorInvalidManagedFolderSize")
3508  {
3510  }
3511  if (str == "ErrorInvalidMergedFreeBusyInterval")
3512  {
3514  }
3515  if (str == "ErrorInvalidNameForNameResolution")
3516  {
3518  }
3519  if (str == "ErrorInvalidNetworkServiceContext")
3520  {
3522  }
3523  if (str == "ErrorInvalidOofParameter")
3524  {
3526  }
3527  if (str == "ErrorInvalidOperation")
3528  {
3530  }
3531  if (str == "ErrorInvalidOrganizationRelationshipForFreeBusy")
3532  {
3533  return response_code::
3535  }
3536  if (str == "ErrorInvalidPagingMaxRows")
3537  {
3539  }
3540  if (str == "ErrorInvalidParentFolder")
3541  {
3543  }
3544  if (str == "ErrorInvalidPercentCompleteValue")
3545  {
3547  }
3548  if (str == "ErrorInvalidPermissionSettings")
3549  {
3551  }
3552  if (str == "ErrorInvalidPhoneCallId")
3553  {
3555  }
3556  if (str == "ErrorInvalidPhoneNumber")
3557  {
3559  }
3560  if (str == "ErrorInvalidPropertyAppend")
3561  {
3563  }
3564  if (str == "ErrorInvalidPropertyDelete")
3565  {
3567  }
3568  if (str == "ErrorInvalidPropertyForExists")
3569  {
3571  }
3572  if (str == "ErrorInvalidPropertyForOperation")
3573  {
3575  }
3576  if (str == "ErrorInvalidPropertyRequest")
3577  {
3579  }
3580  if (str == "ErrorInvalidPropertySet")
3581  {
3583  }
3584  if (str == "ErrorInvalidPropertyUpdateSentMessage")
3585  {
3587  }
3588  if (str == "ErrorInvalidProxySecurityContext")
3589  {
3591  }
3592  if (str == "ErrorInvalidPullSubscriptionId")
3593  {
3595  }
3596  if (str == "ErrorInvalidPushSubscriptionUrl")
3597  {
3599  }
3600  if (str == "ErrorInvalidRecipients")
3601  {
3603  }
3604  if (str == "ErrorInvalidRecipientSubfilter")
3605  {
3607  }
3608  if (str == "ErrorInvalidRecipientSubfilterComparison")
3609  {
3611  }
3612  if (str == "ErrorInvalidRecipientSubfilterOrder")
3613  {
3615  }
3616  if (str == "ErrorInvalidRecipientSubfilterTextFilter")
3617  {
3619  }
3620  if (str == "ErrorInvalidReferenceItem")
3621  {
3623  }
3624  if (str == "ErrorInvalidRequest")
3625  {
3627  }
3628  if (str == "ErrorInvalidRestriction")
3629  {
3631  }
3632  if (str == "ErrorInvalidRetentionTagTypeMismatch")
3633  {
3635  }
3636  if (str == "ErrorInvalidRetentionTagInvisible")
3637  {
3639  }
3640  if (str == "ErrorInvalidRetentionTagInheritance")
3641  {
3643  }
3644  if (str == "ErrorInvalidRetentionTagIdGuid")
3645  {
3647  }
3648  if (str == "ErrorInvalidRoutingType")
3649  {
3651  }
3652  if (str == "ErrorInvalidScheduledOofDuration")
3653  {
3655  }
3656  if (str == "ErrorInvalidSchemaVersionForMailboxVersion")
3657  {
3658  return response_code::
3660  }
3661  if (str == "ErrorInvalidSecurityDescriptor")
3662  {
3664  }
3665  if (str == "ErrorInvalidSendItemSaveSettings")
3666  {
3668  }
3669  if (str == "ErrorInvalidSerializedAccessToken")
3670  {
3672  }
3673  if (str == "ErrorInvalidSharingData")
3674  {
3676  }
3677  if (str == "ErrorInvalidSharingMessage")
3678  {
3680  }
3681  if (str == "ErrorInvalidSid")
3682  {
3684  }
3685  if (str == "ErrorInvalidSIPUri")
3686  {
3688  }
3689  if (str == "ErrorInvalidServerVersion")
3690  {
3692  }
3693  if (str == "ErrorInvalidSmtpAddress")
3694  {
3696  }
3697  if (str == "ErrorInvalidSubfilterType")
3698  {
3700  }
3701  if (str == "ErrorInvalidSubfilterTypeNotAttendeeType")
3702  {
3703  return response_code::
3705  }
3706  if (str == "ErrorInvalidSubfilterTypeNotRecipientType")
3707  {
3708  return response_code::
3710  }
3711  if (str == "ErrorInvalidSubscription")
3712  {
3714  }
3715  if (str == "ErrorInvalidSubscriptionRequest")
3716  {
3718  }
3719  if (str == "ErrorInvalidSyncStateData")
3720  {
3722  }
3723  if (str == "ErrorInvalidTimeInterval")
3724  {
3726  }
3727  if (str == "ErrorInvalidUserInfo")
3728  {
3730  }
3731  if (str == "ErrorInvalidUserOofSettings")
3732  {
3734  }
3735  if (str == "ErrorInvalidUserPrincipalName")
3736  {
3738  }
3739  if (str == "ErrorInvalidUserSid")
3740  {
3742  }
3743  if (str == "ErrorInvalidUserSidMissingUPN")
3744  {
3746  }
3747  if (str == "ErrorInvalidValueForProperty")
3748  {
3750  }
3751  if (str == "ErrorInvalidWatermark")
3752  {
3754  }
3755  if (str == "ErrorIPGatewayNotFound")
3756  {
3758  }
3759  if (str == "ErrorIrresolvableConflict")
3760  {
3762  }
3763  if (str == "ErrorItemCorrupt")
3764  {
3766  }
3767  if (str == "ErrorItemNotFound")
3768  {
3770  }
3771  if (str == "ErrorItemPropertyRequestFailed")
3772  {
3774  }
3775  if (str == "ErrorItemSave")
3776  {
3778  }
3779  if (str == "ErrorItemSavePropertyError")
3780  {
3782  }
3783  if (str == "ErrorLegacyMailboxFreeBusyViewTypeNotMerged")
3784  {
3785  return response_code::
3787  }
3788  if (str == "ErrorLocalServerObjectNotFound")
3789  {
3791  }
3792  if (str == "ErrorLogonAsNetworkServiceFailed")
3793  {
3795  }
3796  if (str == "ErrorMailboxConfiguration")
3797  {
3799  }
3800  if (str == "ErrorMailboxDataArrayEmpty")
3801  {
3803  }
3804  if (str == "ErrorMailboxDataArrayTooBig")
3805  {
3807  }
3808  if (str == "ErrorMailboxFailover")
3809  {
3811  }
3812  if (str == "ErrorMailboxHoldNotFound")
3813  {
3815  }
3816  if (str == "ErrorMailboxLogonFailed")
3817  {
3819  }
3820  if (str == "ErrorMailboxMoveInProgress")
3821  {
3823  }
3824  if (str == "ErrorMailboxStoreUnavailable")
3825  {
3827  }
3828  if (str == "ErrorMailRecipientNotFound")
3829  {
3831  }
3832  if (str == "ErrorMailTipsDisabled")
3833  {
3835  }
3836  if (str == "ErrorManagedFolderAlreadyExists")
3837  {
3839  }
3840  if (str == "ErrorManagedFolderNotFound")
3841  {
3843  }
3844  if (str == "ErrorManagedFoldersRootFailure")
3845  {
3847  }
3848  if (str == "ErrorMeetingSuggestionGenerationFailed")
3849  {
3851  }
3852  if (str == "ErrorMessageDispositionRequired")
3853  {
3855  }
3856  if (str == "ErrorMessageSizeExceeded")
3857  {
3859  }
3860  if (str == "ErrorMessageTrackingNoSuchDomain")
3861  {
3863  }
3864  if (str == "ErrorMessageTrackingPermanentError")
3865  {
3867  }
3868  if (str == " ErrorMessageTrackingTransientError")
3869  {
3871  }
3872  if (str == "ErrorMimeContentConversionFailed")
3873  {
3875  }
3876  if (str == "ErrorMimeContentInvalid")
3877  {
3879  }
3880  if (str == "ErrorMimeContentInvalidBase64String")
3881  {
3883  }
3884  if (str == "ErrorMissingArgument")
3885  {
3887  }
3888  if (str == "ErrorMissingEmailAddress")
3889  {
3891  }
3892  if (str == "ErrorMissingEmailAddressForManagedFolder")
3893  {
3894  return response_code::
3896  }
3897  if (str == "ErrorMissingInformationEmailAddress")
3898  {
3900  }
3901  if (str == "ErrorMissingInformationReferenceItemId")
3902  {
3904  }
3905  if (str == "ErrorMissingItemForCreateItemAttachment")
3906  {
3908  }
3909  if (str == "ErrorMissingManagedFolderId")
3910  {
3912  }
3913  if (str == "ErrorMissingRecipients")
3914  {
3916  }
3917  if (str == "ErrorMissingUserIdInformation")
3918  {
3920  }
3921  if (str == "ErrorMoreThanOneAccessModeSpecified")
3922  {
3924  }
3925  if (str == "ErrorMoveCopyFailed")
3926  {
3928  }
3929  if (str == "ErrorMoveDistinguishedFolder")
3930  {
3932  }
3933  if (str == "ErrorMultiLegacyMailboxAccess")
3934  {
3936  }
3937  if (str == "ErrorNameResolutionMultipleResults")
3938  {
3940  }
3941  if (str == "ErrorNameResolutionNoMailbox")
3942  {
3944  }
3945  if (str == "ErrorNameResolutionNoResults")
3946  {
3948  }
3949  if (str == "ErrorNoApplicableProxyCASServersAvailable")
3950  {
3951  return response_code::
3953  }
3954  if (str == "ErrorNoCalendar")
3955  {
3957  }
3958  if (str == "ErrorNoDestinationCASDueToKerberosRequirements")
3959  {
3960  return response_code::
3962  }
3963  if (str == "ErrorNoDestinationCASDueToSSLRequirements")
3964  {
3965  return response_code::
3967  }
3968  if (str == "ErrorNoDestinationCASDueToVersionMismatch")
3969  {
3970  return response_code::
3972  }
3973  if (str == "ErrorNoFolderClassOverride")
3974  {
3976  }
3977  if (str == "ErrorNoFreeBusyAccess")
3978  {
3980  }
3981  if (str == "ErrorNonExistentMailbox")
3982  {
3984  }
3985  if (str == "ErrorNonPrimarySmtpAddress")
3986  {
3988  }
3989  if (str == "ErrorNoPropertyTagForCustomProperties")
3990  {
3992  }
3993  if (str == "ErrorNoPublicFolderReplicaAvailable")
3994  {
3996  }
3997  if (str == "ErrorNoPublicFolderServerAvailable")
3998  {
4000  }
4001  if (str == "ErrorNoRespondingCASInDestinationSite")
4002  {
4004  }
4005  if (str == "ErrorNotDelegate")
4006  {
4008  }
4009  if (str == "ErrorNotEnoughMemory")
4010  {
4012  }
4013  if (str == "ErrorNotSupportedSharingMessage")
4014  {
4016  }
4017  if (str == "ErrorObjectTypeChanged")
4018  {
4020  }
4021  if (str == "ErrorOccurrenceCrossingBoundary")
4022  {
4024  }
4025  if (str == "ErrorOccurrenceTimeSpanTooBig")
4026  {
4028  }
4029  if (str == "ErrorOperationNotAllowedWithPublicFolderRoot")
4030  {
4031  return response_code::
4033  }
4034  if (str == "ErrorOrganizationNotFederated")
4035  {
4037  }
4038  if (str == "ErrorParentFolderIdRequired")
4039  {
4041  }
4042  if (str == "ErrorParentFolderNotFound")
4043  {
4045  }
4046  if (str == "ErrorPasswordChangeRequired")
4047  {
4049  }
4050  if (str == "ErrorPasswordExpired")
4051  {
4053  }
4054  if (str == "ErrorPermissionNotAllowedByPolicy")
4055  {
4057  }
4058  if (str == "ErrorPhoneNumberNotDialable")
4059  {
4061  }
4062  if (str == "ErrorPropertyUpdate")
4063  {
4065  }
4066  if (str == "ErrorPromptPublishingOperationFailed")
4067  {
4069  }
4070  if (str == "ErrorPropertyValidationFailure")
4071  {
4073  }
4074  if (str == "ErrorProxiedSubscriptionCallFailure")
4075  {
4077  }
4078  if (str == "ErrorProxyCallFailed")
4079  {
4081  }
4082  if (str == "ErrorProxyGroupSidLimitExceeded")
4083  {
4085  }
4086  if (str == "ErrorProxyRequestNotAllowed")
4087  {
4089  }
4090  if (str == "ErrorProxyRequestProcessingFailed")
4091  {
4093  }
4094  if (str == "ErrorProxyServiceDiscoveryFailed")
4095  {
4097  }
4098  if (str == "ErrorProxyTokenExpired")
4099  {
4101  }
4102  if (str == "ErrorPublicFolderMailboxDiscoveryFailed")
4103  {
4105  }
4106  if (str == "ErrorPublicFolderOperationFailed")
4107  {
4109  }
4110  if (str == "ErrorPublicFolderRequestProcessingFailed")
4111  {
4113  }
4114  if (str == "ErrorPublicFolderServerNotFound")
4115  {
4117  }
4118  if (str == "ErrorPublicFolderSyncException")
4119  {
4121  }
4122  if (str == "ErrorQueryFilterTooLong")
4123  {
4125  }
4126  if (str == "ErrorQuotaExceeded")
4127  {
4129  }
4130  if (str == "ErrorReadEventsFailed")
4131  {
4133  }
4134  if (str == "ErrorReadReceiptNotPending")
4135  {
4137  }
4138  if (str == "ErrorRecurrenceEndDateTooBig")
4139  {
4141  }
4142  if (str == "ErrorRecurrenceHasNoOccurrence")
4143  {
4145  }
4146  if (str == "ErrorRemoveDelegatesFailed")
4147  {
4149  }
4150  if (str == "ErrorRequestAborted")
4151  {
4153  }
4154  if (str == "ErrorRequestStreamTooBig")
4155  {
4157  }
4158  if (str == "ErrorRequiredPropertyMissing")
4159  {
4161  }
4162  if (str == "ErrorResolveNamesInvalidFolderType")
4163  {
4165  }
4166  if (str == "ErrorResolveNamesOnlyOneContactsFolderAllowed")
4167  {
4168  return response_code::
4170  }
4171  if (str == "ErrorResponseSchemaValidation")
4172  {
4174  }
4175  if (str == "ErrorRestrictionTooLong")
4176  {
4178  }
4179  if (str == "ErrorRestrictionTooComplex")
4180  {
4182  }
4183  if (str == "ErrorResultSetTooBig")
4184  {
4186  }
4187  if (str == "ErrorSavedItemFolderNotFound")
4188  {
4190  }
4191  if (str == "ErrorSchemaValidation")
4192  {
4194  }
4195  if (str == "ErrorSearchFolderNotInitialized")
4196  {
4198  }
4199  if (str == "ErrorSendAsDenied")
4200  {
4202  }
4203  if (str == "ErrorSendMeetingCancellationsRequired")
4204  {
4206  }
4207  if (str == "ErrorSendMeetingInvitationsOrCancellationsRequired")
4208  {
4209  return response_code::
4211  }
4212  if (str == "ErrorSendMeetingInvitationsRequired")
4213  {
4215  }
4216  if (str == "ErrorSentMeetingRequestUpdate")
4217  {
4219  }
4220  if (str == "ErrorSentTaskRequestUpdate")
4221  {
4223  }
4224  if (str == "ErrorServerBusy")
4225  {
4227  }
4228  if (str == "ErrorServiceDiscoveryFailed")
4229  {
4231  }
4232  if (str == "ErrorStaleObject")
4233  {
4235  }
4236  if (str == "ErrorSubmissionQuotaExceeded")
4237  {
4239  }
4240  if (str == "ErrorSubscriptionAccessDenied")
4241  {
4243  }
4244  if (str == "ErrorSubscriptionDelegateAccessNotSupported")
4245  {
4246  return response_code::
4248  }
4249  if (str == "ErrorSubscriptionNotFound")
4250  {
4252  }
4253  if (str == "ErrorSubscriptionUnsubscribed")
4254  {
4256  }
4257  if (str == "ErrorSyncFolderNotFound")
4258  {
4260  }
4261  if (str == "ErrorTeamMailboxNotFound")
4262  {
4264  }
4265  if (str == "ErrorTeamMailboxNotLinkedToSharePoint")
4266  {
4268  }
4269  if (str == "ErrorTeamMailboxUrlValidationFailed")
4270  {
4272  }
4273  if (str == "ErrorTeamMailboxNotAuthorizedOwner")
4274  {
4276  }
4277  if (str == "ErrorTeamMailboxActiveToPendingDelete")
4278  {
4280  }
4281  if (str == "ErrorTeamMailboxFailedSendingNotifications")
4282  {
4283  return response_code::
4285  }
4286  if (str == "ErrorTeamMailboxErrorUnknown")
4287  {
4289  }
4290  if (str == "ErrorTimeIntervalTooBig")
4291  {
4293  }
4294  if (str == "ErrorTimeoutExpired")
4295  {
4297  }
4298  if (str == "ErrorTimeZone")
4299  {
4301  }
4302  if (str == "ErrorToFolderNotFound")
4303  {
4305  }
4306  if (str == "ErrorTokenSerializationDenied")
4307  {
4309  }
4310  if (str == "ErrorTooManyObjectsOpened")
4311  {
4313  }
4314  if (str == "ErrorUnifiedMessagingDialPlanNotFound")
4315  {
4317  }
4318  if (str == "ErrorUnifiedMessagingReportDataNotFound")
4319  {
4321  }
4322  if (str == "ErrorUnifiedMessagingPromptNotFound")
4323  {
4325  }
4326  if (str == "ErrorUnifiedMessagingRequestFailed")
4327  {
4329  }
4330  if (str == "ErrorUnifiedMessagingServerNotFound")
4331  {
4333  }
4334  if (str == "ErrorUnableToGetUserOofSettings")
4335  {
4337  }
4338  if (str == "ErrorUnableToRemoveImContactFromGroup")
4339  {
4341  }
4342  if (str == "ErrorUnsupportedCulture")
4343  {
4345  }
4346  if (str == "ErrorUnsupportedMapiPropertyType")
4347  {
4349  }
4350  if (str == "ErrorUnsupportedMimeConversion")
4351  {
4353  }
4354  if (str == "ErrorUnsupportedPathForQuery")
4355  {
4357  }
4358  if (str == "ErrorUnsupportedPathForSortGroup")
4359  {
4361  }
4362  if (str == "ErrorUnsupportedPropertyDefinition")
4363  {
4365  }
4366  if (str == "ErrorUnsupportedQueryFilter")
4367  {
4369  }
4370  if (str == "ErrorUnsupportedRecurrence")
4371  {
4373  }
4374  if (str == "ErrorUnsupportedSubFilter")
4375  {
4377  }
4378  if (str == "ErrorUnsupportedTypeForConversion")
4379  {
4381  }
4382  if (str == "ErrorUpdateDelegatesFailed")
4383  {
4385  }
4386  if (str == "ErrorUpdatePropertyMismatch")
4387  {
4389  }
4390  if (str == "ErrorUserNotUnifiedMessagingEnabled")
4391  {
4393  }
4394  if (str == "ErrorUserNotAllowedByPolicy")
4395  {
4397  }
4398  if (str == "ErrorUserWithoutFederatedProxyAddress")
4399  {
4401  }
4402  if (str == "ErrorValueOutOfRange")
4403  {
4405  }
4406  if (str == "ErrorVirusDetected")
4407  {
4409  }
4410  if (str == "ErrorVirusMessageDeleted")
4411  {
4413  }
4414  if (str == "ErrorVoiceMailNotImplemented")
4415  {
4417  }
4418  if (str == "ErrorWebRequestInInvalidState")
4419  {
4421  }
4422  if (str == "ErrorWin32InteropError")
4423  {
4425  }
4426  if (str == "ErrorWorkingHoursSaveFailed")
4427  {
4429  }
4430  if (str == "ErrorWorkingHoursXmlMalformed")
4431  {
4433  }
4434  if (str == "ErrorWrongServerVersion")
4435  {
4437  }
4438  if (str == "ErrorWrongServerVersionDelegate")
4439  {
4441  }
4442  if (str == "ErrorMissingInformationSharingFolderId")
4443  {
4445  }
4446  if (str == "ErrorDuplicateSOAPHeader")
4447  {
4449  }
4450  if (str == "ErrorSharingSynchronizationFailed")
4451  {
4453  }
4454  if (str == "ErrorSharingNoExternalEwsAvailable")
4455  {
4457  }
4458  if (str == "ErrorFreeBusyDLLimitReached")
4459  {
4461  }
4462  if (str == "ErrorNotAllowedExternalSharingByPolicy")
4463  {
4465  }
4466  if (str == "ErrorMessageTrackingTransientError")
4467  {
4469  }
4470  if (str == "ErrorApplyConversationActionFailed")
4471  {
4473  }
4474  if (str == "ErrorInboxRulesValidationError")
4475  {
4477  }
4478  if (str == "ErrorOutlookRuleBlobExists")
4479  {
4481  }
4482  if (str == "ErrorRulesOverQuota")
4483  {
4485  }
4486  if (str == "ErrorNewEventStreamConnectionOpened")
4487  {
4489  }
4490  if (str == "ErrorMissedNotificationEvents")
4491  {
4493  }
4494  if (str == "ErrorDuplicateLegacyDistinguishedName")
4495  {
4497  }
4498  if (str == "ErrorInvalidClientAccessTokenRequest")
4499  {
4501  }
4502  if (str == "ErrorNoSpeechDetected")
4503  {
4505  }
4506  if (str == "ErrorUMServerUnavailable")
4507  {
4509  }
4510  if (str == "ErrorRecipientNotFound")
4511  {
4513  }
4514  if (str == "ErrorRecognizerNotInstalled")
4515  {
4517  }
4518  if (str == "ErrorSpeechGrammarError")
4519  {
4521  }
4522  if (str == "ErrorInvalidManagementRoleHeader")
4523  {
4525  }
4526  if (str == "ErrorLocationServicesDisabled")
4527  {
4529  }
4530  if (str == "ErrorLocationServicesRequestTimedOut")
4531  {
4533  }
4534  if (str == "ErrorLocationServicesRequestFailed")
4535  {
4537  }
4538  if (str == "ErrorLocationServicesInvalidRequest")
4539  {
4541  }
4542  if (str == "ErrorWeatherServiceDisabled")
4543  {
4545  }
4546  if (str == "ErrorMailboxScopeNotAllowedWithoutQueryString")
4547  {
4548  return response_code::
4550  }
4551  if (str == "ErrorArchiveMailboxSearchFailed")
4552  {
4554  }
4555  if (str == "ErrorGetRemoteArchiveFolderFailed")
4556  {
4558  }
4559  if (str == "ErrorFindRemoteArchiveFolderFailed")
4560  {
4562  }
4563  if (str == "ErrorGetRemoteArchiveItemFailed")
4564  {
4566  }
4567  if (str == "ErrorExportRemoteArchiveItemsFailed")
4568  {
4570  }
4571  if (str == "ErrorInvalidPhotoSize")
4572  {
4574  }
4575  if (str == "ErrorSearchQueryHasTooManyKeywords")
4576  {
4578  }
4579  if (str == "ErrorSearchTooManyMailboxes")
4580  {
4582  }
4583  if (str == "ErrorInvalidRetentionTagNone")
4584  {
4586  }
4587  if (str == "ErrorDiscoverySearchesDisabled")
4588  {
4590  }
4591  if (str == "ErrorCalendarSeekToConditionNotSupported")
4592  {
4593  return response_code::
4595  }
4596  if (str == "ErrorCalendarIsGroupMailboxForAccept")
4597  {
4599  }
4600  if (str == "ErrorCalendarIsGroupMailboxForDecline")
4601  {
4603  }
4604  if (str == "ErrorCalendarIsGroupMailboxForTentative")
4605  {
4607  }
4608  if (str == "ErrorCalendarIsGroupMailboxForSuppressReadReceipt")
4609  {
4610  return response_code::
4612  }
4613  if (str == "ErrorOrganizationAccessBlocked")
4614  {
4616  }
4617  if (str == "ErrorInvalidLicense")
4618  {
4620  }
4621  if (str == "ErrorMessagePerFolderCountReceiveQuotaExceeded")
4622  {
4623  return response_code::
4625  }
4626  throw exception("Unrecognized response code: " + str);
4627  }
4628 
4629  inline std::string enum_to_str(response_code code)
4630  {
4631  switch (code)
4632  {
4634  return "NoError";
4636  return "ErrorAccessDenied";
4638  return "ErrorAccessModeSpecified";
4640  return "ErrorAccountDisabled";
4642  return "ErrorAddDelegatesFailed";
4644  return "ErrorAddressSpaceNotFound";
4646  return "ErrorADOperation";
4648  return "ErrorADSessionFilter";
4650  return "ErrorADUnavailable";
4652  return "ErrorAffectedTaskOccurrencesRequired";
4654  return "ErrorArchiveFolderPathCreation";
4656  return "ErrorArchiveMailboxNotEnabled";
4658  return "ErrorArchiveMailboxServiceDiscoveryFailed";
4660  return "ErrorAttachmentNestLevelLimitExceeded";
4662  return "ErrorAttachmentSizeLimitExceeded";
4664  return "ErrorAutoDiscoverFailed";
4666  return "ErrorAvailabilityConfigNotFound";
4668  return "ErrorBatchProcessingStopped";
4670  return "ErrorCalendarCannotMoveOrCopyOccurrence";
4672  return "ErrorCalendarCannotUpdateDeletedItem";
4674  return "ErrorCalendarCannotUseIdForOccurrenceId";
4675  case response_code::
4677  return "ErrorCalendarCannotUseIdForRecurringMasterId";
4679  return "ErrorCalendarDurationIsTooLong";
4681  return "ErrorCalendarEndDateIsEarlierThanStartDate";
4683  return "ErrorCalendarFolderIsInvalidForCalendarView";
4685  return "ErrorCalendarInvalidAttributeValue";
4687  return "ErrorCalendarInvalidDayForTimeChangePattern";
4689  return "ErrorCalendarInvalidDayForWeeklyRecurrence";
4691  return "ErrorCalendarInvalidPropertyState";
4693  return "ErrorCalendarInvalidPropertyValue";
4695  return "ErrorCalendarInvalidRecurrence";
4697  return "ErrorCalendarInvalidTimeZone";
4699  return "ErrorCalendarIsCancelledForAccept";
4701  return "ErrorCalendarIsCancelledForDecline";
4703  return "ErrorCalendarIsCancelledForRemove";
4705  return "ErrorCalendarIsCancelledForTentative";
4707  return "ErrorCalendarIsDelegatedForAccept";
4709  return "ErrorCalendarIsDelegatedForDecline";
4711  return "ErrorCalendarIsDelegatedForRemove";
4713  return "ErrorCalendarIsDelegatedForTentative";
4715  return "ErrorCalendarIsNotOrganizer";
4717  return "ErrorCalendarIsOrganizerForAccept";
4719  return "ErrorCalendarIsOrganizerForDecline";
4721  return "ErrorCalendarIsOrganizerForRemove";
4723  return "ErrorCalendarIsOrganizerForTentative";
4725  return "ErrorCalendarMeetingRequestIsOutOfDate";
4726  case response_code::
4728  return "ErrorCalendarOccurrenceIndexIsOutOfRecurrenceRange";
4729  case response_code::
4731  return "ErrorCalendarOccurrenceIsDeletedFromRecurrence";
4733  return "ErrorCalendarOutOfRange";
4735  return "ErrorCalendarViewRangeTooBig";
4737  return "ErrorCallerIsInvalidADAccount";
4738  case response_code::
4740  return "ErrorCannotArchiveCalendarContactTaskFolderException";
4742  return "ErrorCannotArchiveItemsInPublicFolders";
4744  return "ErrorCannotArchiveItemsInArchiveMailbox";
4745  case response_code::
4747  return "ErrorCannotCreateCalendarItemInNonCalendarFolder";
4749  return "ErrorCannotCreateContactInNonContactFolder";
4751  return "ErrorCannotCreatePostItemInNonMailFolder";
4753  return "ErrorCannotCreateTaskInNonTaskFolder";
4755  return "ErrorCannotDeleteObject";
4757  return "ErrorCannotDeleteTaskOccurrence";
4759  return "ErrorCannotDisableMandatoryExtension";
4761  return "ErrorCannotEmptyFolder";
4763  return "ErrorCannotGetSourceFolderPath";
4765  return "ErrorCannotGetExternalEcpUrl";
4767  return "ErrorCannotOpenFileAttachment";
4768  case response_code::
4770  return "ErrorCannotSetCalendarPermissionOnNonCalendarFolder";
4771  case response_code::
4773  return "ErrorCannotSetNonCalendarPermissionOnCalendarFolder";
4775  return "ErrorCannotSetPermissionUnknownEntries";
4777  return "ErrorCannotSpecifySearchFolderAsSourceFolder";
4779  return "ErrorCannotUseFolderIdForItemId";
4781  return "ErrorCannotUseItemIdForFolderId";
4783  return "ErrorChangeKeyRequired";
4785  return "ErrorChangeKeyRequiredForWriteOperations";
4787  return "ErrorClientDisconnected";
4789  return "ErrorClientIntentInvalidStateDefinition";
4791  return "ErrorClientIntentNotFound";
4793  return "ErrorConnectionFailed";
4795  return "ErrorContainsFilterWrongType";
4797  return "ErrorContentConversionFailed";
4799  return "ErrorContentIndexingNotEnabled";
4801  return "ErrorCorruptData";
4803  return "ErrorCreateItemAccessDenied";
4805  return "ErrorCreateManagedFolderPartialCompletion";
4807  return "ErrorCreateSubfolderAccessDenied";
4809  return "ErrorCrossMailboxMoveCopy";
4811  return "ErrorCrossSiteRequest";
4813  return "ErrorDataSizeLimitExceeded";
4815  return "ErrorDataSourceOperation";
4817  return "ErrorDelegateAlreadyExists";
4819  return "ErrorDelegateCannotAddOwner";
4821  return "ErrorDelegateMissingConfiguration";
4823  return "ErrorDelegateNoUser";
4825  return "ErrorDelegateValidationFailed";
4827  return "ErrorDeleteDistinguishedFolder";
4829  return "ErrorDeleteItemsFailed";
4831  return "ErrorDeleteUnifiedMessagingPromptFailed";
4833  return "ErrorDistinguishedUserNotSupported";
4835  return "ErrorDistributionListMemberNotExist";
4837  return "ErrorDuplicateInputFolderNames";
4839  return "ErrorDuplicateUserIdsSpecified";
4841  return "ErrorEmailAddressMismatch";
4843  return "ErrorEventNotFound";
4845  return "ErrorExceededConnectionCount";
4847  return "ErrorExceededSubscriptionCount";
4849  return "ErrorExceededFindCountLimit";
4851  return "ErrorExpiredSubscription";
4853  return "ErrorExtensionNotFound";
4855  return "ErrorFolderCorrupt";
4857  return "ErrorFolderExists";
4859  return "ErrorFolderNotFound";
4861  return "ErrorFolderPropertyRequestFailed";
4863  return "ErrorFolderSave";
4865  return "ErrorFolderSaveFailed";
4867  return "ErrorFolderSavePropertyError";
4869  return "ErrorFreeBusyGenerationFailed";
4871  return "ErrorGetServerSecurityDescriptorFailed";
4873  return "ErrorImContactLimitReached";
4875  return "ErrorImGroupDisplayNameAlreadyExists";
4877  return "ErrorImGroupLimitReached";
4879  return "ErrorImpersonateUserDenied";
4881  return "ErrorImpersonationDenied";
4883  return "ErrorImpersonationFailed";
4885  return "ErrorIncorrectSchemaVersion";
4887  return "ErrorIncorrectUpdatePropertyCount";
4889  return "ErrorIndividualMailboxLimitReached";
4891  return "ErrorInsufficientResources";
4893  return "ErrorInternalServerError";
4895  return "ErrorInternalServerTransientError";
4897  return "ErrorInvalidAccessLevel";
4899  return "ErrorInvalidArgument";
4901  return "ErrorInvalidAttachmentId";
4903  return "ErrorInvalidAttachmentSubfilter";
4905  return "ErrorInvalidAttachmentSubfilterTextFilter";
4907  return "ErrorInvalidAuthorizationContext";
4909  return "ErrorInvalidChangeKey";
4911  return "ErrorInvalidClientSecurityContext";
4913  return "ErrorInvalidCompleteDate";
4915  return "ErrorInvalidContactEmailAddress";
4917  return "ErrorInvalidContactEmailIndex";
4919  return "ErrorInvalidCrossForestCredentials";
4921  return "ErrorInvalidDelegatePermission";
4923  return "ErrorInvalidDelegateUserId";
4925  return "ErrorInvalidExchangeImpersonationHeaderData";
4927  return "ErrorInvalidExcludesRestriction";
4929  return "ErrorInvalidExpressionTypeForSubFilter";
4931  return "ErrorInvalidExtendedProperty";
4933  return "ErrorInvalidExtendedPropertyValue";
4935  return "ErrorInvalidExternalSharingInitiator";
4937  return "ErrorInvalidExternalSharingSubscriber";
4939  return "ErrorInvalidFederatedOrganizationId";
4941  return "ErrorInvalidFolderId";
4943  return "ErrorInvalidFolderTypeForOperation";
4945  return "ErrorInvalidFractionalPagingParameters";
4947  return "ErrorInvalidFreeBusyViewType";
4949  return "ErrorInvalidId";
4951  return "ErrorInvalidIdEmpty";
4953  return "ErrorInvalidLikeRequest";
4955  return "ErrorInvalidIdMalformed";
4957  return "ErrorInvalidIdMalformedEwsLegacyIdFormat";
4959  return "ErrorInvalidIdMonikerTooLong";
4961  return "ErrorInvalidIdNotAnItemAttachmentId";
4963  return "ErrorInvalidIdReturnedByResolveNames";
4965  return "ErrorInvalidIdStoreObjectIdTooLong";
4967  return "ErrorInvalidIdTooManyAttachmentLevels";
4969  return "ErrorInvalidIdXml";
4971  return "ErrorInvalidImContactId";
4973  return "ErrorInvalidImDistributionGroupSmtpAddress";
4975  return "ErrorInvalidImGroupId";
4977  return "ErrorInvalidIndexedPagingParameters";
4979  return "ErrorInvalidInternetHeaderChildNodes";
4981  return "ErrorInvalidItemForOperationArchiveItem";
4983  return "ErrorInvalidItemForOperationAcceptItem";
4985  return "ErrorInvalidItemForOperationCancelItem";
4986  case response_code::
4988  return "ErrorInvalidItemForOperationCreateItemAttachment";
4990  return "ErrorInvalidItemForOperationCreateItem";
4992  return "ErrorInvalidItemForOperationDeclineItem";
4994  return "ErrorInvalidItemForOperationExpandDL";
4996  return "ErrorInvalidItemForOperationRemoveItem";
4998  return "ErrorInvalidItemForOperationSendItem";
5000  return "ErrorInvalidItemForOperationTentative";
5002  return "ErrorInvalidLogonType";
5004  return "ErrorInvalidMailbox";
5006  return "ErrorInvalidManagedFolderProperty";
5008  return "ErrorInvalidManagedFolderQuota";
5010  return "ErrorInvalidManagedFolderSize";
5012  return "ErrorInvalidMergedFreeBusyInterval";
5014  return "ErrorInvalidNameForNameResolution";
5016  return "ErrorInvalidNetworkServiceContext";
5018  return "ErrorInvalidOofParameter";
5020  return "ErrorInvalidOperation";
5021  case response_code::
5023  return "ErrorInvalidOrganizationRelationshipForFreeBusy";
5025  return "ErrorInvalidPagingMaxRows";
5027  return "ErrorInvalidParentFolder";
5029  return "ErrorInvalidPercentCompleteValue";
5031  return "ErrorInvalidPermissionSettings";
5033  return "ErrorInvalidPhoneCallId";
5035  return "ErrorInvalidPhoneNumber";
5037  return "ErrorInvalidPropertyAppend";
5039  return "ErrorInvalidPropertyDelete";
5041  return "ErrorInvalidPropertyForExists";
5043  return "ErrorInvalidPropertyForOperation";
5045  return "ErrorInvalidPropertyRequest";
5047  return "ErrorInvalidPropertySet";
5049  return "ErrorInvalidPropertyUpdateSentMessage";
5051  return "ErrorInvalidProxySecurityContext";
5053  return "ErrorInvalidPullSubscriptionId";
5055  return "ErrorInvalidPushSubscriptionUrl";
5057  return "ErrorInvalidRecipients";
5059  return "ErrorInvalidRecipientSubfilter";
5061  return "ErrorInvalidRecipientSubfilterComparison";
5063  return "ErrorInvalidRecipientSubfilterOrder";
5065  return "ErrorInvalidRecipientSubfilterTextFilter";
5067  return "ErrorInvalidReferenceItem";
5069  return "ErrorInvalidRequest";
5071  return "ErrorInvalidRestriction";
5073  return "ErrorInvalidRetentionTagTypeMismatch";
5075  return "ErrorInvalidRetentionTagInvisible";
5077  return "ErrorInvalidRetentionTagInheritance";
5079  return "ErrorInvalidRetentionTagIdGuid";
5081  return "ErrorInvalidRoutingType";
5083  return "ErrorInvalidScheduledOofDuration";
5085  return "ErrorInvalidSchemaVersionForMailboxVersion";
5087  return "ErrorInvalidSecurityDescriptor";
5089  return "ErrorInvalidSendItemSaveSettings";
5091  return "ErrorInvalidSerializedAccessToken";
5093  return "ErrorInvalidSharingData";
5095  return "ErrorInvalidSharingMessage";
5097  return "ErrorInvalidSid";
5099  return "ErrorInvalidSIPUri";
5101  return "ErrorInvalidServerVersion";
5103  return "ErrorInvalidSmtpAddress";
5105  return "ErrorInvalidSubfilterType";
5107  return "ErrorInvalidSubfilterTypeNotAttendeeType";
5109  return "ErrorInvalidSubfilterTypeNotRecipientType";
5111  return "ErrorInvalidSubscription";
5113  return "ErrorInvalidSubscriptionRequest";
5115  return "ErrorInvalidSyncStateData";
5117  return "ErrorInvalidTimeInterval";
5119  return "ErrorInvalidUserInfo";
5121  return "ErrorInvalidUserOofSettings";
5123  return "ErrorInvalidUserPrincipalName";
5125  return "ErrorInvalidUserSid";
5127  return "ErrorInvalidUserSidMissingUPN";
5129  return "ErrorInvalidValueForProperty";
5131  return "ErrorInvalidWatermark";
5133  return "ErrorIPGatewayNotFound";
5135  return "ErrorIrresolvableConflict";
5137  return "ErrorItemCorrupt";
5139  return "ErrorItemNotFound";
5141  return "ErrorItemPropertyRequestFailed";
5143  return "ErrorItemSave";
5145  return "ErrorItemSavePropertyError";
5147  return "ErrorLegacyMailboxFreeBusyViewTypeNotMerged";
5149  return "ErrorLocalServerObjectNotFound";
5151  return "ErrorLogonAsNetworkServiceFailed";
5153  return "ErrorMailboxConfiguration";
5155  return "ErrorMailboxDataArrayEmpty";
5157  return "ErrorMailboxDataArrayTooBig";
5159  return "ErrorMailboxFailover";
5161  return "ErrorMailboxHoldNotFound";
5163  return "ErrorMailboxLogonFailed";
5165  return "ErrorMailboxMoveInProgress";
5167  return "ErrorMailboxStoreUnavailable";
5169  return "ErrorMailRecipientNotFound";
5171  return "ErrorMailTipsDisabled";
5173  return "ErrorManagedFolderAlreadyExists";
5175  return "ErrorManagedFolderNotFound";
5177  return "ErrorManagedFoldersRootFailure";
5179  return "ErrorMeetingSuggestionGenerationFailed";
5181  return "ErrorMessageDispositionRequired";
5183  return "ErrorMessageSizeExceeded";
5185  return "ErrorMessageTrackingNoSuchDomain";
5187  return "ErrorMessageTrackingPermanentError";
5189  return " ErrorMessageTrackingTransientError";
5191  return "ErrorMimeContentConversionFailed";
5193  return "ErrorMimeContentInvalid";
5195  return "ErrorMimeContentInvalidBase64String";
5197  return "ErrorMissingArgument";
5199  return "ErrorMissingEmailAddress";
5201  return "ErrorMissingEmailAddressForManagedFolder";
5203  return "ErrorMissingInformationEmailAddress";
5205  return "ErrorMissingInformationReferenceItemId";
5207  return "ErrorMissingItemForCreateItemAttachment";
5209  return "ErrorMissingManagedFolderId";
5211  return "ErrorMissingRecipients";
5213  return "ErrorMissingUserIdInformation";
5215  return "ErrorMoreThanOneAccessModeSpecified";
5217  return "ErrorMoveCopyFailed";
5219  return "ErrorMoveDistinguishedFolder";
5221  return "ErrorMultiLegacyMailboxAccess";
5223  return "ErrorNameResolutionMultipleResults";
5225  return "ErrorNameResolutionNoMailbox";
5227  return "ErrorNameResolutionNoResults";
5229  return "ErrorNoApplicableProxyCASServersAvailable";
5231  return "ErrorNoCalendar";
5232  case response_code::
5234  return "ErrorNoDestinationCASDueToKerberosRequirements";
5236  return "ErrorNoDestinationCASDueToSSLRequirements";
5238  return "ErrorNoDestinationCASDueToVersionMismatch";
5240  return "ErrorNoFolderClassOverride";
5242  return "ErrorNoFreeBusyAccess";
5244  return "ErrorNonExistentMailbox";
5246  return "ErrorNonPrimarySmtpAddress";
5248  return "ErrorNoPropertyTagForCustomProperties";
5250  return "ErrorNoPublicFolderReplicaAvailable";
5252  return "ErrorNoPublicFolderServerAvailable";
5254  return "ErrorNoRespondingCASInDestinationSite";
5256  return "ErrorNotDelegate";
5258  return "ErrorNotEnoughMemory";
5260  return "ErrorNotSupportedSharingMessage";
5262  return "ErrorObjectTypeChanged";
5264  return "ErrorOccurrenceCrossingBoundary";
5266  return "ErrorOccurrenceTimeSpanTooBig";
5268  return "ErrorOperationNotAllowedWithPublicFolderRoot";
5270  return "ErrorOrganizationNotFederated";
5272  return "ErrorParentFolderIdRequired";
5274  return "ErrorParentFolderNotFound";
5276  return "ErrorPasswordChangeRequired";
5278  return "ErrorPasswordExpired";
5280  return "ErrorPhoneNumberNotDialable";
5282  return "ErrorPropertyUpdate";
5284  return "ErrorPromptPublishingOperationFailed";
5286  return "ErrorPropertyValidationFailure";
5288  return "ErrorProxiedSubscriptionCallFailure";
5290  return "ErrorProxyCallFailed";
5292  return "ErrorProxyGroupSidLimitExceeded";
5294  return "ErrorProxyRequestNotAllowed";
5296  return "ErrorProxyRequestProcessingFailed";
5298  return "ErrorProxyServiceDiscoveryFailed";
5300  return "ErrorProxyTokenExpired";
5302  return "ErrorPublicFolderMailboxDiscoveryFailed";
5304  return "ErrorPublicFolderOperationFailed";
5306  return "ErrorPublicFolderRequestProcessingFailed";
5308  return "ErrorPublicFolderServerNotFound";
5310  return "ErrorPublicFolderSyncException";
5312  return "ErrorQueryFilterTooLong";
5314  return "ErrorQuotaExceeded";
5316  return "ErrorReadEventsFailed";
5318  return "ErrorReadReceiptNotPending";
5320  return "ErrorRecurrenceEndDateTooBig";
5322  return "ErrorRecurrenceHasNoOccurrence";
5324  return "ErrorRemoveDelegatesFailed";
5326  return "ErrorRequestAborted";
5328  return "ErrorRequestStreamTooBig";
5330  return "ErrorRequiredPropertyMissing";
5332  return "ErrorResolveNamesInvalidFolderType";
5333  case response_code::
5335  return "ErrorResolveNamesOnlyOneContactsFolderAllowed";
5337  return "ErrorResponseSchemaValidation";
5339  return "ErrorRestrictionTooLong";
5341  return "ErrorRestrictionTooComplex";
5343  return "ErrorResultSetTooBig";
5345  return "ErrorSavedItemFolderNotFound";
5347  return "ErrorSchemaValidation";
5349  return "ErrorSearchFolderNotInitialized";
5351  return "ErrorSendAsDenied";
5353  return "ErrorSendMeetingCancellationsRequired";
5354  case response_code::
5356  return "ErrorSendMeetingInvitationsOrCancellationsRequired";
5358  return "ErrorSendMeetingInvitationsRequired";
5360  return "ErrorSentMeetingRequestUpdate";
5362  return "ErrorSentTaskRequestUpdate";
5364  return "ErrorServerBusy";
5366  return "ErrorServiceDiscoveryFailed";
5368  return "ErrorStaleObject";
5370  return "ErrorSubmissionQuotaExceeded";
5372  return "ErrorSubscriptionAccessDenied";
5374  return "ErrorSubscriptionDelegateAccessNotSupported";
5376  return "ErrorSubscriptionNotFound";
5378  return "ErrorSubscriptionUnsubscribed";
5380  return "ErrorSyncFolderNotFound";
5382  return "ErrorTeamMailboxNotFound";
5384  return "ErrorTeamMailboxNotLinkedToSharePoint";
5386  return "ErrorTeamMailboxUrlValidationFailed";
5388  return "ErrorTeamMailboxNotAuthorizedOwner";
5390  return "ErrorTeamMailboxActiveToPendingDelete";
5392  return "ErrorTeamMailboxFailedSendingNotifications";
5394  return "ErrorTeamMailboxErrorUnknown";
5396  return "ErrorTimeIntervalTooBig";
5398  return "ErrorTimeoutExpired";
5400  return "ErrorTimeZone";
5402  return "ErrorToFolderNotFound";
5404  return "ErrorTokenSerializationDenied";
5406  return "ErrorTooManyObjectsOpened";
5408  return "ErrorUnifiedMessagingDialPlanNotFound";
5410  return "ErrorUnifiedMessagingReportDataNotFound";
5412  return "ErrorUnifiedMessagingPromptNotFound";
5414  return "ErrorUnifiedMessagingRequestFailed";
5416  return "ErrorUnifiedMessagingServerNotFound";
5418  return "ErrorUnableToGetUserOofSettings";
5420  return "ErrorUnableToRemoveImContactFromGroup";
5422  return "ErrorUnsupportedCulture";
5424  return "ErrorUnsupportedMapiPropertyType";
5426  return "ErrorUnsupportedMimeConversion";
5428  return "ErrorUnsupportedPathForQuery";
5430  return "ErrorUnsupportedPathForSortGroup";
5432  return "ErrorUnsupportedPropertyDefinition";
5434  return "ErrorUnsupportedQueryFilter";
5436  return "ErrorUnsupportedRecurrence";
5438  return "ErrorUnsupportedSubFilter";
5440  return "ErrorUnsupportedTypeForConversion";
5442  return "ErrorUpdateDelegatesFailed";
5444  return "ErrorUpdatePropertyMismatch";
5446  return "ErrorUserNotUnifiedMessagingEnabled";
5448  return "ErrorUserNotAllowedByPolicy";
5450  return "ErrorUserWithoutFederatedProxyAddress";
5452  return "ErrorValueOutOfRange";
5454  return "ErrorVirusDetected";
5456  return "ErrorVirusMessageDeleted";
5458  return "ErrorVoiceMailNotImplemented";
5460  return "ErrorWebRequestInInvalidState";
5462  return "ErrorWin32InteropError";
5464  return "ErrorWorkingHoursSaveFailed";
5466  return "ErrorWorkingHoursXmlMalformed";
5468  return "ErrorWrongServerVersion";
5470  return "ErrorWrongServerVersionDelegate";
5472  return "ErrorMissingInformationSharingFolderId";
5474  return "ErrorDuplicateSOAPHeader";
5476  return "ErrorSharingSynchronizationFailed";
5478  return "ErrorSharingNoExternalEwsAvailable";
5480  return "ErrorFreeBusyDLLimitReached";
5482  return "ErrorInvalidGetSharingFolderRequest";
5484  return "ErrorNotAllowedExternalSharingByPolicy";
5486  return "ErrorPermissionNotAllowedByPolicy";
5488  return "ErrorMessageTrackingTransientError";
5490  return "ErrorApplyConversationActionFailed";
5492  return "ErrorInboxRulesValidationError";
5494  return "ErrorOutlookRuleBlobExists";
5496  return "ErrorRulesOverQuota";
5498  return "ErrorNewEventStreamConnectionOpened";
5500  return "ErrorMissedNotificationEvents";
5502  return "ErrorDuplicateLegacyDistinguishedName";
5504  return "ErrorInvalidClientAccessTokenRequest";
5506  return "ErrorNoSpeechDetected";
5508  return "ErrorUMServerUnavailable";
5510  return "ErrorRecipientNotFound";
5512  return "ErrorRecognizerNotInstalled";
5514  return "ErrorSpeechGrammarError";
5516  return "ErrorInvalidManagementRoleHeader";
5518  return "ErrorLocationServicesDisabled";
5520  return "ErrorLocationServicesRequestTimedOut";
5522  return "ErrorLocationServicesRequestFailed";
5524  return "ErrorLocationServicesInvalidRequest";
5526  return "ErrorWeatherServiceDisabled";
5527  case response_code::
5529  return "ErrorMailboxScopeNotAllowedWithoutQueryString";
5531  return "ErrorArchiveMailboxSearchFailed";
5533  return "ErrorGetRemoteArchiveFolderFailed";
5535  return "ErrorFindRemoteArchiveFolderFailed";
5537  return "ErrorGetRemoteArchiveItemFailed";
5539  return "ErrorExportRemoteArchiveItemsFailed";
5541  return "ErrorInvalidPhotoSize";
5543  return "ErrorSearchQueryHasTooManyKeywords";
5545  return "ErrorSearchTooManyMailboxes";
5547  return "ErrorInvalidRetentionTagNone";
5549  return "ErrorDiscoverySearchesDisabled";
5551  return "ErrorCalendarSeekToConditionNotSupported";
5553  return "ErrorCalendarIsGroupMailboxForAccept";
5555  return "ErrorCalendarIsGroupMailboxForDecline";
5557  return "ErrorCalendarIsGroupMailboxForTentative";
5558  case response_code::
5560  return "ErrorCalendarIsGroupMailboxForSuppressReadReceipt";
5562  return "ErrorOrganizationAccessBlocked";
5564  return "ErrorInvalidLicense";
5565  case response_code::
5567  return "ErrorMessagePerFolderCountReceiveQuotaExceeded";
5568  default:
5569  throw exception("Unrecognized response code");
5570  }
5571  }
5572 } // namespace internal
5573 
5578 {
5581  beginning,
5582 
5584  end
5585 };
5586 
5587 namespace internal
5588 {
5589  inline std::string enum_to_str(paging_base_point base)
5590  {
5591  switch (base)
5592  {
5594  return "Beginning";
5596  return "End";
5597  default:
5598  throw exception("Bad enum value");
5599  }
5600  }
5601 } // namespace internal
5602 
5606 enum class time_zone
5607 {
5608  none,
5609  dateline_standard_time,
5610  utc_minus_11,
5611  aleutian_standard_time,
5612  hawaiian_standard_time,
5613  marquesas_standard_time,
5614  alaskan_standard_time,
5615  utc_minus_09,
5616  pacific_standard_time_mexico,
5617  utc_minus_08,
5618  pacific_standard_time,
5619  us_mountain_standard_time,
5620  mountain_standard_time_mexico,
5621  mountain_standard_time,
5622  central_america_standard_time,
5623  central_standard_time,
5624  easter_island_standard_time,
5625  central_standard_time_mexico,
5626  canada_central_standard_time,
5627  sa_pacific_standard_time,
5628  eastern_standard_time_mexico,
5629  eastern_standard_time,
5630  haiti_standard_time,
5631  cuba_standard_time,
5632  us_eastern_standard_time,
5633  turks_and_caicos_standard_time,
5634  paraguay_standard_time,
5635  atlantic_standard_time,
5636  venezuela_standard_time,
5637  central_brazilian_standard_time,
5638  sa_western_standard_time,
5639  pacific_sa_standard_time,
5640  newfoundland_standard_time,
5641  tocantins_standard_time,
5642  e_south_america_standard_time,
5643  sa_eastern_standard_time,
5644  argentina_standard_time,
5645  greenland_standard_time,
5646  montevideo_standard_time,
5647  magallanes_standard_time,
5648  saint_pierre_standard_time,
5649  bahia_standard_time,
5650  utc_minus_02,
5651  mid_minus_atlantic_standard_time,
5652  azores_standard_time,
5653  cape_verde_standard_time,
5654  utc,
5655  morocco_standard_time,
5656  gmt_standard_time,
5657  greenwich_standard_time,
5658  w_europe_standard_time,
5659  central_europe_standard_time,
5660  romance_standard_time,
5661  central_european_standard_time,
5662  w_central_africa_standard_time,
5663  jordan_standard_time,
5664  gtb_standard_time,
5665  middle_east_standard_time,
5666  egypt_standard_time,
5667  e_europe_standard_time,
5668  syria_standard_time,
5669  west_bank_standard_time,
5670  south_africa_standard_time,
5671  fle_standard_time,
5672  israel_standard_time,
5673  kaliningrad_standard_time,
5674  sudan_standard_time,
5675  libya_standard_time,
5676  namibia_standard_time,
5677  arabic_standard_time,
5678  turkey_standard_time,
5679  arab_standard_time,
5680  belarus_standard_time,
5681  russian_standard_time,
5682  e_africa_standard_time,
5683  iran_standard_time,
5684  arabian_standard_time,
5685  astrakhan_standard_time,
5686  azerbaijan_standard_time,
5687  russia_time_zone_3,
5688  mauritius_standard_time,
5689  saratov_standard_time,
5690  georgian_standard_time,
5691  caucasus_standard_time,
5692  afghanistan_standard_time,
5693  west_asia_standard_time,
5694  ekaterinburg_standard_time,
5695  pakistan_standard_time,
5696  india_standard_time,
5697  sri_lanka_standard_time,
5698  nepal_standard_time,
5699  central_asia_standard_time,
5700  bangladesh_standard_time,
5701  omsk_standard_time,
5702  myanmar_standard_time,
5703  se_asia_standard_time,
5704  altai_standard_time,
5705  w_mongolia_standard_time,
5706  north_asia_standard_time,
5707  n_central_asia_standard_time,
5708  tomsk_standard_time,
5709  china_standard_time,
5710  north_asia_east_standard_time,
5711  singapore_standard_time,
5712  w_australia_standard_time,
5713  taipei_standard_time,
5714  ulaanbaatar_standard_time,
5715  north_korea_standard_time,
5716  aus_central_w_standard_time,
5717  transbaikal_standard_time,
5718  tokyo_standard_time,
5719  korea_standard_time,
5720  yakutsk_standard_time,
5721  cen_australia_standard_time,
5722  aus_central_standard_time,
5723  e_australia_standard_time,
5724  aus_eastern_standard_time,
5725  west_pacific_standard_time,
5726  tasmania_standard_time,
5727  vladivostok_standard_time,
5728  lord_howe_standard_time,
5729  bougainville_standard_time,
5730  russia_time_zone_10,
5731  magadan_standard_time,
5732  norfolk_standard_time,
5733  sakhalin_standard_time,
5734  central_pacific_standard_time,
5735  russia_time_zone_11,
5736  new_zealand_standard_time,
5737  utc_plus_12,
5738  fiji_standard_time,
5739  kamchatka_standard_time,
5740  chatham_islands_standard_time,
5741  utc_plus_13,
5742  tonga_standard_time,
5743  samoa_standard_time,
5744  line_islands_standard_time,
5745 };
5746 
5747 namespace internal
5748 {
5749  inline std::string enum_to_str(time_zone tz)
5750  {
5751  switch (tz)
5752  {
5753  case time_zone::dateline_standard_time:
5754  return "Dateline Standard Time";
5755  case time_zone::utc_minus_11:
5756  return "UTC-11";
5757  case time_zone::aleutian_standard_time:
5758  return "Aleutian Standard Time";
5759  case time_zone::hawaiian_standard_time:
5760  return "Hawaiian Standard Time";
5761  case time_zone::marquesas_standard_time:
5762  return "Marquesas Standard Time";
5763  case time_zone::alaskan_standard_time:
5764  return "Alaskan Standard Time";
5765  case time_zone::utc_minus_09:
5766  return "UTC-09";
5767  case time_zone::pacific_standard_time_mexico:
5768  return "Pacific Standard Time (Mexico)";
5769  case time_zone::utc_minus_08:
5770  return "UTC-08";
5771  case time_zone::pacific_standard_time:
5772  return "Pacific Standard Time";
5773  case time_zone::us_mountain_standard_time:
5774  return "US Mountain Standard Time";
5775  case time_zone::mountain_standard_time_mexico:
5776  return "Mountain Standard Time (Mexico)";
5777  case time_zone::mountain_standard_time:
5778  return "Mountain Standard Time";
5779  case time_zone::central_america_standard_time:
5780  return "Central America Standard Time";
5781  case time_zone::central_standard_time:
5782  return "Central Standard Time";
5783  case time_zone::easter_island_standard_time:
5784  return "Easter Island Standard Time";
5785  case time_zone::central_standard_time_mexico:
5786  return "Central Standard Time (Mexico)";
5787  case time_zone::canada_central_standard_time:
5788  return "Canada Central Standard Time";
5789  case time_zone::sa_pacific_standard_time:
5790  return "SA Pacific Standard Time";
5791  case time_zone::eastern_standard_time_mexico:
5792  return "Eastern Standard Time (Mexico)";
5793  case time_zone::eastern_standard_time:
5794  return "Eastern Standard Time";
5795  case time_zone::haiti_standard_time:
5796  return "Haiti Standard Time";
5797  case time_zone::cuba_standard_time:
5798  return "Cuba Standard Time";
5799  case time_zone::us_eastern_standard_time:
5800  return "US Eastern Standard Time";
5801  case time_zone::turks_and_caicos_standard_time:
5802  return "Turks And Caicos Standard Time";
5803  case time_zone::paraguay_standard_time:
5804  return "Paraguay Standard Time";
5805  case time_zone::atlantic_standard_time:
5806  return "Atlantic Standard Time";
5807  case time_zone::venezuela_standard_time:
5808  return "Venezuela Standard Time";
5809  case time_zone::central_brazilian_standard_time:
5810  return "Central Brazilian Standard Time";
5811  case time_zone::sa_western_standard_time:
5812  return "SA Western Standard Time";
5813  case time_zone::pacific_sa_standard_time:
5814  return "Pacific SA Standard Time";
5815  case time_zone::newfoundland_standard_time:
5816  return "Newfoundland Standard Time";
5817  case time_zone::tocantins_standard_time:
5818  return "Tocantins Standard Time";
5819  case time_zone::e_south_america_standard_time:
5820  return "E. South America Standard Time";
5821  case time_zone::sa_eastern_standard_time:
5822  return "SA Eastern Standard Time";
5823  case time_zone::argentina_standard_time:
5824  return "Argentina Standard Time";
5825  case time_zone::greenland_standard_time:
5826  return "Greenland Standard Time";
5827  case time_zone::montevideo_standard_time:
5828  return "Montevideo Standard Time";
5829  case time_zone::magallanes_standard_time:
5830  return "Magallanes Standard Time";
5831  case time_zone::saint_pierre_standard_time:
5832  return "Saint Pierre Standard Time";
5833  case time_zone::bahia_standard_time:
5834  return "Bahia Standard Time";
5835  case time_zone::utc_minus_02:
5836  return "UTC-02";
5837  case time_zone::mid_minus_atlantic_standard_time:
5838  return "Mid-Atlantic Standard Time";
5839  case time_zone::azores_standard_time:
5840  return "Azores Standard Time";
5841  case time_zone::cape_verde_standard_time:
5842  return "Cape Verde Standard Time";
5843  case time_zone::utc:
5844  return "UTC";
5845  case time_zone::morocco_standard_time:
5846  return "Morocco Standard Time";
5847  case time_zone::gmt_standard_time:
5848  return "GMT Standard Time";
5849  case time_zone::greenwich_standard_time:
5850  return "Greenwich Standard Time";
5851  case time_zone::w_europe_standard_time:
5852  return "W. Europe Standard Time";
5853  case time_zone::central_europe_standard_time:
5854  return "Central Europe Standard Time";
5855  case time_zone::romance_standard_time:
5856  return "Romance Standard Time";
5857  case time_zone::central_european_standard_time:
5858  return "Central European Standard Time";
5859  case time_zone::w_central_africa_standard_time:
5860  return "W. Central Africa Standard Time";
5861  case time_zone::jordan_standard_time:
5862  return "Jordan Standard Time";
5863  case time_zone::gtb_standard_time:
5864  return "GTB Standard Time";
5865  case time_zone::middle_east_standard_time:
5866  return "Middle East Standard Time";
5867  case time_zone::egypt_standard_time:
5868  return "Egypt Standard Time";
5869  case time_zone::e_europe_standard_time:
5870  return "E. Europe Standard Time";
5871  case time_zone::syria_standard_time:
5872  return "Syria Standard Time";
5873  case time_zone::west_bank_standard_time:
5874  return "West Bank Standard Time";
5875  case time_zone::south_africa_standard_time:
5876  return "South Africa Standard Time";
5877  case time_zone::fle_standard_time:
5878  return "FLE Standard Time";
5879  case time_zone::israel_standard_time:
5880  return "Israel Standard Time";
5881  case time_zone::kaliningrad_standard_time:
5882  return "Kaliningrad Standard Time";
5883  case time_zone::sudan_standard_time:
5884  return "Sudan Standard Time";
5885  case time_zone::libya_standard_time:
5886  return "Libya Standard Time";
5887  case time_zone::namibia_standard_time:
5888  return "Namibia Standard Time";
5889  case time_zone::arabic_standard_time:
5890  return "Arabic Standard Time";
5891  case time_zone::turkey_standard_time:
5892  return "Turkey Standard Time";
5893  case time_zone::arab_standard_time:
5894  return "Arab Standard Time";
5895  case time_zone::belarus_standard_time:
5896  return "Belarus Standard Time";
5897  case time_zone::russian_standard_time:
5898  return "Russian Standard Time";
5899  case time_zone::e_africa_standard_time:
5900  return "E. Africa Standard Time";
5901  case time_zone::iran_standard_time:
5902  return "Iran Standard Time";
5903  case time_zone::arabian_standard_time:
5904  return "Arabian Standard Time";
5905  case time_zone::astrakhan_standard_time:
5906  return "Astrakhan Standard Time";
5907  case time_zone::azerbaijan_standard_time:
5908  return "Azerbaijan Standard Time";
5909  case time_zone::russia_time_zone_3:
5910  return "Russia Time Zone 3";
5911  case time_zone::mauritius_standard_time:
5912  return "Mauritius Standard Time";
5913  case time_zone::saratov_standard_time:
5914  return "Saratov Standard Time";
5915  case time_zone::georgian_standard_time:
5916  return "Georgian Standard Time";
5917  case time_zone::caucasus_standard_time:
5918  return "Caucasus Standard Time";
5919  case time_zone::afghanistan_standard_time:
5920  return "Afghanistan Standard Time";
5921  case time_zone::west_asia_standard_time:
5922  return "West Asia Standard Time";
5923  case time_zone::ekaterinburg_standard_time:
5924  return "Ekaterinburg Standard Time";
5925  case time_zone::pakistan_standard_time:
5926  return "Pakistan Standard Time";
5927  case time_zone::india_standard_time:
5928  return "India Standard Time";
5929  case time_zone::sri_lanka_standard_time:
5930  return "Sri Lanka Standard Time";
5931  case time_zone::nepal_standard_time:
5932  return "Nepal Standard Time";
5933  case time_zone::central_asia_standard_time:
5934  return "Central Asia Standard Time";
5935  case time_zone::bangladesh_standard_time:
5936  return "Bangladesh Standard Time";
5937  case time_zone::omsk_standard_time:
5938  return "Omsk Standard Time";
5939  case time_zone::myanmar_standard_time:
5940  return "Myanmar Standard Time";
5941  case time_zone::se_asia_standard_time:
5942  return "SE Asia Standard Time";
5943  case time_zone::altai_standard_time:
5944  return "Altai Standard Time";
5945  case time_zone::w_mongolia_standard_time:
5946  return "W. Mongolia Standard Time";
5947  case time_zone::north_asia_standard_time:
5948  return "North Asia Standard Time";
5949  case time_zone::n_central_asia_standard_time:
5950  return "N. Central Asia Standard Time";
5951  case time_zone::tomsk_standard_time:
5952  return "Tomsk Standard Time";
5953  case time_zone::china_standard_time:
5954  return "China Standard Time";
5955  case time_zone::north_asia_east_standard_time:
5956  return "North Asia East Standard Time";
5957  case time_zone::singapore_standard_time:
5958  return "Singapore Standard Time";
5959  case time_zone::w_australia_standard_time:
5960  return "W. Australia Standard Time";
5961  case time_zone::taipei_standard_time:
5962  return "Taipei Standard Time";
5963  case time_zone::ulaanbaatar_standard_time:
5964  return "Ulaanbaatar Standard Time";
5965  case time_zone::north_korea_standard_time:
5966  return "North Korea Standard Time";
5967  case time_zone::aus_central_w_standard_time:
5968  return "Aus Central W. Standard Time";
5969  case time_zone::transbaikal_standard_time:
5970  return "Transbaikal Standard Time";
5971  case time_zone::tokyo_standard_time:
5972  return "Tokyo Standard Time";
5973  case time_zone::korea_standard_time:
5974  return "Korea Standard Time";
5975  case time_zone::yakutsk_standard_time:
5976  return "Yakutsk Standard Time";
5977  case time_zone::cen_australia_standard_time:
5978  return "Cen. Australia Standard Time";
5979  case time_zone::aus_central_standard_time:
5980  return "AUS Central Standard Time";
5981  case time_zone::e_australia_standard_time:
5982  return "E. Australia Standard Time";
5983  case time_zone::aus_eastern_standard_time:
5984  return "AUS Eastern Standard Time";
5985  case time_zone::west_pacific_standard_time:
5986  return "West Pacific Standard Time";
5987  case time_zone::tasmania_standard_time:
5988  return "Tasmania Standard Time";
5989  case time_zone::vladivostok_standard_time:
5990  return "Vladivostok Standard Time";
5991  case time_zone::lord_howe_standard_time:
5992  return "Lord Howe Standard Time";
5993  case time_zone::bougainville_standard_time:
5994  return "Bougainville Standard Time";
5995  case time_zone::russia_time_zone_10:
5996  return "Russia Time Zone 10";
5997  case time_zone::magadan_standard_time:
5998  return "Magadan Standard Time";
5999  case time_zone::norfolk_standard_time:
6000  return "Norfolk Standard Time";
6001  case time_zone::sakhalin_standard_time:
6002  return "Sakhalin Standard Time";
6003  case time_zone::central_pacific_standard_time:
6004  return "Central Pacific Standard Time";
6005  case time_zone::russia_time_zone_11:
6006  return "Russia Time Zone 11";
6007  case time_zone::new_zealand_standard_time:
6008  return "New Zealand Standard Time";
6009  case time_zone::utc_plus_12:
6010  return "UTC+12";
6011  case time_zone::fiji_standard_time:
6012  return "Fiji Standard Time";
6013  case time_zone::kamchatka_standard_time:
6014  return "Kamchatka Standard Time";
6015  case time_zone::chatham_islands_standard_time:
6016  return "Chatham Islands Standard Time";
6017  case time_zone::utc_plus_13:
6018  return "UTC+13";
6019  case time_zone::tonga_standard_time:
6020  return "Tonga Standard Time";
6021  case time_zone::samoa_standard_time:
6022  return "Samoa Standard Time";
6023  case time_zone::line_islands_standard_time:
6024  return "Line Islands Standard Time";
6025  default:
6026  throw exception("Bad enum value");
6027  }
6028  }
6029 
6030  inline time_zone str_to_time_zone(const std::string& str)
6031  {
6032  if (str == "Dateline Standard Time")
6033  {
6034  return time_zone::dateline_standard_time;
6035  }
6036  if (str == "UTC-11")
6037  {
6038  return time_zone::utc_minus_11;
6039  }
6040  if (str == "Aleutian Standard Time")
6041  {
6042  return time_zone::aleutian_standard_time;
6043  }
6044  if (str == "Hawaiian Standard Time")
6045  {
6046  return time_zone::hawaiian_standard_time;
6047  }
6048  if (str == "Marquesas Standard Time")
6049  {
6050  return time_zone::marquesas_standard_time;
6051  }
6052  if (str == "Alaskan Standard Time")
6053  {
6054  return time_zone::alaskan_standard_time;
6055  }
6056  if (str == "UTC-09")
6057  {
6058  return time_zone::utc_minus_09;
6059  }
6060  if (str == "Pacific Standard Time (Mexico)")
6061  {
6062  return time_zone::pacific_standard_time_mexico;
6063  }
6064  if (str == "UTC-08")
6065  {
6066  return time_zone::utc_minus_08;
6067  }
6068  if (str == "Pacific Standard Time")
6069  {
6070  return time_zone::pacific_standard_time;
6071  }
6072  if (str == "US Mountain Standard Time")
6073  {
6074  return time_zone::us_mountain_standard_time;
6075  }
6076  if (str == "Mountain Standard Time (Mexico)")
6077  {
6078  return time_zone::mountain_standard_time_mexico;
6079  }
6080  if (str == "Mountain Standard Time")
6081  {
6082  return time_zone::mountain_standard_time;
6083  }
6084  if (str == "Central America Standard Time")
6085  {
6086  return time_zone::central_america_standard_time;
6087  }
6088  if (str == "Central Standard Time")
6089  {
6090  return time_zone::central_standard_time;
6091  }
6092  if (str == "Easter Island Standard Time")
6093  {
6094  return time_zone::easter_island_standard_time;
6095  }
6096  if (str == "Central Standard Time (Mexico)")
6097  {
6098  return time_zone::central_standard_time_mexico;
6099  }
6100  if (str == "Canada Central Standard Time")
6101  {
6102  return time_zone::canada_central_standard_time;
6103  }
6104  if (str == "SA Pacific Standard Time")
6105  {
6106  return time_zone::sa_pacific_standard_time;
6107  }
6108  if (str == "Eastern Standard Time (Mexico)")
6109  {
6110  return time_zone::eastern_standard_time_mexico;
6111  }
6112  if (str == "Eastern Standard Time")
6113  {
6114  return time_zone::eastern_standard_time;
6115  }
6116  if (str == "Haiti Standard Time")
6117  {
6118  return time_zone::haiti_standard_time;
6119  }
6120  if (str == "Cuba Standard Time")
6121  {
6122  return time_zone::cuba_standard_time;
6123  }
6124  if (str == "US Eastern Standard Time")
6125  {
6126  return time_zone::us_eastern_standard_time;
6127  }
6128  if (str == "Turks And Caicos Standard Time")
6129  {
6130  return time_zone::turks_and_caicos_standard_time;
6131  }
6132  if (str == "Paraguay Standard Time")
6133  {
6134  return time_zone::paraguay_standard_time;
6135  }
6136  if (str == "Atlantic Standard Time")
6137  {
6138  return time_zone::atlantic_standard_time;
6139  }
6140  if (str == "Venezuela Standard Time")
6141  {
6142  return time_zone::venezuela_standard_time;
6143  }
6144  if (str == "Central Brazilian Standard Time")
6145  {
6146  return time_zone::central_brazilian_standard_time;
6147  }
6148  if (str == "SA Western Standard Time")
6149  {
6150  return time_zone::sa_western_standard_time;
6151  }
6152  if (str == "Pacific SA Standard Time")
6153  {
6154  return time_zone::pacific_sa_standard_time;
6155  }
6156  if (str == "Newfoundland Standard Time")
6157  {
6158  return time_zone::newfoundland_standard_time;
6159  }
6160  if (str == "Tocantins Standard Time")
6161  {
6162  return time_zone::tocantins_standard_time;
6163  }
6164  if (str == "E. South America Standard Time")
6165  {
6166  return time_zone::e_south_america_standard_time;
6167  }
6168  if (str == "SA Eastern Standard Time")
6169  {
6170  return time_zone::sa_eastern_standard_time;
6171  }
6172  if (str == "Argentina Standard Time")
6173  {
6174  return time_zone::argentina_standard_time;
6175  }
6176  if (str == "Greenland Standard Time")
6177  {
6178  return time_zone::greenland_standard_time;
6179  }
6180  if (str == "Montevideo Standard Time")
6181  {
6182  return time_zone::montevideo_standard_time;
6183  }
6184  if (str == "Magallanes Standard Time")
6185  {
6186  return time_zone::magallanes_standard_time;
6187  }
6188  if (str == "Saint Pierre Standard Time")
6189  {
6190  return time_zone::saint_pierre_standard_time;
6191  }
6192  if (str == "Bahia Standard Time")
6193  {
6194  return time_zone::bahia_standard_time;
6195  }
6196  if (str == "UTC-02")
6197  {
6198  return time_zone::utc_minus_02;
6199  }
6200  if (str == "Mid-Atlantic Standard Time")
6201  {
6202  return time_zone::mid_minus_atlantic_standard_time;
6203  }
6204  if (str == "Azores Standard Time")
6205  {
6206  return time_zone::azores_standard_time;
6207  }
6208  if (str == "Cape Verde Standard Time")
6209  {
6210  return time_zone::cape_verde_standard_time;
6211  }
6212  if (str == "UTC")
6213  {
6214  return time_zone::utc;
6215  }
6216  if (str == "Morocco Standard Time")
6217  {
6218  return time_zone::morocco_standard_time;
6219  }
6220  if (str == "GMT Standard Time")
6221  {
6222  return time_zone::gmt_standard_time;
6223  }
6224  if (str == "Greenwich Standard Time")
6225  {
6226  return time_zone::greenwich_standard_time;
6227  }
6228  if (str == "W. Europe Standard Time")
6229  {
6230  return time_zone::w_europe_standard_time;
6231  }
6232  if (str == "Central Europe Standard Time")
6233  {
6234  return time_zone::central_europe_standard_time;
6235  }
6236  if (str == "Romance Standard Time")
6237  {
6238  return time_zone::romance_standard_time;
6239  }
6240  if (str == "Central European Standard Time")
6241  {
6242  return time_zone::central_european_standard_time;
6243  }
6244  if (str == "W. Central Africa Standard Time")
6245  {
6246  return time_zone::w_central_africa_standard_time;
6247  }
6248  if (str == "Jordan Standard Time")
6249  {
6250  return time_zone::jordan_standard_time;
6251  }
6252  if (str == "GTB Standard Time")
6253  {
6254  return time_zone::gtb_standard_time;
6255  }
6256  if (str == "Middle East Standard Time")
6257  {
6258  return time_zone::middle_east_standard_time;
6259  }
6260  if (str == "Egypt Standard Time")
6261  {
6262  return time_zone::egypt_standard_time;
6263  }
6264  if (str == "E. Europe Standard Time")
6265  {
6266  return time_zone::e_europe_standard_time;
6267  }
6268  if (str == "Syria Standard Time")
6269  {
6270  return time_zone::syria_standard_time;
6271  }
6272  if (str == "West Bank Standard Time")
6273  {
6274  return time_zone::west_bank_standard_time;
6275  }
6276  if (str == "South Africa Standard Time")
6277  {
6278  return time_zone::south_africa_standard_time;
6279  }
6280  if (str == "FLE Standard Time")
6281  {
6282  return time_zone::fle_standard_time;
6283  }
6284  if (str == "Israel Standard Time")
6285  {
6286  return time_zone::israel_standard_time;
6287  }
6288  if (str == "Kaliningrad Standard Time")
6289  {
6290  return time_zone::kaliningrad_standard_time;
6291  }
6292  if (str == "Sudan Standard Time")
6293  {
6294  return time_zone::sudan_standard_time;
6295  }
6296  if (str == "Libya Standard Time")
6297  {
6298  return time_zone::libya_standard_time;
6299  }
6300  if (str == "Namibia Standard Time")
6301  {
6302  return time_zone::namibia_standard_time;
6303  }
6304  if (str == "Arabic Standard Time")
6305  {
6306  return time_zone::arabic_standard_time;
6307  }
6308  if (str == "Turkey Standard Time")
6309  {
6310  return time_zone::turkey_standard_time;
6311  }
6312  if (str == "Arab Standard Time")
6313  {
6314  return time_zone::arab_standard_time;
6315  }
6316  if (str == "Belarus Standard Time")
6317  {
6318  return time_zone::belarus_standard_time;
6319  }
6320  if (str == "Russian Standard Time")
6321  {
6322  return time_zone::russian_standard_time;
6323  }
6324  if (str == "E. Africa Standard Time")
6325  {
6326  return time_zone::e_africa_standard_time;
6327  }
6328  if (str == "Iran Standard Time")
6329  {
6330  return time_zone::iran_standard_time;
6331  }
6332  if (str == "Arabian Standard Time")
6333  {
6334  return time_zone::arabian_standard_time;
6335  }
6336  if (str == "Astrakhan Standard Time")
6337  {
6338  return time_zone::astrakhan_standard_time;
6339  }
6340  if (str == "Azerbaijan Standard Time")
6341  {
6342  return time_zone::azerbaijan_standard_time;
6343  }
6344  if (str == "Russia Time Zone 3")
6345  {
6346  return time_zone::russia_time_zone_3;
6347  }
6348  if (str == "Mauritius Standard Time")
6349  {
6350  return time_zone::mauritius_standard_time;
6351  }
6352  if (str == "Saratov Standard Time")
6353  {
6354  return time_zone::saratov_standard_time;
6355  }
6356  if (str == "Georgian Standard Time")
6357  {
6358  return time_zone::georgian_standard_time;
6359  }
6360  if (str == "Caucasus Standard Time")
6361  {
6362  return time_zone::caucasus_standard_time;
6363  }
6364  if (str == "Afghanistan Standard Time")
6365  {
6366  return time_zone::afghanistan_standard_time;
6367  }
6368  if (str == "West Asia Standard Time")
6369  {
6370  return time_zone::west_asia_standard_time;
6371  }
6372  if (str == "Ekaterinburg Standard Time")
6373  {
6374  return time_zone::ekaterinburg_standard_time;
6375  }
6376  if (str == "Pakistan Standard Time")
6377  {
6378  return time_zone::pakistan_standard_time;
6379  }
6380  if (str == "India Standard Time")
6381  {
6382  return time_zone::india_standard_time;
6383  }
6384  if (str == "Sri Lanka Standard Time")
6385  {
6386  return time_zone::sri_lanka_standard_time;
6387  }
6388  if (str == "Nepal Standard Time")
6389  {
6390  return time_zone::nepal_standard_time;
6391  }
6392  if (str == "Central Asia Standard Time")
6393  {
6394  return time_zone::central_asia_standard_time;
6395  }
6396  if (str == "Bangladesh Standard Time")
6397  {
6398  return time_zone::bangladesh_standard_time;
6399  }
6400  if (str == "Omsk Standard Time")
6401  {
6402  return time_zone::omsk_standard_time;
6403  }
6404  if (str == "Myanmar Standard Time")
6405  {
6406  return time_zone::myanmar_standard_time;
6407  }
6408  if (str == "SE Asia Standard Time")
6409  {
6410  return time_zone::se_asia_standard_time;
6411  }
6412  if (str == "Altai Standard Time")
6413  {
6414  return time_zone::altai_standard_time;
6415  }
6416  if (str == "W. Mongolia Standard Time")
6417  {
6418  return time_zone::w_mongolia_standard_time;
6419  }
6420  if (str == "North Asia Standard Time")
6421  {
6422  return time_zone::north_asia_standard_time;
6423  }
6424  if (str == "N. Central Asia Standard Time")
6425  {
6426  return time_zone::n_central_asia_standard_time;
6427  }
6428  if (str == "Tomsk Standard Time")
6429  {
6430  return time_zone::tomsk_standard_time;
6431  }
6432  if (str == "China Standard Time")
6433  {
6434  return time_zone::china_standard_time;
6435  }
6436  if (str == "North Asia East Standard Time")
6437  {
6438  return time_zone::north_asia_east_standard_time;
6439  }
6440  if (str == "Singapore Standard Time")
6441  {
6442  return time_zone::singapore_standard_time;
6443  }
6444  if (str == "W. Australia Standard Time")
6445  {
6446  return time_zone::w_australia_standard_time;
6447  }
6448  if (str == "Taipei Standard Time")
6449  {
6450  return time_zone::taipei_standard_time;
6451  }
6452  if (str == "Ulaanbaatar Standard Time")
6453  {
6454  return time_zone::ulaanbaatar_standard_time;
6455  }
6456  if (str == "North Korea Standard Time")
6457  {
6458  return time_zone::north_korea_standard_time;
6459  }
6460  if (str == "Aus Central W. Standard Time")
6461  {
6462  return time_zone::aus_central_w_standard_time;
6463  }
6464  if (str == "Transbaikal Standard Time")
6465  {
6466  return time_zone::transbaikal_standard_time;
6467  }
6468  if (str == "Tokyo Standard Time")
6469  {
6470  return time_zone::tokyo_standard_time;
6471  }
6472  if (str == "Korea Standard Time")
6473  {
6474  return time_zone::korea_standard_time;
6475  }
6476  if (str == "Yakutsk Standard Time")
6477  {
6478  return time_zone::yakutsk_standard_time;
6479  }
6480  if (str == "Cen. Australia Standard Time")
6481  {
6482  return time_zone::cen_australia_standard_time;
6483  }
6484  if (str == "AUS Central Standard Time")
6485  {
6486  return time_zone::aus_central_standard_time;
6487  }
6488  if (str == "E. Australia Standard Time")
6489  {
6490  return time_zone::e_australia_standard_time;
6491  }
6492  if (str == "AUS Eastern Standard Time")
6493  {
6494  return time_zone::aus_eastern_standard_time;
6495  }
6496  if (str == "West Pacific Standard Time")
6497  {
6498  return time_zone::west_pacific_standard_time;
6499  }
6500  if (str == "Tasmania Standard Time")
6501  {
6502  return time_zone::tasmania_standard_time;
6503  }
6504  if (str == "Vladivostok Standard Time")
6505  {
6506  return time_zone::vladivostok_standard_time;
6507  }
6508  if (str == "Lord Howe Standard Time")
6509  {
6510  return time_zone::lord_howe_standard_time;
6511  }
6512  if (str == "Bougainville Standard Time")
6513  {
6514  return time_zone::bougainville_standard_time;
6515  }
6516  if (str == "Russia Time Zone 10")
6517  {
6518  return time_zone::russia_time_zone_10;
6519  }
6520  if (str == "Magadan Standard Time")
6521  {
6522  return time_zone::magadan_standard_time;
6523  }
6524  if (str == "Norfolk Standard Time")
6525  {
6526  return time_zone::norfolk_standard_time;
6527  }
6528  if (str == "Sakhalin Standard Time")
6529  {
6530  return time_zone::sakhalin_standard_time;
6531  }
6532  if (str == "Central Pacific Standard Time")
6533  {
6534  return time_zone::central_pacific_standard_time;
6535  }
6536  if (str == "Russia Time Zone 11")
6537  {
6538  return time_zone::russia_time_zone_11;
6539  }
6540  if (str == "New Zealand Standard Time")
6541  {
6542  return time_zone::new_zealand_standard_time;
6543  }
6544  if (str == "UTC+12")
6545  {
6546  return time_zone::utc_plus_12;
6547  }
6548  if (str == "Fiji Standard Time")
6549  {
6550  return time_zone::fiji_standard_time;
6551  }
6552  if (str == "Kamchatka Standard Time")
6553  {
6554  return time_zone::kamchatka_standard_time;
6555  }
6556  if (str == "Chatham Islands Standard Time")
6557  {
6558  return time_zone::chatham_islands_standard_time;
6559  }
6560  if (str == "UTC+13")
6561  {
6562  return time_zone::utc_plus_13;
6563  }
6564  if (str == "Tonga Standard Time")
6565  {
6566  return time_zone::tonga_standard_time;
6567  }
6568  if (str == "Samoa Standard Time")
6569  {
6570  return time_zone::samoa_standard_time;
6571  }
6572  if (str == "Line Islands Standard Time")
6573  {
6574  return time_zone::line_islands_standard_time;
6575  }
6576 
6577  throw exception("Unrecognized <TimeZone>");
6578  }
6579 } // namespace internal
6580 
6583 enum class server_version
6584 {
6587  exchange_2007,
6588 
6593 
6595  exchange_2010,
6596 
6599 
6603 
6605  exchange_2013,
6606 
6609 };
6610 
6611 namespace internal
6612 {
6613  inline std::string enum_to_str(server_version vers)
6614  {
6615  switch (vers)
6616  {
6618  return "Exchange2007";
6620  return "Exchange2007_SP1";
6622  return "Exchange2010";
6624  return "Exchange2010_SP1";
6626  return "Exchange2010_SP2";
6628  return "Exchange2013";
6630  return "Exchange2013_SP1";
6631  default:
6632  throw exception("Bad enum value");
6633  }
6634  }
6635 
6636  inline server_version str_to_server_version(const std::string& str)
6637  {
6638  if (str == "Exchange2007")
6639  {
6641  }
6642  else if (str == "Exchange2007_SP1")
6643  {
6645  }
6646  else if (str == "Exchange2010")
6647  {
6649  }
6650  else if (str == "Exchange2010_SP1")
6651  {
6653  }
6654  else if (str == "Exchange2010_SP2")
6655  {
6657  }
6658  else if (str == "Exchange2013")
6659  {
6661  }
6662  else if (str == "Exchange2013_SP1")
6663  {
6665  }
6666  else
6667  {
6668  throw exception("Unrecognized <RequestServerVersion>");
6669  }
6670  }
6671 } // namespace internal
6672 
6675 enum class base_shape
6676 {
6678  id_only,
6679 
6681  default_shape,
6682 
6688 };
6689 
6690 namespace internal
6691 {
6692  inline std::string enum_to_str(base_shape shape)
6693  {
6694  switch (shape)
6695  {
6696  case base_shape::id_only:
6697  return "IdOnly";
6699  return "Default";
6701  return "AllProperties";
6702  default:
6703  throw exception("Bad enum value");
6704  }
6705  }
6706 } // namespace internal
6707 
6712 enum class delete_type
6713 {
6715  hard_delete,
6716 
6719 };
6720 
6721 namespace internal
6722 {
6723  inline std::string enum_to_str(delete_type d)
6724  {
6725  switch (d)
6726  {
6728  return "HardDelete";
6730  return "MoveToDeletedItems";
6731  default:
6732  throw exception("Bad enum value");
6733  }
6734  }
6735 } // namespace internal
6736 
6739 {
6742 
6745 };
6746 
6747 namespace internal
6748 {
6749  inline std::string enum_to_str(affected_task_occurrences val)
6750  {
6751  switch (val)
6752  {
6754  return "AllOccurrences";
6756  return "SpecifiedOccurrenceOnly";
6757  default:
6758  throw exception("Bad enum value");
6759  }
6760  }
6761 } // namespace internal
6762 
6765 {
6767  send_to_none,
6768 
6772 
6776 
6780 
6785 };
6786 
6787 namespace internal
6788 {
6789  inline std::string
6791  {
6792  switch (val)
6793  {
6795  return "SendToNone";
6797  return "SendOnlyToAll";
6799  return "SendOnlyToChanged";
6802  return "SendToAllAndSaveCopy";
6805  return "SendToChangedAndSaveCopy";
6806  default:
6807  throw exception("Bad enum value");
6808  }
6809  }
6810 } // namespace internal
6811 
6814 {
6816  send_to_none,
6817 
6821 
6826 };
6827 
6829 
6830 namespace internal
6831 {
6832  inline std::string enum_to_str(send_meeting_cancellations val)
6833  {
6834  switch (val)
6835  {
6837  return "SendToNone";
6839  return "SendOnlyToAll";
6841  return "SendToAllAndSaveCopy";
6842  default:
6843  throw exception("Bad enum value");
6844  }
6845  }
6846 } // namespace internal
6847 
6853 {
6858 
6861  auto_resolve,
6862 
6867 };
6868 
6869 namespace internal
6870 {
6871  inline std::string enum_to_str(conflict_resolution val)
6872  {
6873  switch (val)
6874  {
6876  return "NeverOverwrite";
6878  return "AutoResolve";
6880  return "AlwaysOverwrite";
6881  default:
6882  throw exception("Bad enum value");
6883  }
6884  }
6885 } // namespace internal
6886 
6891 {
6894  save_only,
6895 
6897  send_only,
6898 
6902 };
6903 
6904 namespace internal
6905 {
6906  inline std::string enum_to_str(message_disposition val)
6907  {
6908  switch (val)
6909  {
6911  return "SaveOnly";
6913  return "SendOnly";
6915  return "SendAndSaveCopy";
6916  default:
6917  throw exception("Bad enum value");
6918  }
6919  }
6920 } // namespace internal
6921 
6924 {
6926  free,
6927 
6929  tentative,
6930 
6933  busy,
6934 
6937  out_of_office,
6938 
6941  no_data,
6942 
6948 };
6949 
6950 namespace internal
6951 {
6952  inline std::string enum_to_str(free_busy_status val)
6953  {
6954  switch (val)
6955  {
6957  return "Free";
6959  return "Tentative";
6961  return "Busy";
6963  return "OOF";
6965  return "NoData";
6967  return "WorkingElsewhere";
6968  default:
6969  throw exception("Bad enum value");
6970  }
6971  }
6972 } // namespace internal
6973 
6976 {
6979  single,
6980 
6982  occurrence,
6983 
6985  exception,
6986 
6989 };
6990 
6994 enum class response_type
6995 {
6997  unknown,
6999  organizer,
7001  tentative,
7003  accept,
7005  decline,
7008 };
7009 
7010 namespace internal
7011 {
7012  inline std::string enum_to_str(response_type val)
7013  {
7014  switch (val)
7015  {
7017  return "Unknown";
7019  return "Organizer";
7021  return "Tentative";
7022  case response_type::accept:
7023  return "Accept";
7025  return "Decline";
7027  return "NoResponseReceived";
7028  default:
7029  throw exception("Bad enum value");
7030  }
7031  }
7032 
7033  inline response_type str_to_response_type(const std::string& str)
7034  {
7035  if (str == "Unknown")
7036  {
7037  return response_type::unknown;
7038  }
7039  else if (str == "Organizer")
7040  {
7041  return response_type::organizer;
7042  }
7043  else if (str == "Tentative")
7044  {
7045  return response_type::tentative;
7046  }
7047  else if (str == "Accept")
7048  {
7049  return response_type::accept;
7050  }
7051  else if (str == "Decline")
7052  {
7053  return response_type::decline;
7054  }
7055  else if (str == "NoResponseReceived")
7056  {
7058  }
7059  else
7060  {
7061  throw exception("Bad enum value");
7062  }
7063  }
7064 } // namespace internal
7065 
7069 {
7071  calendar,
7072 
7074  contacts,
7075 
7077  deleted_items,
7078 
7080  drafts,
7081 
7083  inbox,
7084 
7086  journal,
7087 
7089  notes,
7090 
7092  outbox,
7093 
7095  sent_items,
7096 
7098  tasks,
7099 
7102 
7104  root,
7105 
7107  junk_email,
7108 
7111 
7113  voice_mail,
7114 
7116 
7119 
7123 
7127 
7131 
7133  archive_root,
7134 
7137 
7140 
7144  archive_inbox,
7145 
7149 
7153 
7157 
7161 
7162  // Following are folders that came with EWS 2013 and Exchange Online:
7163 
7165  sync_issues,
7166 
7168  conflicts,
7169 
7172 
7175 
7178 
7181 
7184 
7187 
7189  todo_search,
7190 
7192  my_contacts,
7193 
7195  directory,
7196 
7199 
7202 
7204  favorites
7205 };
7206 
7211 {
7212  std::string internal_ews_url;
7213  std::string external_ews_url;
7214 };
7215 
7217 {
7218  std::string autodiscover_url;
7219 };
7220 
7222 enum class sensitivity
7223 {
7225  normal,
7227  personal,
7229  priv,
7231  confidential
7232 };
7233 
7234 namespace internal
7235 {
7236  inline std::string enum_to_str(sensitivity s)
7237  {
7238  switch (s)
7239  {
7240  case sensitivity::normal:
7241  return "Normal";
7242  case sensitivity::personal:
7243  return "Personal";
7244  case sensitivity::priv:
7245  return "Private";
7247  return "Confidential";
7248  default:
7249  throw exception("Bad enum value");
7250  }
7251  }
7252 
7253  inline sensitivity str_to_sensitivity(const std::string& str)
7254  {
7255  if (str == "Normal")
7256  {
7257  return sensitivity::normal;
7258  }
7259  else if (str == "Personal")
7260  {
7261  return sensitivity::personal;
7262  }
7263  else if (str == "Private")
7264  {
7265  return sensitivity::priv;
7266  }
7267  else if (str == "Confidential")
7268  {
7270  }
7271  else
7272  {
7273  throw exception("Bad enum value");
7274  }
7275  }
7276 } // namespace internal
7277 
7281 enum class importance
7282 {
7284  low,
7285 
7287  normal,
7288 
7290  high
7291 };
7292 
7293 namespace internal
7294 {
7295  inline std::string enum_to_str(importance i)
7296  {
7297  switch (i)
7298  {
7299  case importance::low:
7300  return "Low";
7301  case importance::normal:
7302  return "Normal";
7303  case importance::high:
7304  return "High";
7305  default:
7306  throw exception("Bad enum value");
7307  }
7308  }
7309 
7310  inline importance str_to_importance(const std::string& str)
7311  {
7312  if (str == "Low")
7313  {
7314  return importance::low;
7315  }
7316  else if (str == "High")
7317  {
7318  return importance::high;
7319  }
7320  else if (str == "Normal")
7321  {
7322  return importance::normal;
7323  }
7324  else
7325  {
7326  throw exception("Bad enum value");
7327  }
7328  }
7329 
7330  struct response_result
7331  {
7332  response_class cls;
7333  response_code code;
7334  std::string message;
7335 
7336  response_result(response_class cls_, response_code code_)
7337  : cls(cls_), code(code_), message()
7338  {
7339  }
7340 
7341  response_result(response_class cls_, response_code code_,
7342  std::string&& msg)
7343  : cls(cls_), code(code_), message(std::move(msg))
7344  {
7345  }
7346  };
7347 } // namespace internal
7348 
7350 enum class search_scope
7351 {
7359  contacts,
7363 };
7364 
7365 namespace internal
7366 {
7367  inline std::string enum_to_str(search_scope s)
7368  {
7369  switch (s)
7370  {
7372  return "ActiveDirectory";
7374  return "ActiveDirectoryContacts";
7376  return "Contacts";
7378  return "ContactsActiveDirectory";
7379  default:
7380  throw exception("Bad enum value");
7381  }
7382  }
7383 
7384  inline search_scope str_to_search_scope(const std::string& str)
7385  {
7386  if (str == "ActiveDirectory")
7387  {
7389  }
7390  else if (str == "ActiveDirectoryContacts")
7391  {
7393  }
7394  else if (str == "Contacts")
7395  {
7396  return search_scope::contacts;
7397  }
7398  else if (str == "ContactsActiveDirectory")
7399  {
7401  }
7402  else
7403  {
7404  throw exception("Bad enum value");
7405  }
7406  }
7407 } // namespace internal
7408 
7409 #ifdef EWS_HAS_VARIANT
7410 enum class event_type
7412 {
7414  copied_event,
7415 
7417  created_event,
7418 
7420  deleted_event,
7421 
7423  modified_event,
7424 
7427  moved_event,
7428 
7430  new_mail_event,
7432  status_event,
7433 
7435  free_busy_changed_event
7436 };
7437 
7438 namespace internal
7439 {
7440  inline std::string enum_to_str(event_type e)
7441  {
7442  switch (e)
7443  {
7444  case event_type::copied_event:
7445  return "CopiedEvent";
7446  case event_type::created_event:
7447  return "CreatedEvent";
7448  case event_type::deleted_event:
7449  return "DeletedEvent";
7450  case event_type::modified_event:
7451  return "ModifiedEvent";
7452  case event_type::moved_event:
7453  return "MovedEvent";
7454  case event_type::new_mail_event:
7455  return "NewMailEvent";
7456  case event_type::status_event:
7457  return "StatusEvent";
7458  case event_type::free_busy_changed_event:
7459  return "FreeBusyChangedEvent";
7460  default:
7461  throw exception("Bad enum value");
7462  }
7463  }
7464 
7465  inline event_type str_to_event_type(const std::string& str)
7466  {
7467  if (str == "CopiedEvent")
7468  {
7469  return event_type::copied_event;
7470  }
7471  else if (str == "CreatedEvent")
7472  {
7473  return event_type::created_event;
7474  }
7475  else if (str == "DeletedEvent")
7476  {
7477  return event_type::deleted_event;
7478  }
7479  else if (str == "ModifiedEvent")
7480  {
7481  return event_type::modified_event;
7482  }
7483  else if (str == "MovedEvent")
7484  {
7485  return event_type::moved_event;
7486  }
7487  else if (str == "NewMailEvent")
7488  {
7489  return event_type::new_mail_event;
7490  }
7491  else if (str == "StatusEvent")
7492  {
7493  return event_type::status_event;
7494  }
7495  else if (str == "FreeBusyChangedEvent")
7496  {
7497  return event_type::free_busy_changed_event;
7498  }
7499  else
7500  {
7501  throw exception("Bad enum value");
7502  }
7503  }
7504 } // namespace internal
7505 #endif
7506 
7508 class exchange_error final : public exception
7509 {
7510 public:
7513  : exception(internal::enum_to_str(code)), code_(code)
7514  {
7515  }
7516 
7519  exchange_error(response_code code, const std::string& message_text)
7520  : exception(message_text.empty()
7521  ? internal::enum_to_str(code)
7522  : sanitize(message_text) + " (" +
7523  internal::enum_to_str(code) + ")"),
7524  code_(code)
7525  {
7526  }
7527 
7528 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
7529  explicit exchange_error(const internal::response_result& res)
7530  : exception(res.message.empty()
7531  ? internal::enum_to_str(res.code)
7532  : sanitize(res.message) + " (" +
7533  internal::enum_to_str(res.code) + ")"),
7534  code_(res.code)
7535  {
7536  }
7537 #endif
7538 
7539  response_code code() const EWS_NOEXCEPT { return code_; }
7540 
7541 private:
7542  std::string sanitize(const std::string& message_text)
7543  {
7544  // Remove trailing dot, if any
7545  if (!message_text.empty() || message_text.back() == '.')
7546  {
7547  std::string tmp(message_text);
7548  tmp.pop_back();
7549  return tmp;
7550  }
7551 
7552  return message_text;
7553  }
7554 
7555  response_code code_;
7556 };
7557 
7558 namespace internal
7559 {
7560  inline std::string http_status_code_to_str(int status_code)
7561  {
7562  switch (status_code)
7563  {
7564  case 100:
7565  return "Continue";
7566  case 101:
7567  return "Switching Protocols";
7568  case 200:
7569  return "OK";
7570  case 201:
7571  return "Created";
7572  case 202:
7573  return "Accepted";
7574  case 203:
7575  return "Non-Authoritative Information";
7576  case 204:
7577  return "No Content";
7578  case 205:
7579  return "Reset Content";
7580  case 206:
7581  return "Partial Content";
7582  case 300:
7583  return "Multiple Choices";
7584  case 301:
7585  return "Moved Permanently";
7586  case 302:
7587  return "Found";
7588  case 303:
7589  return "See Other";
7590  case 304:
7591  return "Not Modified";
7592  case 305:
7593  return "Use Proxy";
7594  case 307:
7595  return "Temporary Redirect";
7596  case 400:
7597  return "Bad Request";
7598  case 401:
7599  return "Unauthorized";
7600  case 402:
7601  return "Payment Required";
7602  case 403:
7603  return "Forbidden";
7604  case 404:
7605  return "Not Found";
7606  case 405:
7607  return "Method Not Allowed";
7608  case 406:
7609  return "Not Acceptable";
7610  case 407:
7611  return "Proxy Authentication Required";
7612  case 408:
7613  return "Request Timeout";
7614  case 409:
7615  return "Conflict";
7616  case 410:
7617  return "Gone";
7618  case 411:
7619  return "Length Required";
7620  case 412:
7621  return "Precondition Failed";
7622  case 413:
7623  return "Request Entity Too Large";
7624  case 414:
7625  return "Request-URI Too Long";
7626  case 415:
7627  return "Unsupported Media Type";
7628  case 416:
7629  return "Requested Range Not Satisfiable";
7630  case 417:
7631  return "Expectation Failed";
7632  case 500:
7633  return "Internal Server Error";
7634  case 501:
7635  return "Not Implemented";
7636  case 502:
7637  return "Bad Gateway";
7638  case 503:
7639  return "Service Unavailable";
7640  case 504:
7641  return "Gateway Timeout";
7642  case 505:
7643  return "HTTP Version Not Supported";
7644  }
7645  return "";
7646  }
7647 } // namespace internal
7648 
7650 class http_error final : public exception
7651 {
7652 public:
7653  explicit http_error(long status_code)
7654  : exception("HTTP status code: " + std::to_string(status_code) + " (" +
7655  internal::http_status_code_to_str(status_code) + ")"),
7656  code_(status_code)
7657  {
7658  }
7659 
7660  long code() const EWS_NOEXCEPT { return code_; }
7661 
7662 private:
7663  long code_;
7664 };
7665 
7667 class soap_fault : public exception
7668 {
7669 public:
7670  explicit soap_fault(const std::string& what) : exception(what) {}
7671  explicit soap_fault(const char* what) : exception(what) {}
7672 };
7673 
7684 {
7685 public:
7686  schema_validation_error(unsigned long line_number,
7687  unsigned long line_position, std::string violation)
7688  : soap_fault("The request failed schema validation"),
7689  violation_(std::move(violation)), line_pos_(line_position),
7690  line_no_(line_number)
7691  {
7692  }
7693 
7695  unsigned long line_number() const EWS_NOEXCEPT { return line_no_; }
7696 
7698  unsigned long line_position() const EWS_NOEXCEPT { return line_pos_; }
7699 
7701  const std::string& violation() const EWS_NOEXCEPT { return violation_; }
7702 
7703 private:
7704  std::string violation_;
7705  unsigned long line_pos_;
7706  unsigned long line_no_;
7707 };
7708 
7710 class curl_error final : public exception
7711 {
7712 public:
7713  explicit curl_error(const std::string& what,
7714  const std::string& error_details = "")
7715  : exception(what), error_details_(error_details)
7716  {
7717  }
7718  explicit curl_error(const char* what, const std::string& error_details = "")
7719  : exception(what), error_details_(error_details)
7720  {
7721  }
7722 
7724  const std::string& error_details() const EWS_NOEXCEPT
7725  {
7726  return error_details_;
7727  }
7728 
7729 private:
7730  std::string error_details_;
7731 };
7732 
7733 namespace internal
7734 {
7735  // Helper function; constructs an exception with a meaningful error
7736  // message from the given result code for the most recent cURL API call.
7737  //
7738  // msg: A string that prepends the actual cURL error message.
7739  // rescode: The result code of a failed cURL operation.
7740  inline curl_error make_curl_error(const std::string& msg, CURLcode rescode,
7741  const std::string& error_details = "")
7742  {
7743  auto reason = std::string(curl_easy_strerror(rescode));
7744 #ifdef NDEBUG
7745  (void)msg;
7746  return curl_error(reason, error_details);
7747 #else
7748  return curl_error(msg + ": \'" + reason + "\'", error_details);
7749 #endif
7750  }
7751 
7752  // RAII helper class for CURL* handles.
7753  class curl_ptr final
7754  {
7755  public:
7756  curl_ptr() : handle_(curl_easy_init())
7757  {
7758  if (!handle_)
7759  {
7760  throw curl_error("Could not start libcurl session");
7761  }
7762 
7763  curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, error_details_);
7764  }
7765 
7766  curl_ptr(const curl_ptr& other)
7767  : handle_(curl_easy_duphandle(other.handle_))
7768  {
7769  if (!handle_)
7770  {
7771  throw curl_error("Could not dup curl handle");
7772  }
7773 
7774  curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, error_details_);
7775  }
7776 
7777  ~curl_ptr() { curl_easy_cleanup(handle_); }
7778 
7779 #ifdef EWS_HAS_DEFAULT_AND_DELETE
7780  curl_ptr& operator=(const curl_ptr&) = delete;
7781 #else
7782  private:
7783  curl_ptr& operator=(const curl_ptr&); // Never defined
7784 
7785  public:
7786 #endif
7787 
7788  curl_ptr(curl_ptr&& other) : handle_(std::move(other.handle_))
7789  {
7790  other.handle_ = nullptr;
7791  curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, error_details_);
7792  }
7793 
7794  curl_ptr& operator=(curl_ptr&& rhs)
7795  {
7796  if (&rhs != this)
7797  {
7798  handle_ = std::move(rhs.handle_);
7799  rhs.handle_ = nullptr;
7800  curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, error_details_);
7801  }
7802  return *this;
7803  }
7804 
7805  CURL* get() const EWS_NOEXCEPT { return handle_; }
7806 
7807  const char* get_error_details() const EWS_NOEXCEPT
7808  {
7809  return error_details_;
7810  }
7811 
7812  private:
7813  CURL* handle_;
7814  char error_details_[CURL_ERROR_SIZE];
7815  };
7816 
7817 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
7818  defined(EWS_HAS_CXX17_STATIC_ASSERT)
7819  static_assert(std::is_default_constructible<curl_ptr>::value);
7820  static_assert(std::is_copy_constructible<curl_ptr>::value);
7821  static_assert(!std::is_copy_assignable<curl_ptr>::value);
7822  static_assert(std::is_move_constructible<curl_ptr>::value);
7823  static_assert(std::is_move_assignable<curl_ptr>::value);
7824 #endif
7825 
7826  // RAII wrapper class around cURLs slist construct.
7827  class curl_string_list final
7828  {
7829  public:
7830  curl_string_list() EWS_NOEXCEPT : slist_(nullptr) {}
7831 
7832  ~curl_string_list() { curl_slist_free_all(slist_); }
7833 
7834 #ifdef EWS_HAS_DEFAULT_AND_DELETE
7835  curl_string_list(const curl_string_list&) = delete;
7836  curl_string_list& operator=(const curl_string_list&) = delete;
7837 #else
7838  private:
7839  curl_string_list(const curl_string_list&); // N/A
7840  curl_string_list& operator=(const curl_string_list&); // N/A
7841 
7842  public:
7843 #endif
7844 
7845  curl_string_list(curl_string_list&& other)
7846  : slist_(std::move(other.slist_))
7847  {
7848  other.slist_ = nullptr;
7849  }
7850 
7851  curl_string_list& operator=(curl_string_list&& rhs)
7852  {
7853  if (&rhs != this)
7854  {
7855  slist_ = std::move(rhs.slist_);
7856  rhs.slist_ = nullptr;
7857  }
7858  return *this;
7859  }
7860 
7861  void append(const char* str) EWS_NOEXCEPT
7862  {
7863  slist_ = curl_slist_append(slist_, str);
7864  }
7865 
7866  curl_slist* get() const EWS_NOEXCEPT { return slist_; }
7867 
7868  private:
7869  curl_slist* slist_;
7870  };
7871 
7872 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
7873  defined(EWS_HAS_CXX17_STATIC_ASSERT)
7874  static_assert(std::is_default_constructible<curl_string_list>::value);
7875  static_assert(!std::is_copy_constructible<curl_string_list>::value);
7876  static_assert(!std::is_copy_assignable<curl_string_list>::value);
7877  static_assert(std::is_move_constructible<curl_string_list>::value);
7878  static_assert(std::is_move_assignable<curl_string_list>::value);
7879 #endif
7880 
7881  // String constants
7882  // TODO: sure this can't be done easier within a header file?
7883  // We need better handling of static strings (URIs, XML node names,
7884  // values and stuff, see usage of rapidxml::internal::compare)
7885  template <typename Ch = char> struct uri
7886  {
7887  struct microsoft
7888  {
7889  enum
7890  {
7891  errors_size = 58U
7892  };
7893  static const Ch* errors()
7894  {
7895  static const Ch* val = "http://schemas.microsoft.com/"
7896  "exchange/services/2006/errors";
7897  return val;
7898  }
7899  enum
7900  {
7901  types_size = 57U
7902  };
7903  static const Ch* types()
7904  {
7905  static const Ch* const val = "http://schemas.microsoft.com/"
7906  "exchange/services/2006/types";
7907  return val;
7908  }
7909  enum
7910  {
7911  messages_size = 60U
7912  };
7913  static const Ch* messages()
7914  {
7915  static const Ch* const val = "http://schemas.microsoft.com/"
7916  "exchange/services/2006/"
7917  "messages";
7918  return val;
7919  }
7920  enum
7921  {
7922  autodiscover_size = 79U
7923  };
7924  static const Ch* autodiscover()
7925  {
7926  static const Ch* const val = "http://schemas.microsoft.com/"
7927  "exchange/autodiscover/"
7928  "outlook/responseschema/2006a";
7929  return val;
7930  }
7931  };
7932 
7933  struct soapxml
7934  {
7935  enum
7936  {
7937  envelope_size = 41U
7938  };
7939  static const Ch* envelope()
7940  {
7941  static const Ch* const val =
7942  "http://schemas.xmlsoap.org/soap/envelope/";
7943  return val;
7944  }
7945  };
7946  };
7947 
7948  // This ought to be a DOM wrapper; usually around a web response
7949  //
7950  // This class basically wraps rapidxml::xml_document because the parsed
7951  // data must persist for the lifetime of the rapidxml::xml_document.
7952  class http_response final
7953  {
7954  public:
7955  http_response(long code, std::vector<char>&& data)
7956  : data_(std::move(data)), code_(code)
7957  {
7958  check(!data_.empty(), "Given data should not be empty");
7959  }
7960 
7961 #ifdef EWS_HAS_DEFAULT_AND_DELETE
7962  ~http_response() = default;
7963 
7964  http_response(const http_response&) = delete;
7965  http_response& operator=(const http_response&) = delete;
7966 #else
7967  http_response() {}
7968 
7969  private:
7970  http_response(const http_response&); // Never defined
7971  http_response& operator=(const http_response&); // Never defined
7972 
7973  public:
7974 #endif
7975 
7976  http_response(http_response&& other)
7977  : data_(std::move(other.data_)), code_(std::move(other.code_))
7978  {
7979  other.code_ = 0U;
7980  }
7981 
7982  http_response& operator=(http_response&& rhs)
7983  {
7984  if (&rhs != this)
7985  {
7986  data_ = std::move(rhs.data_);
7987  code_ = std::move(rhs.code_);
7988  }
7989  return *this;
7990  }
7991 
7992  // Returns a reference to the raw byte content in this HTTP
7993  // response.
7994  std::vector<char>& content() EWS_NOEXCEPT { return data_; }
7995 
7996  // Returns a reference to the raw byte content in this HTTP
7997  // response.
7998  const std::vector<char>& content() const EWS_NOEXCEPT { return data_; }
7999 
8000  // Returns the response code of the HTTP request.
8001  long code() const EWS_NOEXCEPT { return code_; }
8002 
8003  // Returns whether the response is a SOAP fault.
8004  //
8005  // This means the server responded with status code 500 and
8006  // indicates that the entire request failed (not just a normal EWS
8007  // error). This can happen e.g. when the request we sent was not
8008  // schema compliant.
8009  bool is_soap_fault() const EWS_NOEXCEPT { return code() == 500U; }
8010 
8011  // Returns whether the HTTP response code is 200 (OK).
8012  bool ok() const EWS_NOEXCEPT { return code() == 200U; }
8013 
8014  private:
8015  std::vector<char> data_;
8016  long code_;
8017  };
8018 
8019  // Loads the XML content from a given HTTP response into a
8020  // new xml_document and returns it.
8021  //
8022  // Note: we are using a mutable temporary buffer internally because
8023  // we are using RapidXml in destructive mode (the parser modifies
8024  // source text during the parsing process). Hence, we need to make
8025  // sure that parsing is done only once!
8026  inline std::unique_ptr<rapidxml::xml_document<char>>
8027  parse_response(http_response&& response)
8028  {
8029  if (response.content().empty())
8030  {
8031  throw xml_parse_error("Cannot parse empty response");
8032  }
8033 
8034 #ifdef EWS_HAS_MAKE_UNIQUE
8035  auto doc = std::make_unique<rapidxml::xml_document<char>>();
8036 #else
8037  auto doc = std::unique_ptr<rapidxml::xml_document<char>>(
8038  new rapidxml::xml_document<char>());
8039 #endif
8040  try
8041  {
8042  static const int flags = 0;
8043  doc->parse<flags>(&response.content()[0]);
8044  }
8045  catch (rapidxml::parse_error& exc)
8046  {
8047  // Swallow and erase type
8048  const auto msg =
8049  xml_parse_error::error_message_from(exc, response.content());
8050  throw xml_parse_error(msg);
8051  }
8052 
8053 #ifdef EWS_ENABLE_VERBOSE
8054  std::cerr << "Response code: " << response.code() << ", Content:\n\'"
8055  << *doc << "\'" << std::endl;
8056 #endif
8057 
8058  return doc;
8059  }
8060 
8061  // TODO: explicitly for nodes in Types XML namespace, document or
8062  // change interface
8063  inline rapidxml::xml_node<>& create_node(rapidxml::xml_node<>& parent,
8064  const std::string& name)
8065  {
8066  auto doc = parent.document();
8067  check(doc, "Parent node needs to be part of a document");
8068  auto ptr_to_qname = doc->allocate_string(name.c_str());
8069  auto new_node = doc->allocate_node(rapidxml::node_element);
8070  new_node->qname(ptr_to_qname, name.length(), ptr_to_qname + 2);
8071  new_node->namespace_uri(internal::uri<>::microsoft::types(),
8072  internal::uri<>::microsoft::types_size);
8073  parent.append_node(new_node);
8074  return *new_node;
8075  }
8076 
8077  inline rapidxml::xml_node<>& create_node(rapidxml::xml_node<>& parent,
8078  const std::string& name,
8079  const std::string& value)
8080  {
8081  auto doc = parent.document();
8082  check(doc, "Parent node needs to be part of a document");
8083  auto str = doc->allocate_string(value.c_str());
8084  auto& new_node = create_node(parent, name);
8085  new_node.value(str);
8086  return new_node;
8087  }
8088 
8089  // Traverse elements, depth first, beginning with given node.
8090  //
8091  // Applies given function to every element during traversal, stopping as
8092  // soon as that function returns true.
8093  template <typename Function>
8094  inline bool traverse_elements(const rapidxml::xml_node<>& node,
8095  Function func) EWS_NOEXCEPT
8096  {
8097  for (auto child = node.first_node(); child != nullptr;
8098  child = child->next_sibling())
8099  {
8100  if (traverse_elements(*child, func))
8101  {
8102  return true;
8103  }
8104 
8105  if (child->type() == rapidxml::node_element)
8106  {
8107  if (func(*child))
8108  {
8109  return true;
8110  }
8111  }
8112  }
8113  return false;
8114  }
8115 
8116  // Select element by qualified name, nullptr if there is no such element
8117  // TODO: how to avoid ambiguities when two elements exist with the same
8118  // name and namespace but different paths
8119  inline rapidxml::xml_node<>*
8120  get_element_by_qname(const rapidxml::xml_node<>& node,
8121  const char* local_name, const char* namespace_uri)
8122  {
8123  check(local_name, "Expected local_name, got nullptr");
8124  check(namespace_uri, "Expected namespace_uri, got nullptr");
8125 
8126  rapidxml::xml_node<>* element = nullptr;
8127  const auto local_name_len = strlen(local_name);
8128  const auto namespace_uri_len = strlen(namespace_uri);
8129  traverse_elements(node, [&](rapidxml::xml_node<>& elem) -> bool {
8130  using rapidxml::internal::compare;
8131 
8132  if (compare(elem.namespace_uri(), elem.namespace_uri_size(),
8133  namespace_uri, namespace_uri_len) &&
8134  compare(elem.local_name(), elem.local_name_size(), local_name,
8135  local_name_len))
8136  {
8137  element = std::addressof(elem);
8138  return true;
8139  }
8140  return false;
8141  });
8142  return element;
8143  }
8144 
8145  class credentials
8146  {
8147  public:
8148 #ifdef EWS_HAS_DEFAULT_AND_DELETE
8149  virtual ~credentials() = default;
8150  credentials& operator=(const credentials&) = default;
8151 #else
8152  virtual ~credentials() {}
8153 #endif
8154  virtual void certify(http_request*) const = 0;
8155  };
8156 
8158  class oauth2_basic : public credentials
8159  {
8160  public:
8161  oauth2_basic(std::string tenant, std::string client_id,
8162  std::string scope)
8163  : tenant_(std::move(tenant)), client_id_(std::move(client_id)),
8164  scope_(std::move(scope))
8165  {
8166  }
8167 
8168 #ifdef EWS_HAS_DEFAULT_AND_DELETE
8169  virtual ~oauth2_basic() = default;
8170  oauth2_basic& operator=(const oauth2_basic&) = default;
8171 #else
8172  virtual ~oauth2_basic() {}
8173 #endif
8174 
8175  void certify(internal::http_request*) const override;
8176 
8177  bool expired() const
8178  {
8179  return (std::chrono::steady_clock::now() > expiration);
8180  }
8181 
8182  protected:
8185  virtual void authenticate(internal::http_request* request) const;
8186 
8187  virtual void append_url(CURL* c, std::string& data) const = 0;
8188 
8189  private:
8190  std::string tenant_;
8191  std::string client_id_;
8192  std::string scope_;
8193  mutable std::string access_token;
8194  mutable std::chrono::steady_clock::time_point expiration;
8195  };
8196 
8197 } // namespace internal
8198 
8210 class basic_credentials final : public internal::credentials
8211 {
8212 public:
8213  basic_credentials(std::string username, std::string password)
8214  : username_(std::move(username)), password_(std::move(password))
8215  {
8216  }
8217 
8218 private:
8219  // Implemented below
8220  void certify(internal::http_request*) const override;
8221 
8222  std::string username_;
8223  std::string password_;
8224 };
8225 
8235 class ntlm_credentials final : public internal::credentials
8236 {
8237 public:
8238  ntlm_credentials(std::string username, std::string password,
8239  std::string domain)
8240  : username_(std::move(username)), password_(std::move(password)),
8241  domain_(std::move(domain))
8242  {
8243  }
8244 
8245 private:
8246  // Implemented below
8247  void certify(internal::http_request*) const override;
8248 
8249  std::string username_;
8250  std::string password_;
8251  std::string domain_;
8252 };
8253 
8257 class oauth2_client_credentials final : public internal::oauth2_basic
8258 {
8259 public:
8260  oauth2_client_credentials(std::string tenant, std::string client_id,
8261  std::string client_secret, std::string scope,
8262  std::string resource)
8263  : oauth2_basic(std::move(tenant), std::move(client_id),
8264  std::move(scope)),
8265  client_secret_(std::move(client_secret)),
8266  resource_(std::move(resource))
8267  {
8268  }
8269 
8270 private:
8271  void append_url(CURL* c, std::string& data) const override;
8272 
8273  const std::string client_secret_;
8274  const std::string resource_;
8275 };
8276 
8281  : public internal::oauth2_basic
8282 {
8283 public:
8285  std::string tenant, std::string client_id, std::string client_secret,
8286  std::string scope, std::string username, std::string password)
8287  : oauth2_basic(std::move(tenant), std::move(client_id),
8288  std::move(scope)),
8289  username_(std::move(username)), password_(std::move(password)),
8290  client_secret_(std::move(client_secret))
8291  {
8292  }
8293 
8294 private:
8295  void append_url(CURL* c, std::string& data) const override;
8296 
8297  const std::string username_;
8298  const std::string password_;
8299  const std::string client_secret_;
8300 };
8301 
8302 namespace internal
8303 {
8304  class http_request final
8305  {
8306  public:
8307  enum class method
8308  {
8309  POST
8310  };
8311 
8312  // Create a new HTTP request to the given URL.
8313  explicit http_request(const std::string& url)
8314  {
8315  set_option(CURLOPT_URL, url.c_str());
8316  }
8317 
8319  explicit http_request(const curl_ptr& handle) : handle_(handle)
8320  {
8321  // empty
8322  }
8323 
8325  const curl_ptr& get_handle() const { return handle_; }
8326 
8327  // Set the HTTP method (only POST supported).
8328  void set_method(method)
8329  {
8330  // Method can only be a regular POST in our use case
8331  set_option(CURLOPT_POST, 1);
8332  }
8333 
8334  // Set this HTTP request's content type.
8335  void set_content_type(const std::string& content_type)
8336  {
8337  const std::string str = "Content-Type: " + content_type;
8338  headers_.append(str.c_str());
8339  }
8340 
8341  // Set this HTTP request's content length.
8342  void set_content_length(size_t content_length)
8343  {
8344  const std::string str =
8345  "Content-Length: " + std::to_string(content_length);
8346  headers_.append(str.c_str());
8347  }
8348 
8349  void set_authorization(const std::string& authorization)
8350  {
8351  const std::string str = "Authorization: " + authorization;
8352  headers_.append(str.c_str());
8353  }
8354 
8355  // Set credentials for authentication.
8356  void set_credentials(const credentials& creds) { creds.certify(this); }
8357 
8358  void set_timeout(std::chrono::seconds timeout)
8359  {
8360  curl_easy_setopt(handle_.get(), CURLOPT_TIMEOUT, timeout.count());
8361  }
8362 
8363 #ifdef EWS_HAS_VARIADIC_TEMPLATES
8364  // Small wrapper around curl_easy_setopt(3).
8365  //
8366  // Converts return codes to exceptions of type curl_error and allows
8367  // objects other than http_web_requests to set transfer options
8368  // without direct access to the internal CURL handle.
8369  template <typename... Args>
8370  void set_option(CURLoption option, Args... args)
8371  {
8372  auto retcode = curl_easy_setopt(handle_.get(), option,
8373  std::forward<Args>(args)...);
8374  switch (retcode)
8375  {
8376  case CURLE_OK:
8377  return;
8378 
8379  case CURLE_FAILED_INIT:
8380  {
8381  throw make_curl_error("curl_easy_setopt: unsupported option",
8382  retcode);
8383  }
8384 
8385  default:
8386  {
8387  throw make_curl_error("curl_easy_setopt: failed setting option",
8388  retcode);
8389  }
8390  };
8391  }
8392 #else
8393  template <typename T1> void set_option(CURLoption option, T1 arg1)
8394  {
8395  auto retcode = curl_easy_setopt(handle_.get(), option, arg1);
8396  switch (retcode)
8397  {
8398  case CURLE_OK:
8399  return;
8400 
8401  case CURLE_FAILED_INIT:
8402  {
8403  throw make_curl_error("curl_easy_setopt: unsupported option",
8404  retcode);
8405  }
8406 
8407  default:
8408  {
8409  throw make_curl_error("curl_easy_setopt: failed setting option",
8410  retcode);
8411  }
8412  };
8413  }
8414 
8415  template <typename T1, typename T2>
8416  void set_option(CURLoption option, T1 arg1, T2 arg2)
8417  {
8418  auto retcode = curl_easy_setopt(handle_.get(), option, arg1, arg2);
8419  switch (retcode)
8420  {
8421  case CURLE_OK:
8422  return;
8423 
8424  case CURLE_FAILED_INIT:
8425  {
8426  throw make_curl_error("curl_easy_setopt: unsupported option",
8427  retcode);
8428  }
8429 
8430  default:
8431  {
8432  throw make_curl_error("curl_easy_setopt: failed setting option",
8433  retcode);
8434  }
8435  };
8436  }
8437 #endif
8438 
8439  // Perform the HTTP request and returns the response. This function
8440  // blocks until the complete response is received or a timeout is
8441  // reached. Throws curl_error if operation could not be completed.
8442  //
8443  // request: The complete request string; you must make sure that
8444  // the data is encoded the way you want the server to receive it.
8445  http_response send(const std::string& request)
8446  {
8447  auto callback = [](char* ptr, size_t size, size_t nmemb,
8448  void* userdata) -> size_t {
8449  std::vector<char>* buf =
8450  reinterpret_cast<std::vector<char>*>(userdata);
8451  const auto realsize = size * nmemb;
8452  try
8453  {
8454  buf->reserve(realsize + 1); // plus 0-terminus
8455  }
8456  catch (std::bad_alloc&)
8457  {
8458  // Out of memory, indicate error to libcurl
8459  return 0U;
8460  }
8461  std::copy(ptr, ptr + realsize, std::back_inserter(*buf));
8462  return realsize;
8463  };
8464 
8465  // Do not install (directly or indirectly) signal handlers nor
8466  // call any functions that cause signals to be sent to the
8467  // process
8468  // Note: SIGCHLD is raised anyway if we use CURLAUTH_NTLM_WB and
8469  // SIGPIPE is still possible, too
8470  set_option(CURLOPT_NOSIGNAL, 1L);
8471 
8472 #ifdef EWS_ENABLE_VERBOSE
8473  // Print HTTP headers to stderr
8474  set_option(CURLOPT_VERBOSE, 1L);
8475 #endif
8476 
8477  // Set complete request string for HTTP POST method; note: no
8478  // encoding here
8479  set_option(CURLOPT_POSTFIELDS, request.c_str());
8480  set_option(CURLOPT_POSTFIELDSIZE, request.length());
8481 
8482  // Finally, set HTTP headers. We do this as last action here
8483  // because we want to overwrite implicitly set header lines due
8484  // to the options set above with our own header lines
8485  set_option(CURLOPT_HTTPHEADER, headers_.get());
8486 
8487  std::vector<char> response_data;
8488  set_option(CURLOPT_WRITEFUNCTION,
8489  static_cast<size_t (*)(char*, size_t, size_t, void*)>(
8490  callback));
8491  set_option(CURLOPT_WRITEDATA, std::addressof(response_data));
8492 
8493 #ifdef EWS_DISABLE_TLS_CERT_VERIFICATION
8494  // Warn in release builds
8495 # ifdef NDEBUG
8496 # pragma message( \
8497  "warning: TLS verification of the server's authenticity is disabled")
8498 # endif
8499  // Turn-off verification of the server's authenticity
8500  set_option(CURLOPT_SSL_VERIFYPEER, 0L);
8501  set_option(CURLOPT_SSL_VERIFYHOST, 0L);
8502 
8503 # if LIBCURL_VERSION_NUM >= 0x073400
8504  set_option(CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
8505  set_option(CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
8506 # endif
8507 
8508 #endif
8509 
8510  auto retcode = curl_easy_perform(handle_.get());
8511  if (retcode != 0)
8512  {
8513  throw make_curl_error("curl_easy_perform", retcode,
8514  handle_.get_error_details());
8515  }
8516  long response_code = 0U;
8517  curl_easy_getinfo(handle_.get(), CURLINFO_RESPONSE_CODE,
8518  &response_code);
8519  response_data.emplace_back('\0');
8520  return http_response(std::move(response_code),
8521  std::move(response_data));
8522  }
8523 
8524  private:
8525  curl_ptr handle_;
8526  curl_string_list headers_;
8527  };
8528 
8529 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
8530  defined(EWS_HAS_CXX17_STATIC_ASSERT)
8531  static_assert(!std::is_default_constructible<http_request>::value);
8532  static_assert(!std::is_copy_constructible<http_request>::value);
8533  static_assert(!std::is_copy_assignable<http_request>::value);
8534  static_assert(std::is_move_constructible<http_request>::value);
8535  static_assert(std::is_move_assignable<http_request>::value);
8536 #endif
8537 
8538 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
8539  template <typename RequestHandler = http_request>
8540 #else
8541  template <typename RequestHandler>
8542 #endif
8543  inline http_response
8544  make_raw_soap_request(RequestHandler& handler, const std::string& soap_body,
8545  const std::vector<std::string>& soap_headers)
8546  {
8547  std::stringstream request_stream;
8548  request_stream
8549  << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
8550  "<soap:Envelope "
8551  "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
8552  "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
8553  "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" "
8554  "xmlns:m=\"http://schemas.microsoft.com/exchange/services/"
8555  "2006/messages\" "
8556  "xmlns:t=\"http://schemas.microsoft.com/exchange/services/"
8557  "2006/types\">";
8558 
8559  if (!soap_headers.empty())
8560  {
8561  request_stream << "<soap:Header>";
8562  for (const auto& header : soap_headers)
8563  {
8564  request_stream << header;
8565  }
8566  request_stream << "</soap:Header>";
8567  }
8568 
8569  request_stream << "<soap:Body>";
8570  request_stream << soap_body;
8571  request_stream << "</soap:Body>";
8572  request_stream << "</soap:Envelope>";
8573 
8574 #ifdef EWS_ENABLE_VERBOSE
8575  std::cerr << request_stream.str() << std::endl;
8576 #endif
8577  return handler.send(request_stream.str());
8578  }
8579 // Makes a raw SOAP request.
8580 //
8581 // url: The URL of the server to talk to.
8582 // username: The user-name of user.
8583 // password: The user's secret password, plain-text.
8584 // domain: The user's Windows domain.
8585 // soap_body: The contents of the SOAP body (minus the body element);
8586 // this is the actual EWS request.
8587 // soap_headers: Any SOAP headers to add.
8588 //
8589 // Returns the response.
8590 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
8591  template <typename RequestHandler = http_request>
8592 #else
8593  template <typename RequestHandler>
8594 #endif
8595  inline http_response
8596  make_raw_soap_request(const std::string& url, const std::string& username,
8597  const std::string& password,
8598  const std::string& domain,
8599  const std::string& soap_body,
8600  const std::vector<std::string>& soap_headers)
8601  {
8602  RequestHandler handler(url);
8603  handler.set_method(RequestHandler::method::POST);
8604  handler.set_content_type("text/xml; charset=utf-8");
8605  ntlm_credentials creds(username, password, domain);
8606  handler.set_credentials(creds);
8607  return make_raw_soap_request(handler, soap_body, soap_headers);
8608  }
8609 
8610  // A self-contained copy of a DOM sub-tree generally used to hold
8611  // properties of an item class
8612  //
8613  // We use rapidxml::print for copying the already parsed xml_document
8614  // into a new buffer and then re-parse this buffer again under the
8615  // assumption that all child elements are contained in
8616  //
8617  // http://schemas.microsoft.com/exchange/services/2006/types
8618  //
8619  // XML namespace.
8620  //
8621  // A default constructed xml_subtree instance makes only sense when an
8622  // item class is default constructed. In that case the buffer (and the
8623  // DOM) is initially empty and elements are added directly to the
8624  // document's root node.
8625  class xml_subtree final
8626  {
8627  public:
8628  struct attribute
8629  {
8630  std::string name;
8631  std::string value;
8632  };
8633 
8634  // Default constructible because item class (and it's descendants)
8635  // need to be
8636  xml_subtree() : rawdata_(), doc_(new rapidxml::xml_document<char>) {}
8637 
8638  explicit xml_subtree(const rapidxml::xml_node<char>& origin,
8639  size_t size_hint = 0U)
8640  : rawdata_(), doc_(new rapidxml::xml_document<char>)
8641  {
8642  reparse(origin, size_hint);
8643  }
8644 
8645  // Needs to be copy- and copy-assignable because item classes are.
8646  // However xml_document isn't (and can't be without major rewrite
8647  // IMHO). Hence, copying is quite costly as it involves serializing
8648  // DOM tree to string and re-parsing into new tree
8649  xml_subtree& operator=(const xml_subtree& rhs)
8650  {
8651  if (&rhs != this)
8652  {
8653  // FIXME: not strong exception safe
8654  rawdata_.clear();
8655  doc_->clear();
8656  // TODO: can be done with deep_copy
8657  reparse(*rhs.doc_, rhs.rawdata_.size());
8658  }
8659  return *this;
8660  }
8661 
8662  xml_subtree(const xml_subtree& other)
8663  : rawdata_(), doc_(new rapidxml::xml_document<char>)
8664  {
8665  reparse(*other.doc_, other.rawdata_.size());
8666  }
8667 
8668  // Returns a pointer to the root node of this sub-tree. Returned
8669  // pointer can be null
8670  rapidxml::xml_node<>* root() EWS_NOEXCEPT { return doc_->first_node(); }
8671 
8672  // Returns a pointer to the root node of this sub-tree. Returned
8673  // pointer can be null
8674  const rapidxml::xml_node<>* root() const EWS_NOEXCEPT
8675  {
8676  return doc_->first_node();
8677  }
8678 
8679  // Might return nullptr when there is no such element. Client code
8680  // needs to check returned pointer. Should never throw
8681  rapidxml::xml_node<char>*
8682  get_node(const char* node_name) const EWS_NOEXCEPT
8683  {
8684  return get_element_by_qname(*doc_, node_name,
8685  uri<>::microsoft::types());
8686  }
8687 
8688  rapidxml::xml_node<char>*
8689  get_node(const std::string& node_name) const EWS_NOEXCEPT
8690  {
8691  return get_node(node_name.c_str());
8692  }
8693 
8694  rapidxml::xml_document<char>* document() const EWS_NOEXCEPT
8695  {
8696  return doc_.get();
8697  }
8698 
8699  std::string get_value_as_string(const char* node_name) const
8700  {
8701  const auto node = get_node(node_name);
8702  return node ? std::string(node->value(), node->value_size()) : "";
8703  }
8704 
8705  // Update an existing node with a new value. If the node does not exist
8706  // it is created. Note that any extisting attribute will get removed
8707  // from an existing node.
8708  rapidxml::xml_node<char>& set_or_update(const std::string& node_name,
8709  const std::string& node_value)
8710  {
8711  using rapidxml::internal::compare;
8712 
8713  auto oldnode = get_element_by_qname(*doc_, node_name.c_str(),
8714  uri<>::microsoft::types());
8715  if (oldnode && compare(node_value.c_str(), node_value.length(),
8716  oldnode->value(), oldnode->value_size()))
8717  {
8718  // Nothing to do
8719  return *oldnode;
8720  }
8721 
8722  const auto node_qname = "t:" + node_name;
8723  const auto ptr_to_qname = doc_->allocate_string(node_qname.c_str());
8724  const auto ptr_to_value = doc_->allocate_string(node_value.c_str());
8725 
8726  auto newnode = doc_->allocate_node(rapidxml::node_element);
8727  newnode->qname(ptr_to_qname, node_qname.length(), ptr_to_qname + 2);
8728  newnode->value(ptr_to_value);
8729  newnode->namespace_uri(uri<>::microsoft::types(),
8730  uri<>::microsoft::types_size);
8731  if (oldnode)
8732  {
8733  auto parent = oldnode->parent();
8734  parent->insert_node(oldnode, newnode);
8735  parent->remove_node(oldnode);
8736  return *oldnode;
8737  }
8738 
8739  doc_->append_node(newnode);
8740  return *newnode;
8741  }
8742 
8743  // Update an existing node with a set of attributes. If
8744  // the node does not exist it is created. Note that if the node already
8745  // exists, all extisting attributes will get removed and replaced by the
8746  // given set.
8747  rapidxml::xml_node<char>&
8748  set_or_update(const std::string& node_name,
8749  const std::vector<attribute>& attributes)
8750  {
8751  using rapidxml::internal::compare;
8752 
8753  auto oldnode = get_element_by_qname(*doc_, node_name.c_str(),
8754  uri<>::microsoft::types());
8755  const auto node_qname = "t:" + node_name;
8756  const auto ptr_to_qname = doc_->allocate_string(node_qname.c_str());
8757 
8758  auto newnode = doc_->allocate_node(rapidxml::node_element);
8759  newnode->qname(ptr_to_qname, node_qname.length(), ptr_to_qname + 2);
8760  newnode->namespace_uri(uri<>::microsoft::types(),
8761  uri<>::microsoft::types_size);
8762 
8763  for (auto& attrib : attributes)
8764  {
8765  const auto name = doc_->allocate_string(attrib.name.c_str());
8766  const auto value = doc_->allocate_string(attrib.value.c_str());
8767  auto attr = doc_->allocate_attribute(name, value);
8768  newnode->append_attribute(attr);
8769  }
8770 
8771  if (oldnode)
8772  {
8773  auto parent = oldnode->parent();
8774  parent->insert_node(oldnode, newnode);
8775  parent->remove_node(oldnode);
8776  return *oldnode;
8777  }
8778 
8779  doc_->append_node(newnode);
8780  return *newnode;
8781  }
8782 
8783  std::string to_string() const
8784  {
8785  std::string str;
8786  rapidxml::print(std::back_inserter(str), *doc_,
8787  rapidxml::print_no_indenting);
8788  return str;
8789  }
8790 
8791  void append_to(rapidxml::xml_node<>& dest) const
8792  {
8793  auto target_document = dest.document();
8794  auto source = doc_->first_node();
8795  if (source)
8796  {
8797  auto new_child = deep_copy(target_document, source);
8798  dest.append_node(new_child);
8799  }
8800  }
8801 
8802  private:
8803  std::vector<char> rawdata_;
8804  std::unique_ptr<rapidxml::xml_document<char>> doc_;
8805 
8806  // Custom namespace processor for parsing XML sub-tree. Makes
8807  // uri::microsoft::types the default namespace.
8808  struct custom_namespace_processor
8809  : public rapidxml::internal::xml_namespace_processor<char>
8810  {
8811  struct scope : public rapidxml::internal::xml_namespace_processor<
8812  char>::scope
8813  {
8814  explicit scope(xml_namespace_processor& processor)
8815  : rapidxml::internal::xml_namespace_processor<char>::scope(
8816  processor)
8817  {
8818  static auto nsattr = make_namespace_attribute();
8819  add_namespace_prefix(&nsattr);
8820  }
8821 
8822  static rapidxml::xml_attribute<char> make_namespace_attribute()
8823  {
8824  static const char* const name = "t";
8825  static const char* const value = uri<>::microsoft::types();
8826  rapidxml::xml_attribute<char> attr;
8827  attr.name(name, 1);
8828  attr.value(value, uri<>::microsoft::types_size);
8829  return attr;
8830  }
8831  };
8832  };
8833 
8834  void reparse(const rapidxml::xml_node<char>& source, size_t size_hint)
8835  {
8836  rawdata_.reserve(size_hint);
8837  rapidxml::print(std::back_inserter(rawdata_), source,
8838  rapidxml::print_no_indenting);
8839  rawdata_.emplace_back('\0');
8840 
8841  // Note: we use xml_document::parse_ns here. This is because we
8842  // substitute the default namespace processor with a custom one.
8843  // Reason we do this: when we re-parse only a sub-tree of the
8844  // original XML document, we loose all enclosing namespace URIs.
8845 
8846  doc_->parse_ns<0, custom_namespace_processor>(&rawdata_[0]);
8847  }
8848 
8849  static rapidxml::xml_node<>*
8850  deep_copy(rapidxml::xml_document<>* target_doc,
8851  const rapidxml::xml_node<>* source)
8852  {
8853  check(target_doc, "Expected target_doc, got nullptr");
8854  check(source, "Expected source, got nullptr");
8855 
8856  auto newnode = target_doc->allocate_node(source->type());
8857 
8858  // Copy name and value
8859  auto name = target_doc->allocate_string(source->name());
8860  newnode->qname(name, source->name_size(), source->local_name());
8861 
8862  auto value = target_doc->allocate_string(source->value());
8863  newnode->value(value, source->value_size());
8864 
8865  // Copy child nodes and attributes
8866  for (auto child = source->first_node(); child;
8867  child = child->next_sibling())
8868  {
8869  newnode->append_node(deep_copy(target_doc, child));
8870  }
8871 
8872  for (auto attr = source->first_attribute(); attr;
8873  attr = attr->next_attribute())
8874  {
8875  newnode->append_attribute(target_doc->allocate_attribute(
8876  attr->name(), attr->value(), attr->name_size(),
8877  attr->value_size()));
8878  }
8879 
8880  return newnode;
8881  }
8882  };
8883 
8884 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
8885  defined(EWS_HAS_CXX17_STATIC_ASSERT)
8886  static_assert(std::is_default_constructible<xml_subtree>::value);
8887  static_assert(std::is_copy_constructible<xml_subtree>::value);
8888  static_assert(std::is_copy_assignable<xml_subtree>::value);
8889  static_assert(std::is_move_constructible<xml_subtree>::value);
8890  static_assert(std::is_move_assignable<xml_subtree>::value);
8891 #endif
8892 
8893 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
8894  template <typename RequestHandler = http_request>
8895 #else
8896  template <typename RequestHandler>
8897 #endif
8898  inline autodiscover_result
8899  get_exchange_web_services_url(const std::string& user_smtp_address,
8900  const basic_credentials& credentials,
8901  unsigned int redirections,
8902  const autodiscover_hints& hints)
8903  {
8904  using rapidxml::internal::compare;
8905 
8906  // Check redirection counter. We don't want to get in an endless
8907  // loop
8908  if (redirections > 2)
8909  {
8910  throw exception("Maximum of two redirections reached");
8911  }
8912 
8913  // Check SMTP address
8914  if (user_smtp_address.empty())
8915  {
8916  throw exception("Empty SMTP address given");
8917  }
8918 
8919  std::string autodiscover_url;
8920  if (hints.autodiscover_url.empty())
8921  {
8922  // Get user name and domain part from the SMTP address
8923  const auto at_sign_idx = user_smtp_address.find_first_of("@");
8924  if (at_sign_idx == std::string::npos)
8925  {
8926  throw exception("No valid SMTP address given");
8927  }
8928 
8929  const auto username = user_smtp_address.substr(0, at_sign_idx);
8930  const auto domain = user_smtp_address.substr(
8931  at_sign_idx + 1, user_smtp_address.size());
8932 
8933  // It is important that we use an HTTPS end-point here because we
8934  // authenticate with HTTP basic auth; specifically we send the
8935  // passphrase in plain-text
8936  autodiscover_url =
8937  "https://" + domain + "/autodiscover/autodiscover.xml";
8938  }
8939  else
8940  {
8941  autodiscover_url = hints.autodiscover_url;
8942  }
8943  // Create an Outlook provider <Autodiscover/> request
8944  std::stringstream sstr;
8945  sstr << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
8946  << "<Autodiscover "
8947  << "xmlns=\"http://schemas.microsoft.com/exchange/"
8948  "autodiscover/outlook/requestschema/2006\">"
8949  << "<Request>"
8950  << "<EMailAddress>" << user_smtp_address << "</EMailAddress>"
8951  << "<AcceptableResponseSchema>"
8952  << internal::uri<>::microsoft::autodiscover()
8953  << "</AcceptableResponseSchema>"
8954  << "</Request>"
8955  << "</Autodiscover>";
8956  const auto request_string = sstr.str();
8957 
8958  RequestHandler handler(autodiscover_url);
8959  handler.set_method(RequestHandler::method::POST);
8960  handler.set_credentials(credentials);
8961  handler.set_content_type("text/xml; charset=utf-8");
8962  handler.set_content_length(request_string.size());
8963 
8964 #ifdef EWS_ENABLE_VERBOSE
8965  std::cerr << request_string << std::endl;
8966 #endif
8967 
8968  auto response = handler.send(request_string);
8969  if (!response.ok())
8970  {
8971  throw http_error(response.code());
8972  }
8973 
8974  const auto doc = parse_response(std::move(response));
8975 
8976  const auto account_node = get_element_by_qname(
8977  *doc, "Account", internal::uri<>::microsoft::autodiscover());
8978  if (!account_node)
8979  {
8980  // Check for <Error/> element
8981  const auto error_node =
8982  get_element_by_qname(*doc, "Error",
8983  "http://schemas.microsoft.com/exchange/"
8984  "autodiscover/responseschema/2006");
8985  if (error_node)
8986  {
8987  std::string error_code;
8988  std::string message;
8989 
8990  for (auto node = error_node->first_node(); node;
8991  node = node->next_sibling())
8992  {
8993  if (compare(node->local_name(), node->local_name_size(),
8994  "ErrorCode", strlen("ErrorCode")))
8995  {
8996  error_code =
8997  std::string(node->value(), node->value_size());
8998  }
8999  else if (compare(node->local_name(),
9000  node->local_name_size(), "Message",
9001  strlen("Message")))
9002  {
9003  message =
9004  std::string(node->value(), node->value_size());
9005  }
9006 
9007  if (!error_code.empty() && !message.empty())
9008  {
9009  throw exception(message +
9010  " (error code: " + error_code + ")");
9011  }
9012  }
9013  }
9014 
9015  throw exception("Unable to parse response");
9016  }
9017 
9018  // For each protocol in the response, look for the appropriate
9019  // protocol type (internal/external) and then look for the
9020  // corresponding <ASUrl/> element
9021  std::string protocol;
9022  autodiscover_result result;
9023  for (int i = 0; i < 2; i++)
9024  {
9025  for (auto protocol_node = account_node->first_node(); protocol_node;
9026  protocol_node = protocol_node->next_sibling())
9027  {
9028  if (i >= 1)
9029  {
9030  protocol = "EXCH";
9031  }
9032  else
9033  {
9034  protocol = "EXPR";
9035  }
9036  if (compare(protocol_node->local_name(),
9037  protocol_node->local_name_size(), "Protocol",
9038  strlen("Protocol")))
9039  {
9040  for (auto type_node = protocol_node->first_node();
9041  type_node; type_node = type_node->next_sibling())
9042  {
9043  if (compare(type_node->local_name(),
9044  type_node->local_name_size(), "Type",
9045  strlen("Type")) &&
9046  compare(type_node->value(), type_node->value_size(),
9047  protocol.c_str(), strlen(protocol.c_str())))
9048  {
9049  for (auto asurl_node = protocol_node->first_node();
9050  asurl_node;
9051  asurl_node = asurl_node->next_sibling())
9052  {
9053  if (compare(asurl_node->local_name(),
9054  asurl_node->local_name_size(),
9055  "ASUrl", strlen("ASUrl")))
9056  {
9057  if (i >= 1)
9058  {
9059  result.internal_ews_url = std::string(
9060  asurl_node->value(),
9061  asurl_node->value_size());
9062  return result;
9063  }
9064  else
9065  {
9066  result.external_ews_url = std::string(
9067  asurl_node->value(),
9068  asurl_node->value_size());
9069  }
9070  }
9071  }
9072  }
9073  }
9074  }
9075  }
9076  }
9077 
9078  // If we reach this point, then either autodiscovery returned an
9079  // error or there is a redirect address to retry the autodiscover
9080  // lookup
9081 
9082  for (auto redirect_node = account_node->first_node(); redirect_node;
9083  redirect_node = redirect_node->next_sibling())
9084  {
9085  if (compare(redirect_node->local_name(),
9086  redirect_node->local_name_size(), "RedirectAddr",
9087  strlen("RedirectAddr")))
9088  {
9089  // Retry
9090  redirections++;
9091  const auto redirect_address = std::string(
9092  redirect_node->value(), redirect_node->value_size());
9093  return get_exchange_web_services_url<RequestHandler>(
9094  redirect_address, credentials, redirections, hints);
9095  }
9096  }
9097 
9098  throw exception("Autodiscovery failed unexpectedly");
9099  }
9100 
9101  inline std::string escape(const char* str)
9102  {
9103  std::string res;
9104  rapidxml::internal::copy_and_expand_chars(str, str + strlen(str), '\0',
9105  std::back_inserter(res));
9106  return res;
9107  }
9108 
9109  inline std::string escape(const std::string& str)
9110  {
9111  return escape(str.c_str());
9112  }
9113 } // namespace internal
9114 
9121 inline void set_up() EWS_NOEXCEPT { curl_global_init(CURL_GLOBAL_DEFAULT); }
9122 
9129 inline void tear_down() EWS_NOEXCEPT { curl_global_cleanup(); }
9130 
9136 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
9137 template <typename RequestHandler = internal::http_request>
9138 #else
9139 template <typename RequestHandler>
9140 #endif
9141 inline autodiscover_result
9142 get_exchange_web_services_url(const std::string& user_smtp_address,
9143  const basic_credentials& credentials)
9144 {
9145  autodiscover_hints hints;
9146  return internal::get_exchange_web_services_url<RequestHandler>(
9147  user_smtp_address, credentials, 0U, hints);
9148 }
9149 
9156 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
9157 template <typename RequestHandler = internal::http_request>
9158 #else
9159 template <typename RequestHandler>
9160 #endif
9161 inline autodiscover_result
9162 get_exchange_web_services_url(const std::string& user_smtp_address,
9163  const basic_credentials& credentials,
9164  const autodiscover_hints& hints)
9165 {
9166  return internal::get_exchange_web_services_url<RequestHandler>(
9167  user_smtp_address, credentials, 0U, hints);
9168 }
9169 
9186 class item_id final
9187 {
9188 public:
9189 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9190  item_id() = default;
9192 #else
9193  item_id() {}
9194 #endif
9195 
9197  explicit item_id(std::string id) : id_(std::move(id)), change_key_() {}
9198 
9201  item_id(std::string id, std::string change_key)
9202  : id_(std::move(id)), change_key_(std::move(change_key))
9203  {
9204  }
9205 
9207  const std::string& id() const EWS_NOEXCEPT { return id_; }
9208 
9210  const std::string& change_key() const EWS_NOEXCEPT { return change_key_; }
9211 
9213  bool valid() const EWS_NOEXCEPT { return !id_.empty(); }
9214 
9216  std::string to_xml() const
9217  {
9218  return "<t:ItemId Id=\"" + id() + "\" ChangeKey=\"" + change_key() +
9219  "\"/>";
9220  }
9221 
9223  static item_id from_xml_element(const rapidxml::xml_node<>& elem)
9224  {
9225  auto id_attr = elem.first_attribute("Id");
9226  check(id_attr, "Missing attribute Id in <ItemId>");
9227  auto id = std::string(id_attr->value(), id_attr->value_size());
9228  auto ckey_attr = elem.first_attribute("ChangeKey");
9229  check(ckey_attr, "Missing attribute ChangeKey in <ItemId>");
9230  auto ckey = std::string(ckey_attr->value(), ckey_attr->value_size());
9231  return item_id(std::move(id), std::move(ckey));
9232  }
9233 
9234 private:
9235  // case-sensitive; therefore, comparisons between IDs must be
9236  // case-sensitive or binary
9237  std::string id_;
9238  std::string change_key_;
9239 };
9240 
9241 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9242  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9243 static_assert(std::is_default_constructible<item_id>::value);
9244 static_assert(std::is_copy_constructible<item_id>::value);
9245 static_assert(std::is_copy_assignable<item_id>::value);
9246 static_assert(std::is_move_constructible<item_id>::value);
9247 static_assert(std::is_move_assignable<item_id>::value);
9248 #endif
9249 
9253 {
9254 public:
9255 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9256  occurrence_item_id() = default;
9258 #else
9259  occurrence_item_id() {}
9260 #endif
9261 
9263  occurrence_item_id(std::string id) // intentionally not explicit
9264  : id_(std::move(id)), change_key_(), instance_index_(1)
9265  {
9266  }
9267 
9270  occurrence_item_id(const item_id& item_id) // intentionally not explicit
9271  : id_(item_id.id()), change_key_(item_id.change_key()),
9272  instance_index_(1)
9273  {
9274  }
9275 
9278  occurrence_item_id(const item_id& item_id, int instance_index)
9279  : id_(item_id.id()), change_key_(item_id.change_key()),
9280  instance_index_(instance_index)
9281  {
9282  }
9283 
9286  occurrence_item_id(std::string id, std::string change_key,
9287  int instance_index)
9288  : id_(std::move(id)), change_key_(std::move(change_key)),
9289  instance_index_(instance_index)
9290  {
9291  }
9292 
9294  const std::string& id() const EWS_NOEXCEPT { return id_; }
9295 
9297  const std::string& change_key() const EWS_NOEXCEPT { return change_key_; }
9298 
9300  int instance_index() const EWS_NOEXCEPT { return instance_index_; }
9301 
9303  bool valid() const EWS_NOEXCEPT { return !id_.empty(); }
9304 
9306  std::string to_xml() const
9307  {
9308  std::stringstream sstr;
9309  sstr << "<t:OccurrenceItemId RecurringMasterId=\"" << id();
9310  sstr << "\" ChangeKey=\"" << change_key() << "\" InstanceIndex=\"";
9311  sstr << instance_index() << "\"/>";
9312  return sstr.str();
9313  }
9314 
9317  static occurrence_item_id from_xml_element(const rapidxml::xml_node<>& elem)
9318  {
9319  auto id_attr = elem.first_attribute("RecurringMasterId");
9320  check(id_attr,
9321  "Missing attribute RecurringMasterId in <OccurrenceItemId>");
9322  auto id = std::string(id_attr->value(), id_attr->value_size());
9323 
9324  auto ckey_attr = elem.first_attribute("ChangeKey");
9325  check(ckey_attr, "Missing attribute ChangeKey in <OccurrenceItemId>");
9326  auto ckey = std::string(ckey_attr->value(), ckey_attr->value_size());
9327 
9328  auto index_attr = elem.first_attribute("InstanceIndex");
9329  check(index_attr,
9330  "Missing attribute InstanceIndex in <OccurrenceItemId>");
9331  auto index = std::stoi(
9332  std::string(index_attr->value(), index_attr->value_size()));
9333 
9334  return occurrence_item_id(std::move(id), std::move(ckey), index);
9335  }
9336 
9337 private:
9338  // case-sensitive; therefore, comparisons between IDs must be
9339  // case-sensitive or binary
9340  std::string id_;
9341  std::string change_key_;
9342  int instance_index_;
9343 };
9344 
9345 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9346  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9347 static_assert(std::is_default_constructible<occurrence_item_id>::value);
9348 static_assert(std::is_copy_constructible<occurrence_item_id>::value);
9349 static_assert(std::is_copy_assignable<occurrence_item_id>::value);
9350 static_assert(std::is_move_constructible<occurrence_item_id>::value);
9351 static_assert(std::is_move_assignable<occurrence_item_id>::value);
9352 #endif
9353 
9358 class attachment_id final
9359 {
9360 public:
9361 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9362  attachment_id() = default;
9363 #else
9364  attachment_id() {}
9365 #endif
9366 
9367 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
9368  explicit attachment_id(std::string id) : id_(std::move(id)) {}
9369 
9370  attachment_id(std::string id, item_id root_item_id)
9371  : id_(std::move(id)), root_item_id_(std::move(root_item_id))
9372  {
9373  }
9374 #endif
9375 
9378  const std::string& id() const EWS_NOEXCEPT { return id_; }
9379 
9388  const item_id& root_item_id() const EWS_NOEXCEPT { return root_item_id_; }
9389 
9391  bool valid() const EWS_NOEXCEPT { return !id_.empty(); }
9392 
9393  std::string to_xml() const
9394  {
9395  std::stringstream sstr;
9396  sstr << "<t:AttachmentId Id=\"" << id() << "\"";
9397  if (root_item_id().valid())
9398  {
9399  sstr << " RootItemId=\"" << root_item_id().id()
9400  << "\" RootItemChangeKey=\"" << root_item_id().change_key()
9401  << "\"";
9402  }
9403  sstr << "/>";
9404  return sstr.str();
9405  }
9406 
9408  static attachment_id from_xml_element(const rapidxml::xml_node<>& elem)
9409  {
9410  auto id_attr = elem.first_attribute("Id");
9411  check(id_attr, "Missing attribute Id in <AttachmentId>");
9412  auto id = std::string(id_attr->value(), id_attr->value_size());
9413  auto root_item_id = std::string();
9414  auto root_item_ckey = std::string();
9415 
9416  auto root_item_id_attr = elem.first_attribute("RootItemId");
9417  if (root_item_id_attr)
9418  {
9419  root_item_id = std::string(root_item_id_attr->value(),
9420  root_item_id_attr->value_size());
9421  auto root_item_ckey_attr =
9422  elem.first_attribute("RootItemChangeKey");
9423  check(root_item_ckey_attr,
9424  "Expected attribute 'RootItemChangeKey'");
9425  root_item_ckey = std::string(root_item_ckey_attr->value(),
9426  root_item_ckey_attr->value_size());
9427  }
9428 
9429  return root_item_id.empty()
9430  ? attachment_id(std::move(id))
9431  : attachment_id(std::move(id),
9432  item_id(std::move(root_item_id),
9433  std::move(root_item_ckey)));
9434  }
9435 
9436 private:
9437  std::string id_;
9438  item_id root_item_id_;
9439 };
9440 
9441 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9442  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9443 static_assert(std::is_default_constructible<attachment_id>::value);
9444 static_assert(std::is_copy_constructible<attachment_id>::value);
9445 static_assert(std::is_copy_assignable<attachment_id>::value);
9446 static_assert(std::is_move_constructible<attachment_id>::value);
9447 static_assert(std::is_move_assignable<attachment_id>::value);
9448 #endif
9449 
9455 class mailbox final
9456 {
9457 public:
9458 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9459  mailbox() = default;
9464 #else
9465  mailbox() {}
9466 #endif
9467 
9468  explicit mailbox(item_id id)
9469  : id_(std::move(id)), value_(), name_(), routing_type_(),
9470  mailbox_type_()
9471  {
9472  }
9473 
9474  explicit mailbox(std::string value, std::string name = std::string(),
9475  std::string routing_type = std::string(),
9476  std::string mailbox_type = std::string())
9477  : id_(), value_(std::move(value)), name_(std::move(name)),
9478  routing_type_(std::move(routing_type)),
9479  mailbox_type_(std::move(mailbox_type))
9480  {
9481  }
9482 
9484  bool none() const EWS_NOEXCEPT { return value_.empty() && !id_.valid(); }
9485 
9486  // TODO: rename
9487  const item_id& id() const EWS_NOEXCEPT { return id_; }
9488 
9490  const std::string& value() const EWS_NOEXCEPT { return value_; }
9491 
9495  const std::string& name() const EWS_NOEXCEPT { return name_; }
9496 
9498  //
9500  const std::string& routing_type() const EWS_NOEXCEPT
9501  {
9502  return routing_type_;
9503  }
9504 
9508  const std::string& mailbox_type() const EWS_NOEXCEPT
9509  {
9510  return mailbox_type_;
9511  }
9512 
9522  std::string to_xml(const char* xmlns = "t") const
9523  {
9524  std::stringstream sstr;
9525  sstr << "<" << xmlns << ":Mailbox>";
9526  if (id().valid())
9527  {
9528  sstr << id().to_xml();
9529  }
9530  else
9531  {
9532  sstr << "<t:EmailAddress>" << value() << "</t:EmailAddress>";
9533 
9534  if (!name().empty())
9535  {
9536  sstr << "<t:Name>" << name() << "</t:Name>";
9537  }
9538 
9539  if (!routing_type().empty())
9540  {
9541  sstr << "<t:RoutingType>" << routing_type()
9542  << "</t:RoutingType>";
9543  }
9544 
9545  if (!mailbox_type().empty())
9546  {
9547  sstr << "<t:MailboxType>" << mailbox_type()
9548  << "</t:MailboxType>";
9549  }
9550  }
9551  sstr << "</" << xmlns << ":Mailbox>";
9552  return sstr.str();
9553  }
9554 
9559  rapidxml::xml_node<>& to_xml_element(rapidxml::xml_node<>& parent) const
9560  {
9561  auto doc = parent.document();
9562 
9563  check(doc, "Parent node needs to be somewhere in a document");
9564 
9565  using namespace internal;
9566  auto& mailbox_node = create_node(parent, "t:Mailbox");
9567 
9568  if (!id_.valid())
9569  {
9570  check(!value_.empty(),
9571  "Neither item_id nor value set in mailbox instance");
9572 
9573  create_node(mailbox_node, "t:EmailAddress", value_);
9574 
9575  if (!name_.empty())
9576  {
9577  create_node(mailbox_node, "t:Name", name_);
9578  }
9579 
9580  if (!routing_type_.empty())
9581  {
9582  create_node(mailbox_node, "t:RoutingType", routing_type_);
9583  }
9584 
9585  if (!mailbox_type_.empty())
9586  {
9587  create_node(mailbox_node, "t:MailboxType", mailbox_type_);
9588  }
9589  }
9590  else
9591  {
9592  auto item_id_node = &create_node(mailbox_node, "t:ItemId");
9593 
9594  auto ptr_to_key = doc->allocate_string("Id");
9595  auto ptr_to_value = doc->allocate_string(id_.id().c_str());
9596  item_id_node->append_attribute(
9597  doc->allocate_attribute(ptr_to_key, ptr_to_value));
9598 
9599  ptr_to_key = doc->allocate_string("ChangeKey");
9600  ptr_to_value = doc->allocate_string(id_.change_key().c_str());
9601  item_id_node->append_attribute(
9602  doc->allocate_attribute(ptr_to_key, ptr_to_value));
9603  }
9604  return mailbox_node;
9605  }
9606 
9608  static mailbox from_xml_element(const rapidxml::xml_node<>& elem)
9609  {
9610  using rapidxml::internal::compare;
9611 
9612  // <Mailbox>
9613  // <Name/>
9614  // <EmailAddress/>
9615  // <RoutingType/>
9616  // <MailboxType/>
9617  // <ItemId/>
9618  // </Mailbox>
9619 
9620  std::string name;
9621  std::string address;
9622  std::string routing_type;
9623  std::string mailbox_type;
9624  item_id id;
9625 
9626  for (auto node = elem.first_node(); node; node = node->next_sibling())
9627  {
9628  if (compare(node->local_name(), node->local_name_size(), "Name",
9629  strlen("Name")))
9630  {
9631  name = std::string(node->value(), node->value_size());
9632  }
9633  else if (compare(node->local_name(), node->local_name_size(),
9634  "EmailAddress", strlen("EmailAddress")))
9635  {
9636  address = std::string(node->value(), node->value_size());
9637  }
9638  else if (compare(node->local_name(), node->local_name_size(),
9639  "RoutingType", strlen("RoutingType")))
9640  {
9641  routing_type = std::string(node->value(), node->value_size());
9642  }
9643  else if (compare(node->local_name(), node->local_name_size(),
9644  "MailboxType", strlen("MailboxType")))
9645  {
9646  mailbox_type = std::string(node->value(), node->value_size());
9647  }
9648  else if (compare(node->local_name(), node->local_name_size(),
9649  "ItemId", strlen("ItemId")))
9650  {
9651  id = item_id::from_xml_element(*node);
9652  }
9653  else
9654  {
9655  throw exception("Unexpected child element in <Mailbox>");
9656  }
9657  }
9658 
9659  if (!id.valid())
9660  {
9661  return mailbox(std::move(address), std::move(name),
9662  std::move(routing_type), std::move(mailbox_type));
9663  }
9664 
9665  return mailbox(std::move(id));
9666  }
9667 
9668 private:
9669  item_id id_;
9670  std::string value_;
9671  std::string name_;
9672  std::string routing_type_;
9673  std::string mailbox_type_;
9674 };
9675 
9676 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9677  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9678 static_assert(std::is_default_constructible<mailbox>::value);
9679 static_assert(std::is_copy_constructible<mailbox>::value);
9680 static_assert(std::is_copy_assignable<mailbox>::value);
9681 static_assert(std::is_move_constructible<mailbox>::value);
9682 static_assert(std::is_move_assignable<mailbox>::value);
9683 #endif
9684 
9685 class directory_id final
9686 {
9687 public:
9688 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9689  directory_id() = default;
9690 #else
9691  directory_id() {}
9692 #endif
9693  explicit directory_id(const std::string& str) : id_(str) {}
9694  const std::string& get_id() const EWS_NOEXCEPT { return id_; }
9695 
9696 private:
9697  std::string id_;
9698 };
9699 
9700 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9701  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9702 static_assert(std::is_default_constructible<directory_id>::value);
9703 static_assert(std::is_copy_constructible<directory_id>::value);
9704 static_assert(std::is_copy_assignable<directory_id>::value);
9705 static_assert(std::is_move_constructible<directory_id>::value);
9706 static_assert(std::is_move_assignable<directory_id>::value);
9707 #endif
9708 
9709 struct resolution final
9710 {
9713  std::shared_ptr<ews::contact> contact;
9714 };
9715 
9716 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9717  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9718 static_assert(std::is_default_constructible<resolution>::value);
9719 static_assert(std::is_copy_constructible<resolution>::value);
9720 static_assert(std::is_copy_assignable<resolution>::value);
9721 static_assert(std::is_move_constructible<resolution>::value);
9722 static_assert(std::is_move_assignable<resolution>::value);
9723 #endif
9724 
9725 class resolution_set final
9726 {
9727 public:
9728  resolution_set()
9729  : includes_last_item_in_range(true), indexed_paging_offset(0),
9730  numerator_offset(0), absolute_denominator(0), total_items_in_view(0)
9731  {
9732  }
9733 
9735  bool empty() const EWS_NOEXCEPT { return resolutions.empty(); }
9736 
9738  std::vector<resolution>::iterator begin() { return resolutions.begin(); }
9739 
9741  std::vector<resolution>::iterator end() { return resolutions.end(); }
9742 
9743  bool includes_last_item_in_range;
9744  int indexed_paging_offset;
9745  int numerator_offset;
9746  int absolute_denominator;
9747  int total_items_in_view;
9748  std::vector<resolution> resolutions;
9749 };
9750 
9751 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9752  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9753 static_assert(std::is_default_constructible<resolution_set>::value);
9754 static_assert(std::is_copy_constructible<resolution_set>::value);
9755 static_assert(std::is_copy_assignable<resolution_set>::value);
9756 static_assert(std::is_move_constructible<resolution_set>::value);
9757 static_assert(std::is_move_assignable<resolution_set>::value);
9758 #endif
9759 
9760 #ifdef EWS_HAS_VARIANT
9761 class subscription_information final
9763 {
9764 public:
9765 # ifdef EWS_HAS_DEFAULT_AND_DELETE
9766  subscription_information() = default;
9767 # else
9768  subscription_information() {}
9769 # endif
9770  subscription_information(std::string id, std::string mark)
9771  : subscription_id_(std::move(id)), watermark_(std::move(mark))
9772  {
9773  }
9774 
9775  const std::string& get_subscription_id() const EWS_NOEXCEPT
9776  {
9777  return subscription_id_;
9778  }
9779  const std::string& get_watermark() const EWS_NOEXCEPT { return watermark_; }
9780 
9781 private:
9782  std::string subscription_id_;
9783  std::string watermark_;
9784 };
9785 
9786 # if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9787  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9788 static_assert(std::is_default_constructible<subscription_information>::value);
9789 static_assert(std::is_copy_constructible<subscription_information>::value);
9790 static_assert(std::is_copy_assignable<subscription_information>::value);
9791 static_assert(std::is_move_constructible<subscription_information>::value);
9792 static_assert(std::is_move_assignable<subscription_information>::value);
9793 # endif
9794 #endif
9795 
9801 {
9802 public:
9803 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9804  folder_id() = default;
9805  virtual ~folder_id() = default;
9806  folder_id(const folder_id&) = default;
9807 #else
9808  folder_id() {}
9809  virtual ~folder_id() {}
9810 #endif
9811 
9812  explicit folder_id(std::string id) : id_(std::move(id)), change_key_() {}
9813 
9814  folder_id(std::string id, std::string change_key)
9815  : id_(std::move(id)), change_key_(std::move(change_key))
9816  {
9817  }
9818 
9819  std::string to_xml() const { return this->to_xml_impl(); }
9820 
9822  const std::string& id() const EWS_NOEXCEPT { return id_; }
9823 
9825  const std::string& change_key() const EWS_NOEXCEPT { return change_key_; }
9826 
9828  bool valid() const EWS_NOEXCEPT { return !id_.empty(); }
9829 
9831  static folder_id from_xml_element(const rapidxml::xml_node<>& elem)
9832  {
9833  auto id_attr = elem.first_attribute("Id");
9834  check(id_attr, "Expected <Id> to have an Id attribute");
9835  auto id = std::string(id_attr->value(), id_attr->value_size());
9836 
9837  std::string change_key;
9838  auto ck_attr = elem.first_attribute("ChangeKey");
9839  if (ck_attr)
9840  {
9841  change_key = std::string(ck_attr->value(), ck_attr->value_size());
9842  }
9843  return folder_id(std::move(id), std::move(change_key));
9844  }
9845 
9846 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
9847 protected:
9848  virtual std::string to_xml_impl() const
9849  {
9850  std::stringstream sstr;
9851  sstr << "<t:"
9852  << "FolderId Id=\"" << id_;
9853  if (!change_key_.empty())
9854  {
9855  sstr << "\" ChangeKey=\"" << change_key_;
9856  }
9857  sstr << "\"/>";
9858  return sstr.str();
9859  }
9860 #endif
9861 
9862 private:
9863  std::string id_;
9864  std::string change_key_;
9865 };
9866 
9867 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
9868  defined(EWS_HAS_CXX17_STATIC_ASSERT)
9869 static_assert(std::is_default_constructible<folder_id>::value);
9870 static_assert(std::is_copy_constructible<folder_id>::value);
9871 static_assert(std::is_copy_assignable<folder_id>::value);
9872 static_assert(std::is_move_constructible<folder_id>::value);
9873 static_assert(std::is_move_assignable<folder_id>::value);
9874 #endif
9875 
9880 {
9881 public:
9882 #ifdef EWS_HAS_DEFAULT_AND_DELETE
9883  distinguished_folder_id() = default;
9884 #else
9886 #endif
9887 
9891  : folder_id(well_known_name(folder)) // explicit
9892  {
9893  }
9894 
9898  : folder_id(well_known_name(folder), std::move(change_key))
9899  {
9900  }
9901 
9916  : folder_id(well_known_name(folder)), owner_(std::move(owner))
9917  {
9918  }
9919 
9921  static standard_folder str_to_standard_folder(const std::string& name)
9922  {
9923  if (name == "calendar")
9924  {
9926  }
9927  else if (name == "contacts")
9928  {
9930  }
9931  else if (name == "deleteditems")
9932  {
9934  }
9935  else if (name == "drafts")
9936  {
9937  return standard_folder::drafts;
9938  }
9939  else if (name == "inbox")
9940  {
9941  return standard_folder::inbox;
9942  }
9943  else if (name == "journal")
9944  {
9945  return standard_folder::journal;
9946  }
9947  else if (name == "notes")
9948  {
9949  return standard_folder::notes;
9950  }
9951  else if (name == "outbox")
9952  {
9953  return standard_folder::outbox;
9954  }
9955  else if (name == "sentitems")
9956  {
9958  }
9959  else if (name == "tasks")
9960  {
9961  return standard_folder::tasks;
9962  }
9963  else if (name == "msgfolderroot")
9964  {
9966  }
9967  else if (name == "root")
9968  {
9969  return standard_folder::root;
9970  }
9971  else if (name == "junkemail")
9972  {
9974  }
9975  else if (name == "searchfolders")
9976  {
9978  }
9979  else if (name == "voicemail")
9980  {
9982  }
9983  else if (name == "recoverableitemsroot")
9984  {
9986  }
9987  else if (name == "recoverableitemsdeletions")
9988  {
9990  }
9991  else if (name == "recoverableitemsversions")
9992  {
9994  }
9995  else if (name == "recoverableitemspurges")
9996  {
9998  }
9999  else if (name == "archiveroot")
10000  {
10002  }
10003  else if (name == "archivemsgfolderroot")
10004  {
10006  }
10007  else if (name == "archivedeleteditems")
10008  {
10010  }
10011  else if (name == "archiveinbox")
10012  {
10014  }
10015  else if (name == "archiverecoverableitemsroot")
10016  {
10018  }
10019  else if (name == "archiverecoverableitemsdeletions")
10020  {
10022  }
10023  else if (name == "archiverecoverableitemsversions")
10024  {
10026  }
10027  else if (name == "archiverecoverableitemspurges")
10028  {
10030  }
10031  else if (name == "syncissues")
10032  {
10034  }
10035  else if (name == "conflicts")
10036  {
10038  }
10039  else if (name == "localfailures")
10040  {
10042  }
10043  else if (name == "serverfailures")
10044  {
10046  }
10047  else if (name == "recipientcache")
10048  {
10050  }
10051  else if (name == "quickcontacts")
10052  {
10054  }
10055  else if (name == "conversationhistory")
10056  {
10058  }
10059  else if (name == "adminauditlogs")
10060  {
10062  }
10063  else if (name == "todosearch")
10064  {
10066  }
10067  else if (name == "mycontacts")
10068  {
10070  }
10071  else if (name == "directory")
10072  {
10074  }
10075  else if (name == "imcontactlist")
10076  {
10078  }
10079  else if (name == "peopleconnect")
10080  {
10082  }
10083  else if (name == "favorites")
10084  {
10086  }
10087 
10088  throw exception("Unrecognized folder name");
10089  }
10090 
10092  static std::string well_known_name(standard_folder enumeration)
10093  {
10094  std::string name;
10095  switch (enumeration)
10096  {
10098  name = "calendar";
10099  break;
10100 
10102  name = "contacts";
10103  break;
10104 
10106  name = "deleteditems";
10107  break;
10108 
10110  name = "drafts";
10111  break;
10112 
10114  name = "inbox";
10115  break;
10116 
10118  name = "journal";
10119  break;
10120 
10122  name = "notes";
10123  break;
10124 
10126  name = "outbox";
10127  break;
10128 
10130  name = "sentitems";
10131  break;
10132 
10134  name = "tasks";
10135  break;
10136 
10138  name = "msgfolderroot";
10139  break;
10140 
10141  case standard_folder::root:
10142  name = "root";
10143  break;
10144 
10146  name = "junkemail";
10147  break;
10148 
10150  name = "searchfolders";
10151  break;
10152 
10154  name = "voicemail";
10155  break;
10156 
10158  name = "recoverableitemsroot";
10159  break;
10160 
10162  name = "recoverableitemsdeletions";
10163  break;
10164 
10166  name = "recoverableitemsversions";
10167  break;
10168 
10170  name = "recoverableitemspurges";
10171  break;
10172 
10174  name = "archiveroot";
10175  break;
10176 
10178  name = "archivemsgfolderroot";
10179  break;
10180 
10182  name = "archivedeleteditems";
10183  break;
10184 
10186  name = "archiveinbox";
10187  break;
10188 
10190  name = "archiverecoverableitemsroot";
10191  break;
10192 
10194  name = "archiverecoverableitemsdeletions";
10195  break;
10196 
10198  name = "archiverecoverableitemsversions";
10199  break;
10200 
10202  name = "archiverecoverableitemspurges";
10203  break;
10204 
10206  name = "syncissues";
10207  break;
10208 
10210  name = "conflicts";
10211  break;
10212 
10214  name = "localfailures";
10215  break;
10216 
10218  name = "serverfailures";
10219  break;
10220 
10222  name = "recipientcache";
10223  break;
10224 
10226  name = "quickcontacts";
10227  break;
10228 
10230  name = "conversationhistory";
10231  break;
10232 
10234  name = "adminauditlogs";
10235  break;
10236 
10238  name = "todosearch";
10239  break;
10240 
10242  name = "mycontacts";
10243  break;
10244 
10246  name = "directory";
10247  break;
10248 
10250  name = "imcontactlist";
10251  break;
10252 
10254  name = "peopleconnect";
10255  break;
10256 
10258  name = "favorites";
10259  break;
10260 
10261  default:
10262  throw exception("Unrecognized folder name");
10263  };
10264  return name;
10265  }
10266 
10267 private:
10268 #ifdef EWS_HAS_OPTIONAL
10269  std::optional<mailbox> owner_;
10270 #else
10271  internal::optional<mailbox> owner_;
10272 #endif
10273 
10274  std::string to_xml_impl() const override
10275  {
10276  std::stringstream sstr;
10277  sstr << "<t:DistinguishedFolderId Id=\"";
10278  sstr << id();
10279 
10280  if (owner_.has_value())
10281  {
10282  sstr << "\">";
10283  sstr << owner_.value().to_xml();
10284  sstr << "</t:DistinguishedFolderId>";
10285  }
10286  else
10287  {
10288  if (!change_key().empty())
10289  {
10290  sstr << "\" ChangeKey=\"" << change_key();
10291  }
10292  sstr << "\"/>";
10293  }
10294  return sstr.str();
10295  }
10296 };
10297 
10298 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
10299  defined(EWS_HAS_CXX17_STATIC_ASSERT)
10300 static_assert(std::is_default_constructible<distinguished_folder_id>::value);
10301 static_assert(std::is_copy_constructible<distinguished_folder_id>::value);
10302 static_assert(std::is_copy_assignable<distinguished_folder_id>::value);
10303 static_assert(std::is_move_constructible<distinguished_folder_id>::value);
10304 static_assert(std::is_move_assignable<distinguished_folder_id>::value);
10305 #endif
10306 
10307 #ifdef EWS_HAS_VARIANT
10308 namespace internal
10309 {
10310  class event_base
10311  {
10312  public:
10313  const event_type& get_type() const EWS_NOEXCEPT { return type_; }
10314  const std::string& get_watermark() const EWS_NOEXCEPT
10315  {
10316  return watermark_;
10317  }
10318 
10319  protected:
10320  event_type type_;
10321  std::string watermark_;
10322  };
10323 } // namespace internal
10325 class copied_event final : public internal::event_base
10326 {
10327 public:
10328 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10329  copied_event() = default;
10330 # else
10331  copied_event() {}
10332 # endif
10333 
10334  static copied_event from_xml_element(const rapidxml::xml_node<>& elem)
10335  {
10336  using rapidxml::internal::compare;
10337  copied_event e;
10338  std::string watermark;
10339  std::string timestamp;
10340  item_id id;
10341  item_id old_id;
10342  folder_id f_id;
10343  folder_id old_f_id;
10344  folder_id parent_folder_id;
10345  folder_id old_parent_folder_id;
10346  for (auto node = elem.first_node(); node; node = node->next_sibling())
10347  {
10348  if (compare(node->local_name(), node->local_name_size(),
10349  "Watermark", strlen("Watermark")))
10350  {
10351  watermark = std::string(node->value(), node->value_size());
10352  }
10353  if (compare(node->local_name(), node->local_name_size(),
10354  "TimeStamp", strlen("TimeStamp")))
10355  {
10356  timestamp = std::string(node->value(), node->value_size());
10357  }
10358  if (compare(node->local_name(), node->local_name_size(),
10359  "ParentFolderId", strlen("ParentFolderId")))
10360  {
10361  parent_folder_id = folder_id::from_xml_element(*node);
10362  }
10363  if (compare(node->local_name(), node->local_name_size(),
10364  "OldParentFolderId", strlen("OldParentFolderId")))
10365  {
10366  old_parent_folder_id = folder_id::from_xml_element(*node);
10367  }
10368  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10369  strlen("ItemId")))
10370  {
10371  id = item_id::from_xml_element(*node);
10372  }
10373  if (compare(node->local_name(), node->local_name_size(),
10374  "OldItemId", strlen("OldItemId")))
10375  {
10376  old_id = item_id::from_xml_element(*node);
10377  }
10378  if (compare(node->local_name(), node->local_name_size(), "FolderId",
10379  strlen("FolderId")))
10380  {
10381  f_id = folder_id::from_xml_element(*node);
10382  }
10383  if (compare(node->local_name(), node->local_name_size(),
10384  "OldFolderId", strlen("OldFolderId")))
10385  {
10386  old_f_id = folder_id::from_xml_element(*node);
10387  }
10388  }
10389  e.type_ = event_type::copied_event;
10390  e.watermark_ = watermark;
10391  e.timestamp_ = timestamp;
10392  e.id_ = id;
10393  e.old_item_id_ = old_id;
10394  e.folder_id_ = f_id;
10395  e.old_folder_id_ = old_f_id;
10396  e.parent_folder_id_ = parent_folder_id;
10397  e.old_parent_folder_id_ = old_parent_folder_id;
10398 
10399  return e;
10400  };
10401 
10402  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10403  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10404  const item_id& get_old_item_id() const EWS_NOEXCEPT { return old_item_id_; }
10405  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
10406  const folder_id& get_old_folder_id() const EWS_NOEXCEPT
10407  {
10408  return old_folder_id_;
10409  }
10410  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10411  {
10412  return parent_folder_id_;
10413  }
10414  const folder_id& get_old_parent_folder_id() const EWS_NOEXCEPT
10415  {
10416  return old_parent_folder_id_;
10417  }
10418 
10419 private:
10420  std::string timestamp_;
10421  item_id id_;
10422  item_id old_item_id_;
10423  folder_id folder_id_;
10424  folder_id old_folder_id_;
10425  folder_id parent_folder_id_;
10426  folder_id old_parent_folder_id_;
10427 };
10428 
10430 class created_event final : public internal::event_base
10431 {
10432 public:
10433 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10434  created_event() = default;
10435 # else
10436  created_event() {}
10437 # endif
10438  static created_event from_xml_element(const rapidxml::xml_node<>& elem)
10439  {
10440  using rapidxml::internal::compare;
10441  created_event e;
10442  std::string watermark;
10443  std::string timestamp;
10444  item_id id;
10445  folder_id f_id;
10446  folder_id parent_folder_id;
10447  for (auto node = elem.first_node(); node; node = node->next_sibling())
10448  {
10449  if (compare(node->local_name(), node->local_name_size(),
10450  "Watermark", strlen("Watermark")))
10451  {
10452  watermark = std::string(node->value(), node->value_size());
10453  }
10454  if (compare(node->local_name(), node->local_name_size(),
10455  "TimeStamp", strlen("TimeStamp")))
10456  {
10457  timestamp = std::string(node->value(), node->value_size());
10458  }
10459  if (compare(node->local_name(), node->local_name_size(),
10460  "ParentFolderId", strlen("ParentFolderId")))
10461  {
10462  parent_folder_id = folder_id::from_xml_element(*node);
10463  }
10464  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10465  strlen("ItemId")))
10466  {
10467  id = item_id::from_xml_element(*node);
10468  }
10469  if (compare(node->local_name(), node->local_name_size(), "FolderId",
10470  strlen("FolderId")))
10471  {
10472  f_id = folder_id::from_xml_element(*node);
10473  }
10474  }
10475  e.type_ = event_type::created_event;
10476  e.watermark_ = watermark;
10477  e.timestamp_ = timestamp;
10478  e.id_ = id;
10479  e.folder_id_ = f_id;
10480  e.parent_folder_id_ = parent_folder_id;
10481  return e;
10482  };
10483 
10484  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10485  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10486  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
10487  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10488  {
10489  return parent_folder_id_;
10490  }
10491 
10492 private:
10493  std::string timestamp_;
10494  item_id id_;
10495  folder_id folder_id_;
10496  folder_id parent_folder_id_;
10497 };
10498 
10500 class deleted_event final : public internal::event_base
10501 {
10502 public:
10503 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10504  deleted_event() = default;
10505 # else
10506  deleted_event() {}
10507 # endif
10508 
10509  static deleted_event from_xml_element(const rapidxml::xml_node<>& elem)
10510  {
10511  using rapidxml::internal::compare;
10512  deleted_event e;
10513  std::string watermark;
10514  std::string timestamp;
10515  item_id id;
10516  folder_id f_id;
10517  folder_id parent_folder_id;
10518  for (auto node = elem.first_node(); node; node = node->next_sibling())
10519  {
10520  if (compare(node->local_name(), node->local_name_size(),
10521  "Watermark", strlen("Watermark")))
10522  {
10523  watermark = std::string(node->value(), node->value_size());
10524  }
10525  if (compare(node->local_name(), node->local_name_size(),
10526  "TimeStamp", strlen("TimeStamp")))
10527  {
10528  timestamp = std::string(node->value(), node->value_size());
10529  }
10530  if (compare(node->local_name(), node->local_name_size(),
10531  "ParentFolderId", strlen("ParentFolderId")))
10532  {
10533  parent_folder_id = folder_id::from_xml_element(*node);
10534  }
10535  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10536  strlen("ItemId")))
10537  {
10538  id = item_id::from_xml_element(*node);
10539  }
10540  if (compare(node->local_name(), node->local_name_size(), "FolderId",
10541  strlen("FolderId")))
10542  {
10543  f_id = folder_id::from_xml_element(*node);
10544  }
10545  }
10546  e.type_ = event_type::deleted_event;
10547  e.watermark_ = watermark;
10548  e.timestamp_ = timestamp;
10549  e.id_ = id;
10550  e.folder_id_ = f_id;
10551  e.parent_folder_id_ = parent_folder_id;
10552 
10553  return e;
10554  };
10555 
10556  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10557  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10558  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
10559  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10560  {
10561  return parent_folder_id_;
10562  }
10563 
10564 private:
10565  std::string timestamp_;
10566  item_id id_;
10567  folder_id folder_id_;
10568  folder_id parent_folder_id_;
10569 };
10570 
10572 class modified_event final : public internal::event_base
10573 {
10574 public:
10575  modified_event() : unread_count_(0) {}
10576 
10577  static modified_event from_xml_element(const rapidxml::xml_node<>& elem)
10578  {
10579  using rapidxml::internal::compare;
10580  modified_event e;
10581  std::string watermark;
10582  std::string timestamp;
10583  item_id id;
10584  folder_id f_id;
10585  folder_id parent_folder_id;
10586  int unread_count = 0;
10587  for (auto node = elem.first_node(); node; node = node->next_sibling())
10588  {
10589  if (compare(node->local_name(), node->local_name_size(),
10590  "Watermark", strlen("Watermark")))
10591  {
10592  watermark = std::string(node->value(), node->value_size());
10593  }
10594  if (compare(node->local_name(), node->local_name_size(),
10595  "TimeStamp", strlen("TimeStamp")))
10596  {
10597  timestamp = std::string(node->value(), node->value_size());
10598  }
10599  if (compare(node->local_name(), node->local_name_size(),
10600  "ParentFolderId", strlen("ParentFolderId")))
10601  {
10602  parent_folder_id = folder_id::from_xml_element(*node);
10603  }
10604  if (compare(node->local_name(), node->local_name_size(),
10605  "UnreadCount", strlen("UnreadCount")))
10606  {
10607  unread_count = int(*node->value());
10608  }
10609  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10610  strlen("ItemId")))
10611  {
10612  id = item_id::from_xml_element(*node);
10613  }
10614  if (compare(node->local_name(), node->local_name_size(), "FolderId",
10615  strlen("FolderId")))
10616  {
10617  f_id = folder_id::from_xml_element(*node);
10618  }
10619  }
10620  e.type_ = event_type::modified_event;
10621  e.watermark_ = watermark;
10622  e.timestamp_ = timestamp;
10623  e.id_ = id;
10624  e.folder_id_ = f_id;
10625  e.parent_folder_id_ = parent_folder_id;
10626  e.unread_count_ = unread_count;
10627 
10628  return e;
10629  };
10630 
10631  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10632  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10633  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
10634  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10635  {
10636  return parent_folder_id_;
10637  }
10638  const int& get_unread_count() const EWS_NOEXCEPT { return unread_count_; }
10639 
10640 private:
10641  std::string timestamp_;
10642  int unread_count_;
10643  item_id id_;
10644  folder_id folder_id_;
10645  folder_id parent_folder_id_;
10646 };
10647 
10649 class moved_event final : public internal::event_base
10650 {
10651 public:
10652 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10653  moved_event() = default;
10654 # else
10655  moved_event() {}
10656 # endif
10657 
10658  static moved_event from_xml_element(const rapidxml::xml_node<>& elem)
10659  {
10660  using rapidxml::internal::compare;
10661  moved_event e;
10662  std::string watermark;
10663  std::string timestamp;
10664  item_id id;
10665  item_id old_id;
10666  folder_id f_id;
10667  folder_id old_f_id;
10668  folder_id parent_folder_id;
10669  folder_id old_parent_folder_id;
10670  for (auto node = elem.first_node(); node; node = node->next_sibling())
10671  {
10672  if (compare(node->local_name(), node->local_name_size(),
10673  "Watermark", strlen("Watermark")))
10674  {
10675  watermark = std::string(node->value(), node->value_size());
10676  }
10677  if (compare(node->local_name(), node->local_name_size(),
10678  "TimeStamp", strlen("TimeStamp")))
10679  {
10680  timestamp = std::string(node->value(), node->value_size());
10681  }
10682  if (compare(node->local_name(), node->local_name_size(),
10683  "ParentFolderId", strlen("ParentFolderId")))
10684  {
10685  parent_folder_id = folder_id::from_xml_element(*node);
10686  }
10687  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10688  strlen("ItemId")))
10689  {
10690  id = item_id::from_xml_element(*node);
10691  }
10692  if (compare(node->local_name(), node->local_name_size(),
10693  "OldItemId", strlen("OldItemId")))
10694  {
10695  old_id = item_id::from_xml_element(*node);
10696  }
10697  if (compare(node->local_name(), node->local_name_size(), "FolderId",
10698  strlen("FolderId")))
10699  {
10700  f_id = folder_id::from_xml_element(*node);
10701  }
10702  if (compare(node->local_name(), node->local_name_size(),
10703  "OldFolderId", strlen("OldFolderId")))
10704  {
10705  old_f_id = folder_id::from_xml_element(*node);
10706  }
10707  if (compare(node->local_name(), node->local_name_size(),
10708  "OldParentFolderId", strlen("OldParentFolderId")))
10709  {
10710  old_parent_folder_id = folder_id::from_xml_element(*node);
10711  }
10712  }
10713  e.type_ = event_type::moved_event;
10714  e.watermark_ = watermark;
10715  e.timestamp_ = timestamp;
10716  e.id_ = id;
10717  e.old_item_id_ = old_id;
10718  e.folder_id_ = f_id;
10719  e.old_folder_id_ = old_f_id;
10720  e.parent_folder_id_ = parent_folder_id;
10721  e.old_parent_folder_id_ = old_parent_folder_id;
10722 
10723  return e;
10724  };
10725 
10726  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10727  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10728  const item_id& get_old_item_id() const EWS_NOEXCEPT { return old_item_id_; }
10729  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
10730  const folder_id& get_old_folder_id() const EWS_NOEXCEPT
10731  {
10732  return old_folder_id_;
10733  }
10734  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10735  {
10736  return parent_folder_id_;
10737  }
10738  const folder_id& get_old_parent_folder_id() const EWS_NOEXCEPT
10739  {
10740  return old_parent_folder_id_;
10741  }
10742 
10743 private:
10744  std::string timestamp_;
10745  item_id id_;
10746  item_id old_item_id_;
10747  folder_id folder_id_;
10748  folder_id old_folder_id_;
10749  folder_id parent_folder_id_;
10750  folder_id old_parent_folder_id_;
10751 };
10752 
10754 class new_mail_event final : public internal::event_base
10755 {
10756 public:
10757 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10758  new_mail_event() = default;
10759 # else
10760  new_mail_event() {}
10761 # endif
10762 
10763  static new_mail_event from_xml_element(const rapidxml::xml_node<>& elem)
10764  {
10765  using rapidxml::internal::compare;
10766  new_mail_event e;
10767  std::string watermark;
10768  std::string timestamp;
10769  item_id id;
10770  folder_id parent_folder_id;
10771  for (auto node = elem.first_node(); node; node = node->next_sibling())
10772  {
10773  if (compare(node->local_name(), node->local_name_size(),
10774  "Watermark", strlen("Watermark")))
10775  {
10776  watermark = std::string(node->value(), node->value_size());
10777  }
10778  if (compare(node->local_name(), node->local_name_size(),
10779  "TimeStamp", strlen("TimeStamp")))
10780  {
10781  timestamp = std::string(node->value(), node->value_size());
10782  }
10783  if (compare(node->local_name(), node->local_name_size(),
10784  "ParentFolderId", strlen("ParentFolderId")))
10785  {
10786  parent_folder_id = folder_id::from_xml_element(*node);
10787  }
10788  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10789  strlen("ItemId")))
10790  {
10791  id = item_id::from_xml_element(*node);
10792  }
10793  }
10794  e.type_ = event_type::new_mail_event;
10795  e.watermark_ = watermark;
10796  e.timestamp_ = timestamp;
10797  e.id_ = id;
10798  e.parent_folder_id_ = parent_folder_id;
10799 
10800  return e;
10801  };
10802 
10803  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10804  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10805  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10806  {
10807  return parent_folder_id_;
10808  }
10809 
10810 private:
10811  std::string timestamp_;
10812  item_id id_;
10813  folder_id parent_folder_id_;
10814 };
10815 
10817 class status_event final : public internal::event_base
10818 {
10819 public:
10820 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10821  status_event() = default;
10822 # else
10823  status_event() {}
10824 # endif
10825  static status_event from_xml_element(const rapidxml::xml_node<>& elem)
10826  {
10827  using rapidxml::internal::compare;
10828  status_event e;
10829  std::string watermark;
10830  for (auto node = elem.first_node(); node; node = node->next_sibling())
10831  {
10832  if (compare(node->local_name(), node->local_name_size(),
10833  "Watermark", strlen("Watermark")))
10834  {
10835  watermark = std::string(node->value(), node->value_size());
10836  }
10837  }
10838  e.type_ = event_type::new_mail_event;
10839  e.watermark_ = watermark;
10840  return e;
10841  };
10842 };
10843 
10845 class free_busy_changed_event final : public internal::event_base
10846 {
10847 public:
10848 # ifdef EWS_HAS_DEFAULT_AND_DELETE
10849  free_busy_changed_event() = default;
10850 # else
10851  free_busy_changed_event() {}
10852 # endif
10853 
10854  static free_busy_changed_event
10855  from_xml_element(const rapidxml::xml_node<>& elem)
10856  {
10857  using rapidxml::internal::compare;
10858  free_busy_changed_event e;
10859  std::string watermark;
10860  std::string timestamp;
10861  item_id id;
10862  folder_id parent_folder_id;
10863  for (auto node = elem.first_node(); node; node = node->next_sibling())
10864  {
10865  if (compare(node->local_name(), node->local_name_size(),
10866  "Watermark", strlen("Watermark")))
10867  {
10868  watermark = std::string(node->value(), node->value_size());
10869  }
10870  if (compare(node->local_name(), node->local_name_size(),
10871  "TimeStamp", strlen("TimeStamp")))
10872  {
10873  timestamp = std::string(node->value(), node->value_size());
10874  }
10875  if (compare(node->local_name(), node->local_name_size(),
10876  "ParentFolderId", strlen("ParentFolderId")))
10877  {
10878  parent_folder_id = folder_id::from_xml_element(*node);
10879  }
10880  if (compare(node->local_name(), node->local_name_size(), "ItemId",
10881  strlen("ItemId")))
10882  {
10883  id = item_id::from_xml_element(*node);
10884  }
10885  }
10886  e.type_ = event_type::free_busy_changed_event;
10887  e.watermark_ = watermark;
10888  e.timestamp_ = timestamp;
10889  e.id_ = id;
10890  e.parent_folder_id_ = parent_folder_id;
10891 
10892  return e;
10893  };
10894 
10895  const std::string& get_timestamp() const EWS_NOEXCEPT { return timestamp_; }
10896  const item_id& get_item_id() const EWS_NOEXCEPT { return id_; }
10897  const folder_id& get_parent_folder_id() const EWS_NOEXCEPT
10898  {
10899  return parent_folder_id_;
10900  }
10901 
10902 private:
10903  std::string timestamp_;
10904  item_id id_;
10905  folder_id parent_folder_id_;
10906 };
10907 
10909 typedef std::variant<copied_event, created_event, deleted_event, modified_event,
10910  moved_event, new_mail_event, status_event,
10911  free_busy_changed_event>
10912  event;
10913 
10915 struct notification final
10916 {
10917  std::string subscription_id;
10918  std::string previous_watermark;
10919  bool more_events;
10920  std::vector<event> events;
10921 };
10922 #endif
10923 
10925 class attachment final
10926 {
10927 public:
10928  // Note that we are careful to avoid use of get_element_by_qname() here
10929  // because it might return elements of the enclosed item and not what
10930  // we'd expect
10931 
10933  enum class type
10934  {
10936  item,
10937 
10939  file
10940  };
10941 
10942  attachment() : xml_(), type_(type::item) {}
10943 
10946  {
10947  const auto node = get_node("AttachmentId");
10948  return node ? attachment_id::from_xml_element(*node) : attachment_id();
10949  }
10950 
10952  std::string name() const
10953  {
10954  const auto node = get_node("Name");
10955  return node ? std::string(node->value(), node->value_size()) : "";
10956  }
10957 
10964  std::string get_mime_content() const
10965  {
10966  using rapidxml::internal::compare;
10967 
10968  const auto attachment_node = xml_.root();
10969  if (!attachment_node)
10970  {
10971  return "";
10972  }
10973 
10974  for (auto child = attachment_node->first_node(); child != nullptr;
10975  child = child->next_sibling())
10976  {
10977  for (auto inner = child->first_node(); inner != nullptr;
10978  inner = inner->next_sibling())
10979  {
10980  if (compare(inner->local_name(), inner->local_name_size(),
10981  "MimeContent", strlen("MimeContent")))
10982  {
10983  return std::string(inner->value(), inner->value_size());
10984  }
10985  }
10986  }
10987  return "";
10988  }
10989 
10991  std::string content_type() const
10992  {
10993  const auto node = get_node("ContentType");
10994  return node ? std::string(node->value(), node->value_size()) : "";
10995  }
10996 
11002  std::string content() const
11003  {
11004  const auto node = get_node("Content");
11005  return node ? std::string(node->value(), node->value_size()) : "";
11006  }
11007 
11012  size_t content_size() const
11013  {
11014  const auto node = get_node("Size");
11015  if (!node)
11016  {
11017  return 0U;
11018  }
11019  auto size = std::string(node->value(), node->value_size());
11020  return size.empty() ? 0U : std::stoul(size);
11021  }
11022 
11028  std::string content_id() const
11029  {
11030  const auto node = get_node("ContentId");
11031  return node ? std::string(node->value(), node->value_size()) : "";
11032  }
11033 
11035  bool is_inline() const
11036  {
11037  const auto node = get_node("IsInline");
11038  if (!node)
11039  {
11040  return false;
11041  }
11042  using rapidxml::internal::compare;
11043  return compare(node->value(), node->value_size(), "true",
11044  strlen("true"));
11045  }
11046 
11048  type get_type() const EWS_NOEXCEPT { return type_; }
11049 
11055  size_t write_content_to_file(const std::string& file_path) const
11056  {
11057  if (get_type() == type::item)
11058  {
11059  return 0U;
11060  }
11061 
11062  const auto raw_bytes = internal::base64::decode(content());
11063 
11064  std::ofstream ofstr(file_path, std::ofstream::out | std::ios::binary);
11065  if (!ofstr.is_open())
11066  {
11067  if (file_path.empty())
11068  {
11069  throw exception(
11070  "Could not open file for writing: no file name given");
11071  }
11072 
11073  throw exception("Could not open file for writing: " + file_path);
11074  }
11075 
11076  std::copy(begin(raw_bytes), end(raw_bytes),
11077  std::ostreambuf_iterator<char>(ofstr));
11078  ofstr.close();
11079  return raw_bytes.size();
11080  }
11081 
11083  std::string to_xml() const { return xml_.to_string(); }
11084 
11086  static attachment from_xml_element(const rapidxml::xml_node<>& elem)
11087  {
11088  const auto elem_name =
11089  std::string(elem.local_name(), elem.local_name_size());
11090  check((elem_name == "FileAttachment" || elem_name == "ItemAttachment"),
11091  "Expected <FileAttachment> or <ItemAttachment>");
11092  return attachment(elem_name == "FileAttachment" ? type::file
11093  : type::item,
11094  internal::xml_subtree(elem));
11095  }
11096 
11112  static attachment from_base64(const std::string& content,
11113  std::string content_type, std::string name)
11114  {
11115  using internal::create_node;
11116 
11117  auto obj = attachment();
11118  obj.type_ = type::file;
11119 
11120  auto& attachment_node =
11121  create_node(*obj.xml_.document(), "t:FileAttachment");
11122  create_node(attachment_node, "t:Name", name);
11123  create_node(attachment_node, "t:ContentType", content_type);
11124  create_node(attachment_node, "t:Content", content);
11125  create_node(attachment_node, "t:Size", std::to_string(content.size()));
11126 
11127  return obj;
11128  }
11129 
11144  static attachment from_file(const std::string& file_path,
11145  std::string content_type, std::string name)
11146  {
11147  using internal::create_node;
11148 
11149  // Try open file
11150  std::ifstream ifstr(file_path, std::ifstream::in | std::ios::binary);
11151  if (!ifstr.is_open())
11152  {
11153  throw exception("Could not open file for reading: " + file_path);
11154  }
11155 
11156  // Stop eating newlines in binary mode
11157  ifstr.unsetf(std::ios::skipws);
11158 
11159  // Determine size
11160  ifstr.seekg(0, std::ios::end);
11161  const auto file_size = ifstr.tellg();
11162  ifstr.seekg(0, std::ios::beg);
11163 
11164  // Allocate buffer
11165  auto buffer = std::vector<unsigned char>();
11166  buffer.reserve(
11167  internal::numeric_cast<std::vector<unsigned char>::size_type>(
11168  file_size));
11169 
11170  // Read
11171  buffer.insert(begin(buffer),
11172  std::istream_iterator<unsigned char>(ifstr),
11173  std::istream_iterator<unsigned char>());
11174  ifstr.close();
11175 
11176  // And encode
11177  auto content = internal::base64::encode(buffer);
11178 
11179  auto obj = attachment();
11180  obj.type_ = type::file;
11181 
11182  auto& attachment_node =
11183  create_node(*obj.xml_.document(), "t:FileAttachment");
11184  create_node(attachment_node, "t:Name", name);
11185  create_node(attachment_node, "t:ContentType", content_type);
11186  create_node(attachment_node, "t:Content", content);
11187  create_node(attachment_node, "t:Size", std::to_string(buffer.size()));
11188 
11189  return obj;
11190  }
11191 
11192  static attachment from_item(const item& the_item,
11193  const std::string& name); // implemented
11194  // below
11195 
11196 private:
11197  internal::xml_subtree xml_;
11198  type type_;
11199 
11200  attachment(type&& t, internal::xml_subtree&& xml)
11201  : xml_(std::move(xml)), type_(std::move(t))
11202  {
11203  }
11204 
11205  rapidxml::xml_node<>* get_node(const char* local_name) const
11206  {
11207  using rapidxml::internal::compare;
11208 
11209  const auto attachment_node = xml_.root();
11210  if (!attachment_node)
11211  {
11212  return nullptr;
11213  }
11214 
11215  rapidxml::xml_node<>* node = nullptr;
11216  for (auto child = attachment_node->first_node(); child != nullptr;
11217  child = child->next_sibling())
11218  {
11219  if (compare(child->local_name(), child->local_name_size(),
11220  local_name, strlen(local_name)))
11221  {
11222  node = child;
11223  break;
11224  }
11225  }
11226  return node;
11227  }
11228 };
11229 
11230 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
11231  defined(EWS_HAS_CXX17_STATIC_ASSERT)
11232 static_assert(std::is_default_constructible<attachment>::value);
11233 static_assert(std::is_copy_constructible<attachment>::value);
11234 static_assert(std::is_copy_assignable<attachment>::value);
11235 static_assert(std::is_move_constructible<attachment>::value);
11236 static_assert(std::is_move_assignable<attachment>::value);
11237 #endif
11238 
11239 namespace internal
11240 {
11241  // Parse response class, code, and message text from given response element.
11242  inline response_result
11243  parse_response_class_and_code(const rapidxml::xml_node<>& elem)
11244  {
11245  using rapidxml::internal::compare;
11246 
11247  auto cls = response_class::success;
11248  auto response_class_attr = elem.first_attribute("ResponseClass");
11249  if (compare(response_class_attr->value(),
11250  response_class_attr->value_size(), "Error", 5))
11251  {
11252  cls = response_class::error;
11253  }
11254  else if (compare(response_class_attr->value(),
11255  response_class_attr->value_size(), "Warning", 7))
11256  {
11258  }
11259 
11260  // One thing we can count on is that when the ResponseClass
11261  // attribute is set to Success, ResponseCode will be set to NoError.
11262  // So we only parse the <ResponseCode> element when we have a
11263  // warning or an error.
11264 
11265  auto code = response_code::no_error;
11266  if (cls != response_class::success)
11267  {
11268  auto response_code_elem = elem.first_node_ns(
11269  uri<>::microsoft::messages(), "ResponseCode");
11270  check(response_code_elem, "Expected <ResponseCode> element");
11271  code = str_to_response_code(response_code_elem->value());
11272 
11273  auto message_text_elem =
11274  elem.first_node_ns(uri<>::microsoft::messages(), "MessageText");
11275  if (message_text_elem)
11276  {
11277  return response_result(
11278  cls, code,
11279  std::string(message_text_elem->value(),
11280  message_text_elem->value_size()));
11281  }
11282  }
11283 
11284  return response_result(cls, code);
11285  }
11286 
11287  // Iterate over <Items> array and execute given function for each node.
11288  //
11289  // items_elem: an <Items> element
11290  // func: A callable that is invoked for each item in the response
11291  // message's <Items> array. A const rapidxml::xml_node& is passed to
11292  // that callable.
11293  template <typename Func>
11294  inline void for_each_child_node(const rapidxml::xml_node<>& parent_node,
11295  Func func)
11296  {
11297  for (auto child = parent_node.first_node(); child;
11298  child = child->next_sibling())
11299  {
11300  func(*child);
11301  }
11302  }
11303 
11304  template <typename Func>
11305  inline void for_each_attribute(const rapidxml::xml_node<>& node, Func func)
11306  {
11307  for (auto attrib = node.first_attribute(); attrib;
11308  attrib = attrib->next_attribute())
11309  {
11310  func(*attrib);
11311  }
11312  }
11313 
11317  inline void
11318  check_response_message_for_error(const rapidxml::xml_node<>& element)
11319  {
11320  using rapidxml::internal::compare;
11321 
11322  auto response_class_attr = element.first_attribute("ResponseClass");
11323 
11324  if (compare(response_class_attr->value(),
11325  response_class_attr->value_size(), "Error", 5))
11326  {
11327  auto code = response_code::no_error;
11328 
11329  auto rcode_elem = element.first_node_ns(
11330  uri<>::microsoft::messages(), "ResponseCode");
11331  check(rcode_elem, "Expected <ResponseCode> element");
11332 
11333  code = str_to_response_code(rcode_elem->value());
11334  auto message_text = element.first_node_ns(
11335  uri<>::microsoft::messages(), "MessageText");
11336 
11337  if (message_text)
11338  {
11339  throw exchange_error(code,
11340  std::string(message_text->value(),
11341  message_text->value_size()));
11342  }
11343 
11344  throw exchange_error(code);
11345  }
11346  }
11347 
11348  // Base-class for all response messages
11349  class response_message_base
11350  {
11351  public:
11352  explicit response_message_base(response_result&& res)
11353  : res_(std::move(res))
11354  {
11355  }
11356 
11357  const response_result& result() const EWS_NOEXCEPT { return res_; }
11358 
11359  bool success() const EWS_NOEXCEPT
11360  {
11361  return res_.cls == response_class::success;
11362  }
11363 
11364  private:
11365  response_result res_;
11366  };
11367 
11368  // Base-class for response messages that contain an <Items> array.
11369  //
11370  // The ItemType template parameter denotes the type of all items in the
11371  // returned array. The choice for a compile-time parameter has following
11372  // implications and restrictions:
11373  //
11374  // - Microsoft EWS allows for different types of items in the returned
11375  // array. However, this implementation forces you to only issue
11376  // requests that return only one type of item in a single response at
11377  // a time.
11378  //
11379  // - You need to know the type of the item returned by a request
11380  // up-front at compile time. Microsoft EWS would allow to deal with
11381  // different types of items in a single response dynamically.
11382  template <typename ItemType>
11383  class response_message_with_items : public response_message_base
11384  {
11385  public:
11386  typedef ItemType item_type;
11387 
11388  response_message_with_items(response_result&& res,
11389  std::vector<item_type>&& items)
11390  : response_message_base(std::move(res)), items_(std::move(items))
11391  {
11392  }
11393 
11394  const std::vector<item_type>& items() const EWS_NOEXCEPT
11395  {
11396  return items_;
11397  }
11398 
11399  private:
11400  std::vector<item_type> items_;
11401  };
11402 
11403  class create_folder_response_message final
11404  : public response_message_with_items<folder_id>
11405  {
11406  public:
11407  // implemented below
11408  static create_folder_response_message parse(http_response&&);
11409 
11410  private:
11411  create_folder_response_message(response_result&& res,
11412  std::vector<folder_id>&& items)
11413  : response_message_with_items<folder_id>(std::move(res),
11414  std::move(items))
11415  {
11416  }
11417  };
11418 
11419  class create_item_response_message final
11420  : public response_message_with_items<item_id>
11421  {
11422  public:
11423  // implemented below
11424  static create_item_response_message parse(http_response&&);
11425 
11426  private:
11427  create_item_response_message(response_result&& res,
11428  std::vector<item_id>&& items)
11429  : response_message_with_items<item_id>(std::move(res),
11430  std::move(items))
11431  {
11432  }
11433  };
11434 
11435  class find_folder_response_message final
11436  : public response_message_with_items<folder_id>
11437  {
11438  public:
11439  // implemented below
11440  static find_folder_response_message parse(http_response&&);
11441 
11442  private:
11443  find_folder_response_message(response_result&& res,
11444  std::vector<folder_id>&& items)
11445  : response_message_with_items<folder_id>(std::move(res),
11446  std::move(items))
11447  {
11448  }
11449  };
11450 
11451  class find_item_response_message final
11452  : public response_message_with_items<item_id>
11453  {
11454  public:
11455  // implemented below
11456  static find_item_response_message parse(http_response&&);
11457 
11458  private:
11459  find_item_response_message(response_result&& res,
11460  std::vector<item_id>&& items)
11461  : response_message_with_items<item_id>(std::move(res),
11462  std::move(items))
11463  {
11464  }
11465  };
11466 
11467  class find_calendar_item_response_message final
11468  : public response_message_with_items<calendar_item>
11469  {
11470  public:
11471  // implemented below
11472  static find_calendar_item_response_message parse(http_response&&);
11473 
11474  private:
11475  find_calendar_item_response_message(response_result&& res,
11476  std::vector<calendar_item>&& items)
11477  : response_message_with_items<calendar_item>(std::move(res),
11478  std::move(items))
11479  {
11480  }
11481  };
11482 
11483  class update_item_response_message final
11484  : public response_message_with_items<item_id>
11485  {
11486  public:
11487  // implemented below
11488  static update_item_response_message parse(http_response&&);
11489 
11490  private:
11491  update_item_response_message(response_result&& res,
11492  std::vector<item_id>&& items)
11493  : response_message_with_items<item_id>(std::move(res),
11494  std::move(items))
11495  {
11496  }
11497  };
11498 
11499  class update_folder_response_message final
11500  : public response_message_with_items<folder_id>
11501  {
11502  public:
11503  // implemented below
11504  static update_folder_response_message parse(http_response&&);
11505 
11506  private:
11507  update_folder_response_message(response_result&& res,
11508  std::vector<folder_id>&& items)
11509  : response_message_with_items<folder_id>(std::move(res),
11510  std::move(items))
11511  {
11512  }
11513  };
11514 
11515  class get_folder_response_message final
11516  : public response_message_with_items<folder>
11517  {
11518  public:
11519  // implemented below
11520  static get_folder_response_message parse(http_response&&);
11521 
11522  private:
11523  get_folder_response_message(response_result&& res,
11524  std::vector<folder>&& items)
11525  : response_message_with_items<folder>(std::move(res),
11526  std::move(items))
11527  {
11528  }
11529  };
11530 
11531  class folder_response_message final
11532  {
11533  public:
11534  typedef std::tuple<response_class, response_code, std::vector<folder>>
11535  response_message;
11536 
11537  std::vector<folder> items() const
11538  {
11539  std::vector<folder> items;
11540  items.reserve(messages_.size()); // Seems like there is always one
11541  // item per message
11542  for (const auto& msg : messages_)
11543  {
11544  const auto& msg_items = std::get<2>(msg);
11545  std::copy(begin(msg_items), end(msg_items),
11546  std::back_inserter(items));
11547  }
11548  return items;
11549  }
11550 
11551  bool success() const
11552  {
11553  // Consequently, this means we're aborting here because of a
11554  // warning. Is this desired? Don't think so. At least it is
11555  // consistent with response_message_base::success().
11556 
11557  return std::all_of(begin(messages_), end(messages_),
11558  [](const response_message& msg) {
11559  return std::get<0>(msg) ==
11561  });
11562  }
11563 
11564  response_code first_error_or_warning() const
11565  {
11566  auto it = std::find_if_not(begin(messages_), end(messages_),
11567  [](const response_message& msg) {
11568  return std::get<0>(msg) ==
11570  });
11571  return it == end(messages_) ? response_code::no_error
11572  : std::get<1>(*it);
11573  }
11574 
11575  // implemented below
11576  static folder_response_message parse(http_response&&);
11577 
11578  private:
11579  explicit folder_response_message(
11580  std::vector<response_message>&& messages)
11581  : messages_(std::move(messages))
11582  {
11583  }
11584 
11585  std::vector<response_message> messages_;
11586  };
11587 
11588  class get_room_lists_response_message final
11589  : public response_message_with_items<mailbox>
11590  {
11591  public:
11592  // implemented below
11593  static get_room_lists_response_message parse(http_response&&);
11594 
11595  private:
11596  get_room_lists_response_message(response_result&& res,
11597  std::vector<mailbox>&& items)
11598  : response_message_with_items<mailbox>(std::move(res),
11599  std::move(items))
11600  {
11601  }
11602  };
11603 
11604  class get_rooms_response_message final
11605  : public response_message_with_items<mailbox>
11606  {
11607  public:
11608  // implemented below
11609  static get_rooms_response_message parse(http_response&&);
11610 
11611  private:
11612  get_rooms_response_message(response_result&& res,
11613  std::vector<mailbox>&& items)
11614  : response_message_with_items<mailbox>(std::move(res),
11615  std::move(items))
11616  {
11617  }
11618  };
11619 
11620  template <typename ItemType>
11621  class get_item_response_message final
11622  : public response_message_with_items<ItemType>
11623  {
11624  public:
11625  // implemented below
11626  static get_item_response_message parse(http_response&&);
11627 
11628  private:
11629  get_item_response_message(response_result&& res,
11630  std::vector<ItemType>&& items)
11631  : response_message_with_items<ItemType>(std::move(res),
11632  std::move(items))
11633  {
11634  }
11635  };
11636 
11637  template <typename IdType> class response_message_with_ids
11638  {
11639  public:
11640  typedef IdType id_type;
11641  typedef std::tuple<response_class, response_code, std::vector<id_type>>
11642  response_message;
11643 
11644  explicit response_message_with_ids(
11645  std::vector<response_message>&& messages)
11646  : messages_(std::move(messages))
11647  {
11648  }
11649 
11650  std::vector<id_type> items() const
11651  {
11652  std::vector<id_type> items;
11653  items.reserve(messages_.size()); // Seems like there is always one
11654  // item per message
11655  for (const auto& msg : messages_)
11656  {
11657  const auto& msg_items = std::get<2>(msg);
11658  std::copy(begin(msg_items), end(msg_items),
11659  std::back_inserter(items));
11660  }
11661  return items;
11662  }
11663 
11664  bool success() const
11665  {
11666  // Consequently, this means we're aborting here because of a
11667  // warning. Is this desired? Don't think so. At least it is
11668  // consistent with response_message_base::success().
11669 
11670  return std::all_of(begin(messages_), end(messages_),
11671  [](const response_message& msg) {
11672  return std::get<0>(msg) ==
11674  });
11675  }
11676 
11677  response_code first_error_or_warning() const
11678  {
11679  auto it = std::find_if_not(begin(messages_), end(messages_),
11680  [](const response_message& msg) {
11681  return std::get<0>(msg) ==
11683  });
11684  return it == end(messages_) ? response_code::no_error
11685  : std::get<1>(*it);
11686  }
11687 
11688  private:
11689  std::vector<response_message> messages_;
11690  };
11691 
11692  class move_item_response_message final
11693  : public response_message_with_ids<item_id>
11694  {
11695  public:
11696  // implemented below
11697  static move_item_response_message parse(http_response&&);
11698 
11699  private:
11700  move_item_response_message(std::vector<response_message>&& items)
11701  : response_message_with_ids<item_id>(std::move(items))
11702  {
11703  }
11704  };
11705 
11706  class move_folder_response_message final
11707  : public response_message_with_ids<folder_id>
11708  {
11709  public:
11710  // implemented below
11711  static move_folder_response_message parse(http_response&&);
11712 
11713  private:
11714  move_folder_response_message(std::vector<response_message>&& items)
11715  : response_message_with_ids<folder_id>(std::move(items))
11716  {
11717  }
11718  };
11719 
11720  template <typename ItemType> class item_response_messages final
11721  {
11722  public:
11723  typedef ItemType item_type;
11724  typedef std::tuple<response_class, response_code,
11725  std::vector<item_type>>
11726  response_message;
11727 
11728  std::vector<item_type> items() const
11729  {
11730  std::vector<item_type> items;
11731  items.reserve(messages_.size()); // Seems like there is always one
11732  // item per message
11733  for (const auto& msg : messages_)
11734  {
11735  const auto& msg_items = std::get<2>(msg);
11736  std::copy(begin(msg_items), end(msg_items),
11737  std::back_inserter(items));
11738  }
11739  return items;
11740  }
11741 
11742  bool success() const
11743  {
11744  // Consequently, this means we're aborting here because of a
11745  // warning. Is this desired? Don't think so. At least it is
11746  // consistent with response_message_base::success().
11747 
11748  return std::all_of(begin(messages_), end(messages_),
11749  [](const response_message& msg) {
11750  return std::get<0>(msg) ==
11752  });
11753  }
11754 
11755  response_code first_error_or_warning() const
11756  {
11757  auto it = std::find_if_not(begin(messages_), end(messages_),
11758  [](const response_message& msg) {
11759  return std::get<0>(msg) ==
11761  });
11762  return it == end(messages_) ? response_code::no_error
11763  : std::get<1>(*it);
11764  }
11765 
11766  // implemented below
11767  static item_response_messages parse(http_response&&);
11768 
11769  private:
11770  explicit item_response_messages(
11771  std::vector<response_message>&& messages)
11772  : messages_(std::move(messages))
11773  {
11774  }
11775 
11776  std::vector<response_message> messages_;
11777  };
11778 
11779  class delegate_response_message : public response_message_base
11780  {
11781  public:
11782  const std::vector<delegate_user>& get_delegates() const EWS_NOEXCEPT
11783  {
11784  return delegates_;
11785  }
11786 
11787  protected:
11788  delegate_response_message(response_result&& res,
11789  std::vector<delegate_user>&& delegates)
11790  : response_message_base(std::move(res)),
11791  delegates_(std::move(delegates))
11792  {
11793  }
11794 
11795  // defined below
11796  static std::vector<delegate_user>
11797  parse_users(const rapidxml::xml_node<>& response_element);
11798 
11799  std::vector<delegate_user> delegates_;
11800  };
11801 
11802  class add_delegate_response_message final : public delegate_response_message
11803  {
11804  public:
11805  // defined below
11806  static add_delegate_response_message parse(http_response&&);
11807 
11808  private:
11809  add_delegate_response_message(response_result&& res,
11810  std::vector<delegate_user>&& delegates)
11811  : delegate_response_message(std::move(res), std::move(delegates))
11812  {
11813  }
11814  };
11815 
11816  class get_delegate_response_message final : public delegate_response_message
11817  {
11818  public:
11819  // defined below
11820  static get_delegate_response_message parse(http_response&&);
11821 
11822  private:
11823  get_delegate_response_message(response_result&& res,
11824  std::vector<delegate_user>&& delegates)
11825  : delegate_response_message(std::move(res), std::move(delegates))
11826  {
11827  }
11828  };
11829 
11830  class remove_delegate_response_message final : public response_message_base
11831  {
11832  public:
11833  // defined below
11834  static remove_delegate_response_message parse(http_response&&);
11835 
11836  private:
11837  explicit remove_delegate_response_message(response_result&& res)
11838  : response_message_base(std::move(res))
11839  {
11840  }
11841  };
11842 
11843  class resolve_names_response_message final : public response_message_base
11844  {
11845  public:
11846  // defined below
11847  static resolve_names_response_message parse(http_response&& response);
11848  const resolution_set& resolutions() const EWS_NOEXCEPT
11849  {
11850  return resolutions_;
11851  }
11852 
11853  private:
11854  resolve_names_response_message(response_result&& res,
11855  resolution_set&& rset)
11856  : response_message_base(std::move(res)),
11857  resolutions_(std::move(rset))
11858  {
11859  }
11860 
11861  resolution_set resolutions_;
11862  };
11863 
11864 #ifdef EWS_HAS_VARIANT
11865  class subscribe_response_message final : public response_message_base
11866  {
11867  public:
11868  // defined below
11869  static subscribe_response_message parse(http_response&& response);
11870  const subscription_information& information() const EWS_NOEXCEPT
11871  {
11872  return information_;
11873  }
11874 
11875  private:
11876  subscribe_response_message(response_result&& res,
11877  subscription_information&& info)
11878  : response_message_base(std::move(res)),
11879  information_(std::move(info))
11880  {
11881  }
11882 
11883  subscription_information information_;
11884  };
11885 
11886  class unsubscribe_response_message final : public response_message_base
11887  {
11888  public:
11889  // defined below
11890  static unsubscribe_response_message parse(http_response&& response);
11891 
11892  private:
11893  unsubscribe_response_message(response_result&& res)
11894  : response_message_base(std::move(res))
11895  {
11896  }
11897  };
11898 
11899  class get_events_response_message final : public response_message_base
11900  {
11901  public:
11902  // defined below
11903  static get_events_response_message parse(http_response&& response);
11904  const notification& get_notification() const EWS_NOEXCEPT
11905  {
11906  return notification_;
11907  }
11908 
11909  private:
11910  get_events_response_message(response_result&& res, notification&& n)
11911  : response_message_base(std::move(res)), notification_(std::move(n))
11912  {
11913  }
11914 
11915  notification notification_;
11916  };
11917 #endif
11918 
11919  class create_attachment_response_message final
11920  : public response_message_base
11921  {
11922  public:
11923  static create_attachment_response_message
11924  parse(http_response&& response)
11925  {
11926  const auto doc = parse_response(std::move(response));
11927  auto elem =
11928  get_element_by_qname(*doc, "CreateAttachmentResponseMessage",
11929  uri<>::microsoft::messages());
11930 
11931  check(elem, "Expected <CreateAttachmentResponseMessage>");
11932 
11933  auto result = parse_response_class_and_code(*elem);
11934 
11935  auto attachments_element = elem->first_node_ns(
11936  uri<>::microsoft::messages(), "Attachments");
11937  check(attachments_element, "Expected <Attachments> element");
11938 
11939  auto ids = std::vector<attachment_id>();
11940  for (auto attachment_elem = attachments_element->first_node();
11941  attachment_elem;
11942  attachment_elem = attachment_elem->next_sibling())
11943  {
11944  auto attachment_id_elem = attachment_elem->first_node_ns(
11945  uri<>::microsoft::types(), "AttachmentId");
11946  check(attachment_id_elem,
11947  "Expected <AttachmentId> in response");
11948  ids.emplace_back(
11949  attachment_id::from_xml_element(*attachment_id_elem));
11950  }
11951  return create_attachment_response_message(std::move(result),
11952  std::move(ids));
11953  }
11954 
11955  const std::vector<attachment_id>& attachment_ids() const EWS_NOEXCEPT
11956  {
11957  return ids_;
11958  }
11959 
11960  private:
11961  create_attachment_response_message(
11962  response_result&& res, std::vector<attachment_id>&& attachment_ids)
11963  : response_message_base(std::move(res)),
11964  ids_(std::move(attachment_ids))
11965  {
11966  }
11967 
11968  std::vector<attachment_id> ids_;
11969  };
11970 
11971  class get_attachment_response_message final : public response_message_base
11972  {
11973  public:
11974  static get_attachment_response_message parse(http_response&& response)
11975  {
11976  const auto doc = parse_response(std::move(response));
11977  auto elem =
11978  get_element_by_qname(*doc, "GetAttachmentResponseMessage",
11979  uri<>::microsoft::messages());
11980 
11981  check(elem, "Expected <GetAttachmentResponseMessage>");
11982 
11983  auto result = parse_response_class_and_code(*elem);
11984 
11985  auto attachments_element = elem->first_node_ns(
11986  uri<>::microsoft::messages(), "Attachments");
11987  check(attachments_element, "Expected <Attachments> element");
11988  auto attachments = std::vector<attachment>();
11989  for (auto attachment_elem = attachments_element->first_node();
11990  attachment_elem;
11991  attachment_elem = attachment_elem->next_sibling())
11992  {
11993  attachments.emplace_back(
11994  attachment::from_xml_element(*attachment_elem));
11995  }
11996  return get_attachment_response_message(std::move(result),
11997  std::move(attachments));
11998  }
11999 
12000  const std::vector<attachment>& attachments() const EWS_NOEXCEPT
12001  {
12002  return attachments_;
12003  }
12004 
12005  private:
12006  get_attachment_response_message(response_result&& res,
12007  std::vector<attachment>&& attachments)
12008  : response_message_base(std::move(res)),
12009  attachments_(std::move(attachments))
12010  {
12011  }
12012 
12013  std::vector<attachment> attachments_;
12014  };
12015 
12016  class send_item_response_message final : public response_message_base
12017  {
12018  public:
12019  static send_item_response_message parse(http_response&& response)
12020  {
12021  const auto doc = parse_response(std::move(response));
12022  auto elem = get_element_by_qname(*doc, "SendItemResponseMessage",
12023  uri<>::microsoft::messages());
12024 
12025  check(elem, "Expected <SendItemResponseMessage>");
12026  auto result = parse_response_class_and_code(*elem);
12027  return send_item_response_message(std::move(result));
12028  }
12029 
12030  private:
12031  explicit send_item_response_message(response_result&& res)
12032  : response_message_base(std::move(res))
12033  {
12034  }
12035  };
12036 
12037  class delete_folder_response_message final : public response_message_base
12038  {
12039  public:
12040  static delete_folder_response_message parse(http_response&& response)
12041  {
12042  const auto doc = parse_response(std::move(response));
12043  auto elem =
12044  get_element_by_qname(*doc, "DeleteFolderResponseMessage",
12045  uri<>::microsoft::messages());
12046  auto result = parse_response_class_and_code(*elem);
12047  check(elem, "Expected <DeleteFolderResponseMessage>");
12048  return delete_folder_response_message(std::move(result));
12049  }
12050 
12051  private:
12052  explicit delete_folder_response_message(response_result&& res)
12053  : response_message_base(std::move(res))
12054  {
12055  }
12056  };
12057 
12058  class delete_item_response_message final : public response_message_base
12059  {
12060  public:
12061  static delete_item_response_message parse(http_response&& response)
12062  {
12063  const auto doc = parse_response(std::move(response));
12064  auto elem = get_element_by_qname(*doc, "DeleteItemResponseMessage",
12065  uri<>::microsoft::messages());
12066  check(elem, "Expected <DeleteItemResponseMessage>");
12067  auto result = parse_response_class_and_code(*elem);
12068  return delete_item_response_message(std::move(result));
12069  }
12070 
12071  private:
12072  explicit delete_item_response_message(response_result&& res)
12073  : response_message_base(std::move(res))
12074  {
12075  }
12076  };
12077 
12078  class delete_attachment_response_message final
12079  : public response_message_base
12080  {
12081  public:
12082  static delete_attachment_response_message
12083  parse(http_response&& response)
12084  {
12085  const auto doc = parse_response(std::move(response));
12086  auto elem =
12087  get_element_by_qname(*doc, "DeleteAttachmentResponseMessage",
12088  uri<>::microsoft::messages());
12089 
12090  check(elem, "Expected <DeleteAttachmentResponseMessage>");
12091  auto result = parse_response_class_and_code(*elem);
12092 
12093  auto root_item_id = item_id();
12094  auto root_item_id_elem =
12095  elem->first_node_ns(uri<>::microsoft::messages(), "RootItemId");
12096  if (root_item_id_elem)
12097  {
12098  auto id_attr = root_item_id_elem->first_attribute("RootItemId");
12099  check(id_attr, "Expected RootItemId attribute");
12100  auto id = std::string(id_attr->value(), id_attr->value_size());
12101 
12102  auto change_key_attr =
12103  root_item_id_elem->first_attribute("RootItemChangeKey");
12104  check(change_key_attr, "Expected RootItemChangeKey attribute");
12105  auto change_key = std::string(change_key_attr->value(),
12106  change_key_attr->value_size());
12107 
12108  root_item_id = item_id(std::move(id), std::move(change_key));
12109  }
12110 
12111  return delete_attachment_response_message(std::move(result),
12112  std::move(root_item_id));
12113  }
12114 
12115  item_id get_root_item_id() const { return root_item_id_; }
12116 
12117  private:
12118  delete_attachment_response_message(response_result&& res,
12119  item_id&& root_item_id)
12120  : response_message_base(std::move(res)),
12121  root_item_id_(std::move(root_item_id))
12122  {
12123  }
12124 
12125  item_id root_item_id_;
12126  };
12127 } // namespace internal
12128 
12130  : public internal::response_message_base
12131 {
12132 public:
12133 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
12134  // implemented below
12135  static sync_folder_hierarchy_result parse(internal::http_response&&);
12136 #endif
12137 
12138  const std::string& get_sync_state() const EWS_NOEXCEPT
12139  {
12140  return sync_state_;
12141  }
12142 
12143  const std::vector<folder>& get_created_folders() const EWS_NOEXCEPT
12144  {
12145  return created_folders_;
12146  }
12147 
12148  const std::vector<folder>& get_updated_folders() const EWS_NOEXCEPT
12149  {
12150  return updated_folders_;
12151  }
12152 
12153  const std::vector<folder_id>& get_deleted_folder_ids() const EWS_NOEXCEPT
12154  {
12155  return deleted_folder_ids_;
12156  }
12157 
12158  bool get_includes_last_folder_in_range() const EWS_NOEXCEPT
12159  {
12160  return includes_last_folder_in_range_;
12161  }
12162 
12163 private:
12164  explicit sync_folder_hierarchy_result(internal::response_result&& res)
12165  : response_message_base(std::move(res)), sync_state_(),
12166  created_folders_(), updated_folders_(), deleted_folder_ids_(),
12167  includes_last_folder_in_range_(false)
12168  {
12169  }
12170 
12171  std::string sync_state_;
12172  std::vector<folder> created_folders_;
12173  std::vector<folder> updated_folders_;
12174  std::vector<folder_id> deleted_folder_ids_;
12175  bool includes_last_folder_in_range_;
12176 };
12177 
12178 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12179  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12180 static_assert(
12181  !std::is_default_constructible<sync_folder_hierarchy_result>::value, "");
12182 static_assert(std::is_copy_constructible<sync_folder_hierarchy_result>::value);
12183 static_assert(std::is_copy_assignable<sync_folder_hierarchy_result>::value);
12184 static_assert(std::is_move_constructible<sync_folder_hierarchy_result>::value);
12185 static_assert(std::is_move_assignable<sync_folder_hierarchy_result>::value);
12186 #endif
12187 
12188 class sync_folder_items_result final : public internal::response_message_base
12189 {
12190 public:
12191 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
12192  // implemented below
12193  static sync_folder_items_result parse(internal::http_response&&);
12194 #endif
12195 
12196  const std::string& get_sync_state() const EWS_NOEXCEPT
12197  {
12198  return sync_state_;
12199  }
12200 
12201  const std::vector<item_id>& get_created_items() const EWS_NOEXCEPT
12202  {
12203  return created_items_;
12204  }
12205 
12206  const std::vector<item_id>& get_updated_items() const EWS_NOEXCEPT
12207  {
12208  return updated_items_;
12209  }
12210 
12211  const std::vector<item_id>& get_deleted_items() const EWS_NOEXCEPT
12212  {
12213  return deleted_items_;
12214  }
12215 
12216  const std::vector<std::pair<item_id, bool>>&
12217  get_read_flag_changed() const EWS_NOEXCEPT
12218  {
12219  return read_flag_changed_;
12220  }
12221 
12222  bool get_includes_last_item_in_range() const EWS_NOEXCEPT
12223  {
12224  return includes_last_item_in_range_;
12225  }
12226 
12227 private:
12228  explicit sync_folder_items_result(internal::response_result&& res)
12229  : response_message_base(std::move(res)), sync_state_(),
12230  created_items_(), updated_items_(), deleted_items_(),
12231  read_flag_changed_(), includes_last_item_in_range_(false)
12232  {
12233  }
12234 
12235  std::string sync_state_;
12236  std::vector<item_id> created_items_;
12237  std::vector<item_id> updated_items_;
12238  std::vector<item_id> deleted_items_;
12239  std::vector<std::pair<item_id, bool>> read_flag_changed_;
12240  bool includes_last_item_in_range_;
12241 };
12242 
12243 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12244  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12245 static_assert(!std::is_default_constructible<sync_folder_items_result>::value,
12246  "");
12247 static_assert(std::is_copy_constructible<sync_folder_items_result>::value);
12248 static_assert(std::is_copy_assignable<sync_folder_items_result>::value);
12249 static_assert(std::is_move_constructible<sync_folder_items_result>::value);
12250 static_assert(std::is_move_assignable<sync_folder_items_result>::value);
12251 #endif
12252 
12290 class date_time final
12291 {
12292 public:
12293 #ifdef EWS_HAS_DEFAULT_AND_DELETE
12294  date_time() = default;
12295 #else
12296  date_time() {}
12297 #endif
12298 
12299  date_time(std::string str) // intentionally not explicit
12300  : val_(std::move(str))
12301  {
12302  }
12303 
12304  const std::string& to_string() const EWS_NOEXCEPT { return val_; }
12305 
12306  inline bool is_set() const EWS_NOEXCEPT { return !val_.empty(); }
12307 
12314  time_t to_epoch() const
12315  {
12316  if (!is_set())
12317  {
12318  throw exception("to_epoch called on empty date_time");
12319  }
12320 
12321  bool local_time = false;
12322  time_t offset = 0U; // Seconds east of UTC
12323 
12324  int y, M, d, h, m, tzh, tzm;
12325  tzh = tzm = 0;
12326  float s;
12327  char tzo;
12328 #if _MSC_VER == 1700 || _MSC_VER == 1800
12329  auto res = sscanf_s(val_.c_str(), "%d-%d-%dT%d:%d:%f%c%d:%d", &y, &M,
12330  &d, &h, &m, &s, &tzo, 1, &tzh, &tzm);
12331 #else
12332  auto res = sscanf(val_.c_str(), "%d-%d-%dT%d:%d:%f%c%d:%d", &y, &M, &d,
12333  &h, &m, &s, &tzo, &tzh, &tzm);
12334 #endif
12335  if (res == EOF)
12336  {
12337  throw exception("sscanf failed");
12338  }
12339  else if (res == 6)
12340  {
12341  // without 'Z', interpreted as local time
12342  local_time = true;
12343  }
12344  else if (res == 7)
12345  {
12346  if (tzo == 'Z')
12347  {
12348  // UTC offset: 0
12349  }
12350  else
12351  {
12352  throw exception("to_epoch: unexpected character at match 7");
12353  }
12354  }
12355  else if (res == 9)
12356  {
12357  if (tzo == '-')
12358  {
12359  offset = (tzh * 60 * 60) + (tzm * 60);
12360  }
12361  else if (tzo == '+')
12362  {
12363  offset = ((tzh * 60 * 60) + (tzm * 60)) * (-1);
12364  }
12365  else
12366  {
12367  throw exception("to_epoch: unexpected character at match 7");
12368  }
12369  }
12370  else if (res < 6) // Whats that? Error case?
12371  {
12372  throw exception("to_epoch: could not parse string");
12373  }
12374 
12375  // The following broken-down time struct is always in local time.
12376  tm t;
12377  memset(&t, 0, sizeof(struct tm));
12378  t.tm_year = y - 1900; // Year since 1900
12379  t.tm_mon = M - 1; // 0-11
12380  t.tm_mday = d; // 1-31
12381  t.tm_hour = h; // 0-23
12382  t.tm_min = m; // 0-59
12383  t.tm_sec = static_cast<int>(s); // 0 - 61
12384  t.tm_isdst = -1; // Tells mktime() to determine if DST is in effect
12385  // using system's TZ infos
12386 
12387  time_t epoch = 0L;
12388  if (offset == 0)
12389  {
12390  epoch = mktime(&t);
12391  if (epoch == -1L)
12392  {
12393  throw exception(
12394  "mktime: time cannot be represented as calendar time");
12395  }
12396  }
12397  else
12398  {
12399 #ifdef _WIN32
12400  // timegm is a nonstandard GNU extension that is also present on
12401  // some BSDs including macOS
12402  epoch = _mkgmtime(&t);
12403 #else
12404  epoch = timegm(&t);
12405 #endif
12406  if (epoch == -1L)
12407  {
12408  throw exception(
12409  "timegm: time cannot be represented as calendar time");
12410  }
12411  }
12412  const auto bias =
12413  local_time ? 0L : (offset == 0L ? utc_offset(&epoch) : offset);
12414  return epoch + bias;
12415  }
12416 
12427  static date_time from_epoch(time_t epoch)
12428  {
12429 #ifdef _WIN32
12430  tm result;
12431  gmtime_s(&result, &epoch);
12432  tm* t = &result;
12433 #else
12434  tm result;
12435  auto t = gmtime_r(&epoch, &result);
12436 #endif
12437  char buf[21];
12438  auto len = strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%SZ", t);
12439  if (len == 0)
12440  {
12441  throw exception("strftime failed");
12442  }
12443  return date_time(buf);
12444  }
12445 
12446 private:
12447  // Compute the offset between local time and UTC in seconds for a given
12448  // time point. If time point is the null pointer, the current offset is
12449  // returned. Note: this implementation might not work when DST changes
12450  // during the call.
12451  static time_t utc_offset(const time_t* timepoint)
12452  {
12453  time_t now;
12454  if (timepoint == nullptr)
12455  {
12456  now = time(nullptr);
12457  }
12458  else
12459  {
12460  now = *timepoint;
12461  }
12462 
12463 #ifdef _WIN32
12464  tm gmtime_result;
12465  auto gmtime_error = gmtime_s(&gmtime_result, &now);
12466  if (gmtime_error)
12467  {
12468  throw std::runtime_error("Invalid argument to gmtime_s");
12469  }
12470  tm* utc_time = &gmtime_result;
12471 #else
12472  tm result;
12473  auto utc_time = gmtime_r(&now, &result);
12474 #endif
12475  utc_time->tm_isdst = -1;
12476  const auto utc_epoch = mktime(utc_time);
12477 
12478 #ifdef _WIN32
12479  tm localtime_result;
12480  auto localtime_error = localtime_s(&localtime_result, &now);
12481  if (localtime_error)
12482  {
12483  throw std::runtime_error("Invalid argument to localtime_s");
12484  }
12485  tm* local_time = &localtime_result;
12486 #else
12487  auto local_time = localtime_r(&now, &result);
12488 #endif
12489  local_time->tm_isdst = -1;
12490  const auto local_epoch = mktime(local_time);
12491 
12492  return local_epoch - utc_epoch;
12493  }
12494 
12495  friend bool operator==(const date_time&, const date_time&);
12496  std::string val_;
12497 };
12498 
12499 inline bool operator==(const date_time& lhs, const date_time& rhs)
12500 {
12501  return lhs.val_ == rhs.val_;
12502 }
12503 
12504 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12505  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12506 static_assert(std::is_default_constructible<date_time>::value);
12507 static_assert(std::is_copy_constructible<date_time>::value);
12508 static_assert(std::is_copy_assignable<date_time>::value);
12509 static_assert(std::is_move_constructible<date_time>::value);
12510 static_assert(std::is_move_assignable<date_time>::value);
12511 #endif
12512 
12517 typedef date_time date;
12518 
12535 class duration final
12536 {
12537 public:
12538 #ifdef EWS_HAS_DEFAULT_AND_DELETE
12539  duration() = default;
12540 #else
12541  duration() {}
12542 #endif
12543 
12544  duration(std::string str) // intentionally not explicit
12545  : val_(std::move(str))
12546  {
12547  }
12548 
12549  const std::string& to_string() const EWS_NOEXCEPT { return val_; }
12550 
12551  inline bool is_set() const EWS_NOEXCEPT { return !val_.empty(); }
12552 
12553 private:
12554  friend bool operator==(const duration&, const duration&);
12555  std::string val_;
12556 };
12557 
12558 inline bool operator==(const duration& lhs, const duration& rhs)
12559 {
12560  return lhs.val_ == rhs.val_;
12561 }
12562 
12563 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12564  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12565 static_assert(std::is_default_constructible<duration>::value);
12566 static_assert(std::is_copy_constructible<duration>::value);
12567 static_assert(std::is_copy_assignable<duration>::value);
12568 static_assert(std::is_move_constructible<duration>::value);
12569 static_assert(std::is_move_assignable<duration>::value);
12570 #endif
12571 
12573 enum class body_type
12574 {
12581  best,
12582 
12584  plain_text,
12585 
12587  html
12588 };
12589 
12590 namespace internal
12591 {
12592  inline std::string body_type_str(body_type type)
12593  {
12594  switch (type)
12595  {
12596  case body_type::best:
12597  return "Best";
12598  case body_type::plain_text:
12599  return "Text";
12600  case body_type::html:
12601  return "HTML";
12602  default:
12603  throw exception("Bad enum value");
12604  }
12605  }
12606 } // namespace internal
12607 
12611 class body final
12612 {
12613 public:
12615  body() : content_(), type_(body_type::plain_text), is_truncated_(false) {}
12616 
12618  explicit body(std::string content, body_type type = body_type::plain_text)
12619  : content_(std::move(content)), type_(type), is_truncated_(false)
12620  {
12621  }
12622 
12623  body_type type() const EWS_NOEXCEPT { return type_; }
12624 
12625  void set_type(body_type type) { type_ = type; }
12626 
12627  bool is_truncated() const EWS_NOEXCEPT { return is_truncated_; }
12628 
12629  void set_truncated(bool truncated) { is_truncated_ = truncated; }
12630 
12631  const std::string& content() const EWS_NOEXCEPT { return content_; }
12632 
12633  void set_content(std::string content) { content_ = std::move(content); }
12634 
12635  std::string to_xml() const
12636  {
12637  // FIXME: what about IsTruncated attribute?
12638  static const auto cdata_beg = std::string("<![CDATA[");
12639  static const auto cdata_end = std::string("]]>");
12640 
12641  std::stringstream sstr;
12642  sstr << "<t:Body BodyType=\"" << internal::body_type_str(type());
12643  sstr << "\">";
12644  if (type() == body_type::html &&
12645  !(content_.compare(0, cdata_beg.length(), cdata_beg) == 0))
12646  {
12647  sstr << cdata_beg << content_ << cdata_end;
12648  }
12649  else
12650  {
12651  sstr << internal::escape(content_);
12652  }
12653  sstr << "</t:Body>";
12654  return sstr.str();
12655  }
12656 
12657 private:
12658  std::string content_;
12659  body_type type_;
12660  bool is_truncated_;
12661 };
12662 
12663 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12664  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12665 static_assert(std::is_default_constructible<body>::value);
12666 static_assert(std::is_copy_constructible<body>::value);
12667 static_assert(std::is_copy_assignable<body>::value);
12668 static_assert(std::is_move_constructible<body>::value);
12669 static_assert(std::is_move_assignable<body>::value);
12670 #endif
12671 
12677 class mime_content final
12678 {
12679 public:
12680 #ifdef EWS_HAS_DEFAULT_AND_DELETE
12681  mime_content() = default;
12682 #else
12683  mime_content() {}
12684 #endif
12685 
12687  mime_content(std::string charset, const char* const ptr, size_t len)
12688  : charset_(std::move(charset)), bytearray_(ptr, ptr + len)
12689  {
12690  }
12691 
12693  const std::string& character_set() const EWS_NOEXCEPT { return charset_; }
12694 
12696  const char* bytes() const EWS_NOEXCEPT { return bytearray_.data(); }
12697 
12698  size_t len_bytes() const EWS_NOEXCEPT { return bytearray_.size(); }
12699 
12705  bool none() const EWS_NOEXCEPT { return len_bytes() == 0U; }
12706 
12707 private:
12708  std::string charset_;
12709  std::vector<char> bytearray_;
12710 };
12711 
12712 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12713  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12714 static_assert(std::is_default_constructible<mime_content>::value);
12715 static_assert(std::is_copy_constructible<mime_content>::value);
12716 static_assert(std::is_copy_assignable<mime_content>::value);
12717 static_assert(std::is_move_constructible<mime_content>::value);
12718 static_assert(std::is_move_assignable<mime_content>::value);
12719 #endif
12720 
12727 class attendee final
12728 {
12729 public:
12730  attendee(mailbox address, response_type type, date_time last_response_time)
12731  : mailbox_(std::move(address)), response_type_(std::move(type)),
12732  last_response_time_(std::move(last_response_time))
12733  {
12734  }
12735 
12736  explicit attendee(mailbox address)
12737  : mailbox_(std::move(address)), response_type_(response_type::unknown),
12738  last_response_time_()
12739  {
12740  }
12741 
12743  const mailbox& get_mailbox() const EWS_NOEXCEPT { return mailbox_; }
12744 
12749  response_type get_response_type() const EWS_NOEXCEPT
12750  {
12751  return response_type_;
12752  }
12753 
12755  void set_response_type(response_type type) { response_type_ = type; }
12756 
12758  const date_time& get_last_response_time() const EWS_NOEXCEPT
12759  {
12760  return last_response_time_;
12761  }
12762 
12765  {
12766  last_response_time_ = time;
12767  }
12768 
12770  const date_time& get_proposed_start() const EWS_NOEXCEPT
12771  {
12772  return proposed_start_;
12773  }
12774 
12776  void set_proposed_start(const date_time& start) { proposed_start_ = start; }
12777 
12779  const date_time& get_proposed_end() const EWS_NOEXCEPT
12780  {
12781  return proposed_end_;
12782  }
12783 
12785  void set_proposed_end(const date_time& end) { proposed_end_ = end; }
12786 
12788  std::string to_xml() const
12789  {
12790  std::stringstream sstr;
12791  sstr << "<t:Attendee>";
12792  sstr << mailbox_.to_xml();
12793  sstr << "<t:ResponseType>" << internal::enum_to_str(response_type_)
12794  << "</t:ResponseType>";
12795  sstr << "<t:LastResponseTime>" << last_response_time_.to_string()
12796  << "</t:LastResponseTime>";
12797  if (!proposed_start_.to_string().empty())
12798  {
12799  sstr << "<t:ProposedStart>" << proposed_start_.to_string()
12800  << "</t:ProposedStart>";
12801  }
12802  if (!proposed_end_.to_string().empty())
12803  {
12804  sstr << "<t:ProposedEnd>" << proposed_end_.to_string()
12805  << "</t:ProposedEnd>";
12806  }
12807  sstr << "</t:Attendee>";
12808  return sstr.str();
12809  }
12810 
12815  rapidxml::xml_node<>& to_xml_element(rapidxml::xml_node<>& parent) const
12816  {
12817  check(parent.document(),
12818  "Parent node needs to be somewhere in a document");
12819 
12820  // <Attendee>
12821  // <Mailbox/>
12822  // <ResponseType/>
12823  // <LastResponseTime/>
12824  // <ProposedStart/>
12825  // <ProposedEnd/>
12826  // </Attendee>
12827 
12828  using namespace internal;
12829 
12830  auto& attendee_node = create_node(parent, "t:Attendee");
12831  mailbox_.to_xml_element(attendee_node);
12832 
12833  create_node(attendee_node, "t:ResponseType",
12834  enum_to_str(response_type_));
12835  create_node(attendee_node, "t:LastResponseTime",
12836  last_response_time_.to_string());
12837 
12838  if (!proposed_start_.to_string().empty())
12839  {
12840  create_node(attendee_node, "t:ProposedStart",
12841  proposed_start_.to_string());
12842  }
12843  if (!proposed_end_.to_string().empty())
12844  {
12845  create_node(attendee_node, "t:ProposedEnd",
12846  proposed_end_.to_string());
12847  }
12848 
12849  return attendee_node;
12850  }
12851 
12853  static attendee from_xml_element(const rapidxml::xml_node<>& elem)
12854  {
12855  using rapidxml::internal::compare;
12856 
12857  // <Attendee>
12858  // <Mailbox/>
12859  // <ResponseType/>
12860  // <LastResponseTime/>
12861  // <ProposedStart/>
12862  // <ProposedEnd/>
12863  // </Attendee>
12864 
12865  auto mailbox_node =
12866  elem.first_node_ns(internal::uri<>::microsoft::types(), "Mailbox");
12867  check(mailbox_node, "Expected <Mailbox>");
12868 
12870 
12871  for (auto node = elem.first_node(); node; node = node->next_sibling())
12872  {
12873  if (compare(node->local_name(), node->local_name_size(),
12874  "ResponseType", strlen("ResponseType")))
12875  {
12876  attendee.set_response_type(internal::str_to_response_type(
12877  std::string(node->value(), node->value_size())));
12878  }
12879  else if (compare(node->local_name(), node->local_name_size(),
12880  "LastResponseTime", strlen("LastResponseTime")))
12881  {
12882  attendee.set_last_response_time(
12883  date_time(std::string(node->value(), node->value_size())));
12884  }
12885  else if (compare(node->local_name(), node->local_name_size(),
12886  "ProposedStart", strlen("ProposedStart")))
12887  {
12888  attendee.set_proposed_start(
12889  date_time(std::string(node->value(), node->value_size())));
12890  }
12891  else if (compare(node->local_name(), node->local_name_size(),
12892  "ProposedEnd", strlen("ProposedEnd")))
12893  {
12894  attendee.set_proposed_end(
12895  date_time(std::string(node->value(), node->value_size())));
12896  }
12897  }
12898 
12899  return attendee;
12900  }
12901 
12902 private:
12903  mailbox mailbox_;
12904  response_type response_type_;
12905  date_time last_response_time_;
12906  date_time proposed_start_;
12907  date_time proposed_end_;
12908 };
12909 
12910 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12911  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12912 static_assert(!std::is_default_constructible<attendee>::value);
12913 static_assert(std::is_copy_constructible<attendee>::value);
12914 static_assert(std::is_copy_assignable<attendee>::value);
12915 static_assert(std::is_move_constructible<attendee>::value);
12916 static_assert(std::is_move_assignable<attendee>::value);
12917 #endif
12918 
12932 {
12933 public:
12934 #ifdef EWS_HAS_DEFAULT_AND_DELETE
12935  internet_message_header() = delete;
12936 #else
12937 private:
12939 
12940 public:
12941 #endif
12942  internet_message_header(std::string name, std::string value)
12944  : header_name_(std::move(name)), header_value_(std::move(value))
12945  {
12946  }
12947 
12949  const std::string& get_name() const EWS_NOEXCEPT { return header_name_; }
12950 
12952  const std::string& get_value() const EWS_NOEXCEPT { return header_value_; }
12953 
12954 private:
12955  std::string header_name_;
12956  std::string header_value_;
12957 };
12958 
12959 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12960  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12961 static_assert(!std::is_default_constructible<internet_message_header>::value);
12962 static_assert(std::is_copy_constructible<internet_message_header>::value);
12963 static_assert(std::is_copy_assignable<internet_message_header>::value);
12964 static_assert(std::is_move_constructible<internet_message_header>::value);
12965 static_assert(std::is_move_assignable<internet_message_header>::value);
12966 #endif
12967 
12968 namespace internal
12969 {
12970  // Wraps a string so that it becomes its own type
12971  template <int tag> class str_wrapper final
12972  {
12973  public:
12974 #ifdef EWS_HAS_DEFAULT_AND_DELETE
12975  str_wrapper() = default;
12976 #else
12977  str_wrapper() : value_() {}
12978 #endif
12979 
12980  explicit str_wrapper(std::string str) : value_(std::move(str)) {}
12981 
12982  const std::string& str() const EWS_NOEXCEPT { return value_; }
12983 
12984  private:
12985  std::string value_;
12986  };
12987 
12988 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
12989  defined(EWS_HAS_CXX17_STATIC_ASSERT)
12990  static_assert(std::is_default_constructible<str_wrapper<0>>::value);
12991  static_assert(std::is_copy_constructible<str_wrapper<0>>::value);
12992  static_assert(std::is_copy_assignable<str_wrapper<0>>::value);
12993  static_assert(std::is_move_constructible<str_wrapper<0>>::value);
12994  static_assert(std::is_move_assignable<str_wrapper<0>>::value);
12995 #endif
12996 
12997  enum type_tags
12998  {
12999  distinguished_property_set_id,
13000  property_set_id,
13001  property_tag,
13002  property_name,
13003  property_id,
13004  property_type
13005  };
13006 } // namespace internal
13007 
13010 {
13011 public:
13012 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
13013 # ifdef EWS_HAS_TYPE_ALIAS
13014  using distinguished_property_set_id =
13015  internal::str_wrapper<internal::distinguished_property_set_id>;
13016  using property_set_id = internal::str_wrapper<internal::property_set_id>;
13017  using property_tag = internal::str_wrapper<internal::property_tag>;
13018  using property_name = internal::str_wrapper<internal::property_name>;
13019  using property_id = internal::str_wrapper<internal::property_id>;
13020  using property_type = internal::str_wrapper<internal::property_type>;
13021 # else
13022  typedef internal::str_wrapper<internal::distinguished_property_set_id>
13023  distinguished_property_set_id;
13024  typedef internal::str_wrapper<internal::property_set_id> property_set_id;
13025  typedef internal::str_wrapper<internal::property_tag> property_tag;
13026  typedef internal::str_wrapper<internal::property_name> property_name;
13027  typedef internal::str_wrapper<internal::property_id> property_id;
13028  typedef internal::str_wrapper<internal::property_type> property_type;
13029 # endif
13030 #endif
13031 
13032 #ifdef EWS_HAS_DEFAULT_AND_DELETE
13033  extended_field_uri() = delete;
13034 #else
13035 private:
13037 
13038 public:
13039 #endif
13040 
13041  extended_field_uri(distinguished_property_set_id set_id, property_id id,
13042  property_type type)
13043  : distinguished_set_id_(std::move(set_id)), id_(std::move(id)),
13044  type_(std::move(type))
13045  {
13046  }
13047 
13048  extended_field_uri(distinguished_property_set_id set_id, property_name name,
13049  property_type type)
13050  : distinguished_set_id_(std::move(set_id)), name_(std::move(name)),
13051  type_(std::move(type))
13052  {
13053  }
13054 
13055  extended_field_uri(property_set_id set_id, property_id id,
13056  property_type type)
13057  : set_id_(std::move(set_id)), id_(std::move(id)), type_(std::move(type))
13058  {
13059  }
13060 
13061  extended_field_uri(property_set_id set_id, property_name name,
13062  property_type type)
13063  : set_id_(std::move(set_id)), name_(std::move(name)),
13064  type_(std::move(type))
13065  {
13066  }
13067 
13068  extended_field_uri(property_tag tag, property_type type)
13069  : tag_(std::move(tag)), type_(std::move(type))
13070  {
13071  }
13072 
13073  const std::string& get_distinguished_property_set_id() const EWS_NOEXCEPT
13074  {
13075  return distinguished_set_id_.str();
13076  }
13077 
13078  const std::string& get_property_set_id() const EWS_NOEXCEPT
13079  {
13080  return set_id_.str();
13081  }
13082 
13083  const std::string& get_property_tag() const EWS_NOEXCEPT
13084  {
13085  return tag_.str();
13086  }
13087 
13088  const std::string& get_property_name() const EWS_NOEXCEPT
13089  {
13090  return name_.str();
13091  }
13092 
13093  const std::string& get_property_id() const EWS_NOEXCEPT
13094  {
13095  return id_.str();
13096  }
13097 
13098  const std::string& get_property_type() const EWS_NOEXCEPT
13099  {
13100  return type_.str();
13101  }
13102 
13104  std::string to_xml()
13105  {
13106  std::stringstream sstr;
13107 
13108  sstr << "<t:ExtendedFieldURI ";
13109 
13110  if (!distinguished_set_id_.str().empty())
13111  {
13112  sstr << "DistinguishedPropertySetId=\""
13113  << distinguished_set_id_.str() << "\" ";
13114  }
13115  if (!id_.str().empty())
13116  {
13117  sstr << "PropertyId=\"" << id_.str() << "\" ";
13118  }
13119  if (!set_id_.str().empty())
13120  {
13121  sstr << "PropertySetId=\"" << set_id_.str() << "\" ";
13122  }
13123  if (!tag_.str().empty())
13124  {
13125  sstr << "PropertyTag=\"" << tag_.str() << "\" ";
13126  }
13127  if (!name_.str().empty())
13128  {
13129  sstr << "PropertyName=\"" << name_.str() << "\" ";
13130  }
13131  if (!type_.str().empty())
13132  {
13133  sstr << "PropertyType=\"" << type_.str() << "\"/>";
13134  }
13135  return sstr.str();
13136  }
13137 
13139  static extended_field_uri from_xml_element(const rapidxml::xml_node<>& elem)
13140  {
13141  using rapidxml::internal::compare;
13142 
13143  check(compare(elem.name(), elem.name_size(), "t:ExtendedFieldURI",
13144  strlen("t:ExtendedFieldURI")),
13145  "Expected a <ExtendedFieldURI>, got something else");
13146 
13147  std::string distinguished_set_id;
13148  std::string set_id;
13149  std::string tag;
13150  std::string name;
13151  std::string id;
13152  std::string type;
13153 
13154  for (auto attr = elem.first_attribute(); attr != nullptr;
13155  attr = attr->next_attribute())
13156  {
13157  if (compare(attr->name(), attr->name_size(),
13158  "DistinguishedPropertySetId",
13159  strlen("DistinguishedPropertySetId")))
13160  {
13161  distinguished_set_id =
13162  std::string(attr->value(), attr->value_size());
13163  }
13164  else if (compare(attr->name(), attr->name_size(), "PropertySetId",
13165  strlen("PropertySetId")))
13166  {
13167  set_id = std::string(attr->value(), attr->value_size());
13168  }
13169  else if (compare(attr->name(), attr->name_size(), "PropertyTag",
13170  strlen("PropertyTag")))
13171  {
13172  tag = std::string(attr->value(), attr->value_size());
13173  }
13174  else if (compare(attr->name(), attr->name_size(), "PropertyName",
13175  strlen("PropertyName")))
13176  {
13177  name = std::string(attr->value(), attr->value_size());
13178  }
13179  else if (compare(attr->name(), attr->name_size(), "PropertyId",
13180  strlen("PropertyId")))
13181  {
13182  id = std::string(attr->value(), attr->value_size());
13183  }
13184  else if (compare(attr->name(), attr->name_size(), "PropertyType",
13185  strlen("PropertyType")))
13186  {
13187  type = std::string(attr->value(), attr->value_size());
13188  }
13189  else
13190  {
13191  throw exception("Unexpected attribute in <ExtendedFieldURI>");
13192  }
13193  }
13194 
13195  check(!type.empty(), "'PropertyType' attribute missing");
13196 
13197  if (!distinguished_set_id.empty())
13198  {
13199  if (!id.empty())
13200  {
13201  return extended_field_uri(
13202  distinguished_property_set_id(distinguished_set_id),
13203  property_id(id), property_type(type));
13204  }
13205  else if (!name.empty())
13206  {
13207  return extended_field_uri(
13208  distinguished_property_set_id(distinguished_set_id),
13209  property_name(name), property_type(type));
13210  }
13211  }
13212  else if (!set_id.empty())
13213  {
13214  if (!id.empty())
13215  {
13216  return extended_field_uri(property_set_id(set_id),
13217  property_id(id), property_type(type));
13218  }
13219  else if (!name.empty())
13220  {
13221  return extended_field_uri(property_set_id(set_id),
13222  property_name(name),
13223  property_type(type));
13224  }
13225  }
13226  else if (!tag.empty())
13227  {
13228  return extended_field_uri(property_tag(tag), property_type(type));
13229  }
13230 
13231  throw exception(
13232  "Unexpected combination of <ExtendedFieldURI/> attributes");
13233  }
13234 
13235  rapidxml::xml_node<>& to_xml_element(rapidxml::xml_node<>& parent) const
13236  {
13237  auto doc = parent.document();
13238 
13239  auto ptr_to_node = doc->allocate_string("t:ExtendedFieldURI");
13240  auto new_node = doc->allocate_node(rapidxml::node_element, ptr_to_node);
13241  new_node->namespace_uri(internal::uri<>::microsoft::types(),
13242  internal::uri<>::microsoft::types_size);
13243 
13244  if (!get_distinguished_property_set_id().empty())
13245  {
13246  auto ptr_to_attr =
13247  doc->allocate_string("DistinguishedPropertySetId");
13248  auto ptr_to_property = doc->allocate_string(
13249  get_distinguished_property_set_id().c_str());
13250  auto attr_new =
13251  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13252  new_node->append_attribute(attr_new);
13253  }
13254 
13255  if (!get_property_set_id().empty())
13256  {
13257  auto ptr_to_attr = doc->allocate_string("PropertySetId");
13258  auto ptr_to_property =
13259  doc->allocate_string(get_property_set_id().c_str());
13260  auto attr_new =
13261  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13262  new_node->append_attribute(attr_new);
13263  }
13264 
13265  if (!get_property_tag().empty())
13266  {
13267  auto ptr_to_attr = doc->allocate_string("PropertyTag");
13268  auto ptr_to_property =
13269  doc->allocate_string(get_property_tag().c_str());
13270  auto attr_new =
13271  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13272  new_node->append_attribute(attr_new);
13273  }
13274 
13275  if (!get_property_name().empty())
13276  {
13277  auto ptr_to_attr = doc->allocate_string("PropertyName");
13278  auto ptr_to_property =
13279  doc->allocate_string(get_property_name().c_str());
13280  auto attr_new =
13281  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13282  new_node->append_attribute(attr_new);
13283  }
13284 
13285  if (!get_property_type().empty())
13286  {
13287  auto ptr_to_attr = doc->allocate_string("PropertyType");
13288  auto ptr_to_property =
13289  doc->allocate_string(get_property_type().c_str());
13290  auto attr_new =
13291  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13292  new_node->append_attribute(attr_new);
13293  }
13294 
13295  if (!get_property_id().empty())
13296  {
13297  auto ptr_to_attr = doc->allocate_string("PropertyId");
13298  auto ptr_to_property =
13299  doc->allocate_string(get_property_id().c_str());
13300  auto attr_new =
13301  doc->allocate_attribute(ptr_to_attr, ptr_to_property);
13302  new_node->append_attribute(attr_new);
13303  }
13304 
13305  parent.append_node(new_node);
13306  return *new_node;
13307  }
13308 
13309 private:
13310  distinguished_property_set_id distinguished_set_id_;
13311  property_set_id set_id_;
13312  property_tag tag_;
13313  property_name name_;
13314  property_id id_;
13315  property_type type_;
13316 };
13317 
13318 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
13319  defined(EWS_HAS_CXX17_STATIC_ASSERT)
13320 static_assert(!std::is_default_constructible<extended_field_uri>::value);
13321 static_assert(std::is_copy_constructible<extended_field_uri>::value);
13322 static_assert(std::is_copy_assignable<extended_field_uri>::value);
13323 static_assert(std::is_move_constructible<extended_field_uri>::value);
13324 static_assert(std::is_move_assignable<extended_field_uri>::value);
13325 #endif
13326 
13335 {
13336 public:
13337 #ifdef EWS_HAS_DEFAULT_AND_DELETE
13338  extended_property() = delete;
13339 #else
13340 private:
13342 
13343 public:
13344 #endif
13345 
13349  std::vector<std::string> values)
13350  : extended_field_uri_(std::move(ext_field_uri)),
13351  values_(std::move(values))
13352  {
13353  }
13354 
13355  static extended_property
13356  from_xml_element(const rapidxml::xml_node<char>& node); // defined below
13357  std::string to_xml() const;
13358 
13361  const extended_field_uri& get_extended_field_uri() const EWS_NOEXCEPT
13362  {
13363  return extended_field_uri_;
13364  }
13365 
13368  const std::vector<std::string>& get_values() const EWS_NOEXCEPT
13369  {
13370  return values_;
13371  }
13372 
13373 private:
13374  extended_field_uri extended_field_uri_;
13375  std::vector<std::string> values_;
13376 };
13377 
13378 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
13379  defined(EWS_HAS_CXX17_STATIC_ASSERT)
13380 static_assert(!std::is_default_constructible<extended_property>::value);
13381 static_assert(std::is_copy_constructible<extended_property>::value);
13382 static_assert(std::is_copy_assignable<extended_property>::value);
13383 static_assert(std::is_move_constructible<extended_property>::value);
13384 static_assert(std::is_move_assignable<extended_property>::value);
13385 #endif
13386 
13387 inline std::string extended_property::to_xml() const
13388 {
13389  std::stringstream sstr;
13390 
13391  auto values = get_values();
13392  auto efu = get_extended_field_uri();
13393  for (auto&& v : values)
13394  {
13395  sstr << efu.to_xml();
13396  sstr << "<t:Message>";
13397  sstr << "<t:ExtendedProperty>" << efu.to_xml();
13398  sstr << "<t:Value>" << v << "</t:Value>";
13399  sstr << "</t:ExtendedProperty>";
13400  sstr << "</t:Message>";
13401  }
13402  return sstr.str();
13403 }
13404 
13405 inline extended_property
13406 extended_property::from_xml_element(const rapidxml::xml_node<char>& top_node)
13407 {
13408  using namespace internal;
13409  using rapidxml::internal::compare;
13410 
13411  check(compare(top_node.name(), top_node.name_size(), "t:ExtendedProperty",
13412  strlen("t:ExtendedProperty")),
13413  "Expected a <ExtendedProperty>, got something else");
13414 
13415  auto node = top_node.first_node();
13416  auto ext_field_uri = extended_field_uri::from_xml_element(*node);
13417  std::vector<std::string> values;
13418  node = node->next_sibling();
13419 
13420  if (compare(node->name(), node->name_size(), "t:Value", strlen("t:Value")))
13421  {
13422  values.emplace_back(std::string(node->value(), node->value_size()));
13423  }
13424  else if (compare(node->name(), node->name_size(), "t:Values",
13425  strlen("t:Values")))
13426  {
13427  for (auto child = node->first_node(); child != nullptr;
13428  child = child->next_sibling())
13429  {
13430  values.emplace_back(
13431  std::string(child->value(), child->value_size()));
13432  }
13433  }
13434  return extended_property(std::move(ext_field_uri), std::move(values));
13435 }
13436 
13438 class folder final
13439 {
13440 public:
13442 #ifdef EWS_HAS_DEFAULT_AND_DELETE
13443  folder() = default;
13444 #else
13445  folder() {}
13446 #endif
13447  explicit folder(folder_id id) : folder_id_(std::move(id)), xml_subtree_() {}
13449 
13450 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
13451  folder(folder_id&& id, internal::xml_subtree&& properties)
13452  : folder_id_(std::move(id)), xml_subtree_(std::move(properties))
13453  {
13454  }
13455 #endif
13456 
13458  const folder_id& get_folder_id() const EWS_NOEXCEPT { return folder_id_; }
13459 
13461  std::string get_display_name() const
13462  {
13463  return xml().get_value_as_string("DisplayName");
13464  }
13465 
13467  void set_display_name(const std::string& display_name)
13468  {
13469  xml().set_or_update("DisplayName", display_name);
13470  }
13471 
13473  int get_total_count() const
13474  {
13475  return std::stoi(xml().get_value_as_string("TotalCount"));
13476  }
13477 
13480  {
13481  return std::stoi(xml().get_value_as_string("ChildFolderCount"));
13482  }
13483 
13486  {
13487  auto parent_id_node = xml().get_node("ParentFolderId");
13488  check(parent_id_node, "Expected <ParentFolderId>");
13489  return folder_id::from_xml_element(*parent_id_node);
13490  }
13491 
13493  int get_unread_count() const
13494  {
13495  return std::stoi(xml().get_value_as_string("UnreadCount"));
13496  }
13497 
13499  static folder from_xml_element(const rapidxml::xml_node<>& elem)
13500  {
13501  auto id_node =
13502  elem.first_node_ns(internal::uri<>::microsoft::types(), "FolderId");
13503  check(id_node, "Expected <FolderId>");
13504  return folder(folder_id::from_xml_element(*id_node),
13505  internal::xml_subtree(elem));
13506  }
13507 
13508 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
13509 protected:
13510  internal::xml_subtree& xml() EWS_NOEXCEPT { return xml_subtree_; }
13511 
13512  const internal::xml_subtree& xml() const EWS_NOEXCEPT
13513  {
13514  return xml_subtree_;
13515  }
13516 #endif
13517 
13518 private:
13519  template <typename U> friend class basic_service;
13520 
13521  folder_id folder_id_;
13522  internal::xml_subtree xml_subtree_;
13523 };
13524 
13525 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
13526  defined(EWS_HAS_CXX17_STATIC_ASSERT)
13527 static_assert(std::is_default_constructible<folder>::value);
13528 static_assert(std::is_copy_constructible<folder>::value);
13529 static_assert(std::is_copy_assignable<folder>::value);
13530 static_assert(std::is_move_constructible<folder>::value);
13531 static_assert(std::is_move_assignable<folder>::value);
13532 #endif
13533 
13550 class item
13551 {
13552 public:
13554 #ifdef EWS_HAS_DEFAULT_AND_DELETE
13555  item() = default;
13556 #else
13557  item() {}
13558 #endif
13559  explicit item(item_id id) : item_id_(std::move(id)), xml_subtree_() {}
13561 
13562 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
13563  item(item_id&& id, internal::xml_subtree&& properties)
13564  : item_id_(std::move(id)), xml_subtree_(std::move(properties))
13565  {
13566  }
13567 #endif
13568 
13570  const item_id& get_item_id() const EWS_NOEXCEPT { return item_id_; }
13571 
13574  {
13575  const auto node = xml().get_node("MimeContent");
13576  if (!node)
13577  {
13578  return mime_content();
13579  }
13580  auto charset = node->first_attribute("CharacterSet");
13581  check(charset, "Expected <MimeContent> to have CharacterSet attribute");
13582  return mime_content(charset->value(), node->value(),
13583  node->value_size());
13584  }
13585 
13591  {
13592  const auto node = xml().get_node("ParentFolderId");
13593  return node ? folder_id::from_xml_element(*node) : folder_id();
13594  }
13595 
13598  std::string get_item_class() const
13599  {
13600  return xml().get_value_as_string("ItemClass");
13601  }
13602 
13604  void set_subject(const std::string& subject)
13605  {
13606  xml().set_or_update("Subject", subject);
13607  }
13608 
13610  std::string get_subject() const
13611  {
13612  return xml().get_value_as_string("Subject");
13613  }
13614 
13617  {
13618  const auto val = xml().get_value_as_string("Sensitivity");
13619  return !val.empty() ? internal::str_to_sensitivity(val)
13621  }
13622 
13625  {
13626  xml().set_or_update("Sensitivity", internal::enum_to_str(s));
13627  }
13628 
13630  void set_body(const body& b)
13631  {
13632  auto doc = xml().document();
13633 
13634  auto body_node = xml().get_node("Body");
13635  if (body_node)
13636  {
13637  doc->remove_node(body_node);
13638  }
13639 
13640  body_node = &internal::create_node(*doc, "t:Body", b.content());
13641 
13642  auto ptr_to_key = doc->allocate_string("BodyType");
13643  auto ptr_to_value =
13644  doc->allocate_string(internal::body_type_str(b.type()).c_str());
13645  body_node->append_attribute(
13646  doc->allocate_attribute(ptr_to_key, ptr_to_value));
13647 
13648  bool truncated = b.is_truncated();
13649  if (truncated)
13650  {
13651  ptr_to_key = doc->allocate_string("IsTruncated");
13652  ptr_to_value = doc->allocate_string(truncated ? "true" : "false");
13653  body_node->append_attribute(
13654  doc->allocate_attribute(ptr_to_key, ptr_to_value));
13655  }
13656  }
13657 
13659  body get_body() const
13660  {
13661  using rapidxml::internal::compare;
13662 
13663  body b;
13664  auto body_node = xml().get_node("Body");
13665  if (body_node)
13666  {
13667  for (auto attr = body_node->first_attribute(); attr;
13668  attr = attr->next_attribute())
13669  {
13670  if (compare(attr->name(), attr->name_size(), "BodyType",
13671  strlen("BodyType")))
13672  {
13673  if (compare(attr->value(), attr->value_size(), "HTML",
13674  strlen("HTML")))
13675  {
13676  b.set_type(body_type::html);
13677  }
13678  else if (compare(attr->value(), attr->value_size(), "Text",
13679  strlen("Text")))
13680  {
13681  b.set_type(body_type::plain_text);
13682  }
13683  else if (compare(attr->value(), attr->value_size(), "Best",
13684  strlen("Best")))
13685  {
13686  b.set_type(body_type::best);
13687  }
13688  else
13689  {
13690  check(false, "Unexpected attribute value for BodyType");
13691  }
13692  }
13693  else if (compare(attr->name(), attr->name_size(), "IsTruncated",
13694  strlen("IsTruncated")))
13695  {
13696  const auto val = compare(attr->value(), attr->value_size(),
13697  "true", strlen("true"));
13698  b.set_truncated(val);
13699  }
13700  else
13701  {
13702  check(false, "Unexpected attribute in <Body> element");
13703  }
13704  }
13705 
13706  auto content =
13707  std::string(body_node->value(), body_node->value_size());
13708  b.set_content(std::move(content));
13709  }
13710  return b;
13711  }
13712 
13714  std::vector<attachment> get_attachments() const
13715  {
13716  // TODO: support attachment hierarchies
13717 
13718  const auto attachments_node = xml().get_node("Attachments");
13719  if (!attachments_node)
13720  {
13721  return std::vector<attachment>();
13722  }
13723 
13724  std::vector<attachment> attachments;
13725  for (auto child = attachments_node->first_node(); child != nullptr;
13726  child = child->next_sibling())
13727  {
13728  attachments.emplace_back(attachment::from_xml_element(*child));
13729  }
13730  return attachments;
13731  }
13732 
13737  {
13738  const auto val = xml().get_value_as_string("DateTimeReceived");
13739  return !val.empty() ? date_time(val) : date_time();
13740  }
13741 
13745  size_t get_size() const
13746  {
13747  const auto size = xml().get_value_as_string("Size");
13748  return size.empty() ? 0U : std::stoul(size);
13749  }
13750 
13758  void set_categories(const std::vector<std::string>& categories)
13759  {
13760  auto doc = xml().document();
13761  auto target_node = xml().get_node("Categories");
13762  if (!target_node)
13763  {
13764  target_node = &internal::create_node(*doc, "t:Categories");
13765  }
13766 
13767  for (const auto& category : categories)
13768  {
13769  internal::create_node(*target_node, "t:String", category);
13770  }
13771  }
13772 
13776  std::vector<std::string> get_categories() const
13777  {
13778  const auto categories_node = xml().get_node("Categories");
13779  if (!categories_node)
13780  {
13781  return std::vector<std::string>();
13782  }
13783 
13784  std::vector<std::string> categories;
13785  for (auto child = categories_node->first_node(); child != nullptr;
13786  child = child->next_sibling())
13787  {
13788  categories.emplace_back(
13789  std::string(child->value(), child->value_size()));
13790  }
13791  return categories;
13792  }
13793 
13796  {
13797  xml().set_or_update("Importance", internal::enum_to_str(i));
13798  }
13799 
13802  {
13803  const auto val = xml().get_value_as_string("Importance");
13804  return !val.empty() ? internal::str_to_importance(val)
13806  }
13807 
13812  std::string get_in_reply_to() const
13813  {
13814  return xml().get_value_as_string("InReplyTo");
13815  }
13816 
13820  bool is_submitted() const
13821  {
13822  return xml().get_value_as_string("isSubmitted") == "true";
13823  }
13824 
13828  bool is_draft() const
13829  {
13830  return xml().get_value_as_string("isDraft") == "true";
13831  }
13832 
13836  bool is_from_me() const
13837  {
13838  return xml().get_value_as_string("isFromMe") == "true";
13839  }
13840 
13844  bool is_resend() const
13845  {
13846  return xml().get_value_as_string("isResend") == "true";
13847  }
13848 
13852  bool is_unmodified() const
13853  {
13854  return xml().get_value_as_string("isUnmodified") == "true";
13855  }
13856 
13863  std::vector<internet_message_header> get_internet_message_headers() const
13864  {
13865  const auto node = xml().get_node("InternetMessageHeaders");
13866  if (!node)
13867  {
13868  return std::vector<internet_message_header>();
13869  }
13870 
13871  std::vector<internet_message_header> headers;
13872  for (auto child = node->first_node(); child != nullptr;
13873  child = child->next_sibling())
13874  {
13875  auto field = std::string(child->first_attribute()->value(),
13876  child->first_attribute()->value_size());
13877  auto value = std::string(child->value(), child->value_size());
13878 
13879  headers.emplace_back(
13880  internet_message_header(std::move(field), std::move(value)));
13881  }
13882 
13883  return headers;
13884  }
13885 
13890  {
13891  return date_time(xml().get_value_as_string("DateTimeSent"));
13892  }
13893 
13898  {
13899  return date_time(xml().get_value_as_string("DateTimeCreated"));
13900  }
13901 
13902  // Applicable response actions for this item
13903  // (NonEmptyArrayOfResponseObjectsType)
13904  // TODO: get_response_objects
13905 
13909  void set_reminder_due_by(const date_time& due_by)
13910  {
13911  xml().set_or_update("ReminderDueBy", due_by.to_string());
13912  }
13913 
13918  {
13919  return date_time(xml().get_value_as_string("ReminderDueBy"));
13920  }
13921 
13923  void set_reminder_enabled(bool enabled)
13924  {
13925  xml().set_or_update("ReminderIsSet", enabled ? "true" : "false");
13926  }
13927 
13929  bool is_reminder_enabled() const
13930  {
13931  return xml().get_value_as_string("ReminderIsSet") == "true";
13932  }
13933 
13936  void set_reminder_minutes_before_start(uint32_t minutes)
13937  {
13938  xml().set_or_update("ReminderMinutesBeforeStart",
13939  std::to_string(minutes));
13940  }
13941 
13945  {
13946  std::string minutes =
13947  xml().get_value_as_string("ReminderMinutesBeforeStart");
13948  return minutes.empty() ? 0U : std::stoul(minutes);
13949  }
13950 
13957  std::string get_display_cc() const
13958  {
13959  return xml().get_value_as_string("DisplayCc");
13960  }
13961 
13968  std::string get_display_to() const
13969  {
13970  return xml().get_value_as_string("DisplayTo");
13971  }
13972 
13976  bool has_attachments() const
13977  {
13978  return xml().get_value_as_string("HasAttachments") == "true";
13979  }
13980 
13983  std::vector<extended_property> get_extended_properties() const
13984  {
13985  using rapidxml::internal::compare;
13986 
13987  std::vector<extended_property> properties;
13988 
13989  for (auto top_node = xml().get_node("ExtendedProperty");
13990  top_node != nullptr; top_node = top_node->next_sibling())
13991  {
13992  if (!compare(top_node->name(), top_node->name_size(),
13993  "t:ExtendedProperty", strlen("t:ExtendedProperty")))
13994  {
13995  continue;
13996  }
13997 
13998  auto ext_prop = extended_property::from_xml_element(*top_node);
13999  properties.emplace_back(ext_prop);
14000  }
14001 
14002  return properties;
14003  }
14004 
14006  void set_extended_property(const extended_property& extended_prop)
14007  {
14008  auto doc = xml().document();
14009 
14010  auto ptr_to_qname = doc->allocate_string("t:ExtendedProperty");
14011  auto top_node = doc->allocate_node(rapidxml::node_element);
14012  top_node->qname(ptr_to_qname, strlen("t:ExtendedProperty"),
14013  ptr_to_qname + 2);
14014  top_node->namespace_uri(internal::uri<>::microsoft::types(),
14015  internal::uri<>::microsoft::types_size);
14016  doc->append_node(top_node);
14017 
14018  extended_field_uri field_uri = extended_prop.get_extended_field_uri();
14019  field_uri.to_xml_element(*top_node);
14020 
14021  rapidxml::xml_node<>* cover_node = nullptr;
14022  if (extended_prop.get_values().size() > 1)
14023  {
14024  auto ptr_to_values = doc->allocate_string("t:Values");
14025  cover_node =
14026  doc->allocate_node(rapidxml::node_element, ptr_to_values);
14027  cover_node->namespace_uri(internal::uri<>::microsoft::types(),
14028  internal::uri<>::microsoft::types_size);
14029  top_node->append_node(cover_node);
14030  }
14031 
14032  for (auto str : extended_prop.get_values())
14033  {
14034  auto new_str = doc->allocate_string(str.c_str());
14035  auto ptr_to_value = doc->allocate_string("t:Value");
14036  auto cur_node =
14037  doc->allocate_node(rapidxml::node_element, ptr_to_value);
14038  cur_node->namespace_uri(internal::uri<>::microsoft::types(),
14039  internal::uri<>::microsoft::types_size);
14040  cur_node->value(new_str);
14041 
14042  cover_node == nullptr ? top_node->append_node(cur_node)
14043  : cover_node->append_node(cur_node);
14044  }
14045  }
14046 
14048  void set_culture(const std::string& culture)
14049  {
14050  xml().set_or_update("Culture", culture);
14051  }
14052 
14054  std::string get_culture() const
14055  {
14056  return xml().get_value_as_string("Culture");
14057  }
14058 
14059  // Following properties are beyond 2007 scope:
14060  // <EffectiveRights/>
14061  // <LastModifiedName/>
14062  // <LastModifiedTime/>
14063  // <IsAssociated/>
14064  // <WebClientReadFormQueryString/>
14065  // <WebClientEditFormQueryString/>
14066  // <ConversationId/>
14067  // <UniqueBody/>
14068 
14069 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
14070 protected:
14071  internal::xml_subtree& xml() EWS_NOEXCEPT { return xml_subtree_; }
14072 
14073  const internal::xml_subtree& xml() const EWS_NOEXCEPT
14074  {
14075  return xml_subtree_;
14076  }
14077 #endif
14078 
14079  void set_array_of_strings_helper(const std::vector<std::string>& strings,
14080  const char* name)
14081  {
14082  // TODO: this does not meet strong exception safety guarantees
14083 
14084  using namespace internal;
14085 
14086  auto outer_node = xml().get_node(name);
14087  if (outer_node)
14088  {
14089  auto doc = outer_node->document();
14090  doc->remove_node(outer_node);
14091  }
14092 
14093  if (strings.empty())
14094  {
14095  // Nothing to do
14096  return;
14097  }
14098 
14099  outer_node = &create_node(*xml().document(), std::string("t:") + name);
14100  for (const auto& element : strings)
14101  {
14102  create_node(*outer_node, "t:String", element);
14103  }
14104  }
14105 
14106  std::vector<std::string> get_array_of_strings_helper(const char* name) const
14107  {
14108  auto node = xml().get_node(name);
14109  if (!node)
14110  {
14111  return std::vector<std::string>();
14112  }
14113  auto res = std::vector<std::string>();
14114  for (auto entry = node->first_node(); entry;
14115  entry = entry->next_sibling())
14116  {
14117  res.emplace_back(std::string(entry->value(), entry->value_size()));
14118  }
14119  return res;
14120  }
14121 
14122 private:
14123  friend class attachment;
14124 
14125  item_id item_id_;
14126  internal::xml_subtree xml_subtree_;
14127 };
14128 
14129 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
14130  defined(EWS_HAS_CXX17_STATIC_ASSERT)
14131 static_assert(std::is_default_constructible<item>::value);
14132 static_assert(std::is_copy_constructible<item>::value);
14133 static_assert(std::is_copy_assignable<item>::value);
14134 static_assert(std::is_move_constructible<item>::value);
14135 static_assert(std::is_move_assignable<item>::value);
14136 #endif
14137 
14138 class user_id final
14139 {
14140 public:
14141  // Default or Anonymous
14142  enum class distinguished_user
14143  {
14144  default_user_account,
14145  anonymous
14146  };
14147 
14148 #ifdef EWS_HAS_DEFAULT_AND_DELETE
14149  user_id() = default;
14150 #else
14151  user_id() {}
14152 #endif
14153 
14154  user_id(std::string sid, std::string primary_smtp_address,
14155  std::string display_name)
14156  : sid_(std::move(sid)),
14157  primary_smtp_address_(std::move(primary_smtp_address)),
14158  display_name_(std::move(display_name)), distinguished_user_(),
14159  external_user_identity_(false)
14160  {
14161  }
14162 
14163  user_id(std::string sid, std::string primary_smtp_address,
14164  std::string display_name, distinguished_user user_account,
14165  bool external_user_identity)
14166  : sid_(std::move(sid)),
14167  primary_smtp_address_(std::move(primary_smtp_address)),
14168  display_name_(std::move(display_name)),
14169  distinguished_user_(std::move(user_account)),
14170  external_user_identity_(std::move(external_user_identity))
14171  {
14172  }
14173 
14174  const std::string& get_sid() const EWS_NOEXCEPT { return sid_; }
14175 
14176  const std::string& get_primary_smtp_address() const EWS_NOEXCEPT
14177  {
14178  return primary_smtp_address_;
14179  }
14180 
14181  const std::string& get_display_name() const EWS_NOEXCEPT
14182  {
14183  return display_name_;
14184  }
14185 
14186 #ifdef EWS_HAS_OPTIONAL
14187  std::optional<distinguished_user>
14188 #else
14189  internal::optional<distinguished_user>
14190 #endif
14191  get_distinguished_user() const EWS_NOEXCEPT
14192  {
14193  return distinguished_user_;
14194  }
14195 
14196  bool is_external_user_identity() const EWS_NOEXCEPT
14197  {
14198  return external_user_identity_;
14199  }
14200 
14202  static user_id from_primary_smtp_address(std::string primary_smtp_address)
14203  {
14204  return user_id(std::string(), std::move(primary_smtp_address),
14205  std::string());
14206  }
14207 
14209  static user_id from_sid(std::string sid)
14210  {
14211  return user_id(std::move(sid), std::string(), std::string());
14212  }
14213 
14214  static user_id from_xml_element(const rapidxml::xml_node<char>& elem)
14215  {
14216  using rapidxml::internal::compare;
14217 
14218  // <UserId>
14219  // <SID/>
14220  // <PrimarySmtpAddress/>
14221  // <DisplayName/>
14222  // <DistinguishedUser/>
14223  // <ExternalUserIdentity/>
14224  // </UserId>
14225 
14226  std::string sid;
14227  std::string primary_smtp_address;
14228  std::string display_name;
14229  distinguished_user user_account =
14230  distinguished_user::default_user_account;
14231  bool external_user_identity = false;
14232 
14233  for (auto node = elem.first_node(); node; node = node->next_sibling())
14234  {
14235  if (compare(node->local_name(), node->local_name_size(), "SID",
14236  strlen("SID")))
14237  {
14238  sid = std::string(node->value(), node->value_size());
14239  }
14240  else if (compare(node->local_name(), node->local_name_size(),
14241  "PrimarySmtpAddress",
14242  strlen("PrimarySmtpAddress")))
14243  {
14244  primary_smtp_address =
14245  std::string(node->value(), node->value_size());
14246  }
14247  else if (compare(node->local_name(), node->local_name_size(),
14248  "DisplayName", strlen("DisplayName")))
14249  {
14250  display_name = std::string(node->value(), node->value_size());
14251  }
14252  else if (compare(node->local_name(), node->local_name_size(),
14253  "DistinguishedUser", strlen("DistinguishedUser")))
14254  {
14255  const auto val = std::string(node->value(), node->value_size());
14256  if (val != "Anonymous")
14257  {
14258  user_account = distinguished_user::anonymous;
14259  }
14260  }
14261  else if (compare(node->local_name(), node->local_name_size(),
14262  "ExternalUserIdentity",
14263  strlen("ExternalUserIdentity")))
14264  {
14265  external_user_identity = true;
14266  }
14267  else
14268  {
14269  throw exception("Unexpected child element in <UserId>");
14270  }
14271  }
14272 
14273  return user_id(sid, primary_smtp_address, display_name, user_account,
14274  external_user_identity);
14275  }
14276 
14277  std::string to_xml() const
14278  {
14279  std::stringstream sstr;
14280  sstr << "<t:UserId>";
14281 
14282  if (!sid_.empty())
14283  {
14284  sstr << "<t:SID>" << sid_ << "</t:SID>";
14285  }
14286 
14287  if (!primary_smtp_address_.empty())
14288  {
14289  sstr << "<t:PrimarySmtpAddress>" << primary_smtp_address_
14290  << "</t:PrimarySmtpAddress>";
14291  }
14292 
14293  if (!display_name_.empty())
14294  {
14295  sstr << "<t:DisplayName>" << display_name_ << "</t:DisplayName>";
14296  }
14297 
14298  if (distinguished_user_.has_value())
14299  {
14300  sstr << "<t:DistinguishedUser>"
14301  << (distinguished_user_ == distinguished_user::anonymous
14302  ? "Anonymous"
14303  : "Default")
14304  << "</t:DistinguishedUser>";
14305  }
14306 
14307  if (external_user_identity_)
14308  {
14309  sstr << "<t:ExternalUserIdentity/>";
14310  }
14311 
14312  sstr << "</t:UserId>";
14313  return sstr.str();
14314  }
14315 
14316 private:
14317  std::string sid_;
14318  std::string primary_smtp_address_;
14319  std::string display_name_;
14320 #ifdef EWS_HAS_OPTIONAL
14321  std::optional<distinguished_user> distinguished_user_;
14322 #else
14323  internal::optional<distinguished_user> distinguished_user_;
14324 #endif
14325  bool external_user_identity_; // Renders to an element without text value,
14326  // if set
14327 };
14328 
14329 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
14330  defined(EWS_HAS_CXX17_STATIC_ASSERT)
14331 static_assert(std::is_default_constructible<user_id>::value);
14332 static_assert(std::is_copy_constructible<user_id>::value);
14333 static_assert(std::is_copy_assignable<user_id>::value);
14334 static_assert(std::is_move_constructible<user_id>::value);
14335 static_assert(std::is_move_assignable<user_id>::value);
14336 #endif
14337 
14339 class delegate_user final
14340 {
14341 public:
14343  enum class permission_level
14344  {
14346  none,
14347 
14349  reviewer,
14350 
14352  author,
14353 
14355  editor,
14356 
14358  custom
14359  };
14360 
14362  {
14363  permission_level calendar_folder;
14364  permission_level tasks_folder;
14365  permission_level inbox_folder;
14366  permission_level contacts_folder;
14367  permission_level notes_folder;
14368  permission_level journal_folder;
14369 
14371  : calendar_folder(permission_level::none),
14372  tasks_folder(permission_level::none),
14373  inbox_folder(permission_level::none),
14374  contacts_folder(permission_level::none),
14375  notes_folder(permission_level::none),
14376  journal_folder(permission_level::none)
14377  {
14378  }
14379 
14380  // defined below
14381  std::string to_xml() const;
14382 
14383  // defined below
14384  static delegate_permissions
14385  from_xml_element(const rapidxml::xml_node<char>& elem);
14386  };
14387 
14388 #ifdef EWS_HAS_DEFAULT_AND_DELETE
14389  delegate_user() = default;
14390 #else
14391  delegate_user() {}
14392 #endif
14393 
14394  delegate_user(user_id user, delegate_permissions permissions,
14395  bool receive_copies, bool view_private_items)
14396  : user_id_(std::move(user)), permissions_(std::move(permissions)),
14397  receive_copies_(std::move(receive_copies)),
14398  view_private_items_(std::move(view_private_items))
14399  {
14400  }
14401 
14402  const user_id& get_user_id() const EWS_NOEXCEPT { return user_id_; }
14403 
14404  const delegate_permissions& get_permissions() const EWS_NOEXCEPT
14405  {
14406  return permissions_;
14407  }
14408 
14411  bool get_receive_copies_of_meeting_messages() const EWS_NOEXCEPT
14412  {
14413  return receive_copies_;
14414  }
14415 
14418  bool get_view_private_items() const EWS_NOEXCEPT
14419  {
14420  return view_private_items_;
14421  }
14422 
14423  static delegate_user from_xml_element(const rapidxml::xml_node<char>& elem)
14424  {
14425  // <DelegateUser>
14426  // <UserId/>
14427  // <DelegatePermissions/>
14428  // <ReceiveCopiesOfMeetingMessages/>
14429  // <ViewPrivateItems/>
14430  // </DelegateUser>
14431 
14432  using rapidxml::internal::compare;
14433 
14434  user_id id;
14435  delegate_permissions perms;
14436  bool receive_copies = false;
14437  bool view_private_items = false;
14438 
14439  for (auto node = elem.first_node(); node; node = node->next_sibling())
14440  {
14441  if (compare(node->local_name(), node->local_name_size(), "UserId",
14442  strlen("UserId")))
14443  {
14444  id = user_id::from_xml_element(*node);
14445  }
14446  else if (compare(node->local_name(), node->local_name_size(),
14447  "DelegatePermissions",
14448  strlen("DelegatePermissions")))
14449  {
14450  perms = delegate_permissions::from_xml_element(*node);
14451  }
14452  else if (compare(node->local_name(), node->local_name_size(),
14453  "ReceiveCopiesOfMeetingMessages",
14454  strlen("ReceiveCopiesOfMeetingMessages")))
14455  {
14456  receive_copies = true;
14457  }
14458  else if (compare(node->local_name(), node->local_name_size(),
14459  "ViewPrivateItems", strlen("ViewPrivateItems")))
14460  {
14461  view_private_items = true;
14462  }
14463  else
14464  {
14465  throw exception("Unexpected child element in <DelegateUser>");
14466  }
14467  }
14468 
14469  return delegate_user(id, perms, receive_copies, view_private_items);
14470  }
14471 
14472  std::string to_xml() const
14473  {
14474  std::stringstream sstr;
14475  sstr << "<t:DelegateUser>";
14476  sstr << user_id_.to_xml();
14477  sstr << permissions_.to_xml();
14478  sstr << "<t:ReceiveCopiesOfMeetingMessages>"
14479  << (receive_copies_ ? "true" : "false")
14480  << "</t:ReceiveCopiesOfMeetingMessages>";
14481  sstr << "<t:ViewPrivateItems>"
14482  << (view_private_items_ ? "true" : "false")
14483  << "</t:ViewPrivateItems>";
14484  sstr << "</t:DelegateUser>";
14485  return sstr.str();
14486  }
14487 
14488 private:
14489  user_id user_id_;
14490  delegate_permissions permissions_;
14491  bool receive_copies_;
14492  bool view_private_items_;
14493 };
14494 
14495 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
14496  defined(EWS_HAS_CXX17_STATIC_ASSERT)
14497 static_assert(std::is_default_constructible<delegate_user>::value);
14498 static_assert(std::is_copy_constructible<delegate_user>::value);
14499 static_assert(std::is_copy_assignable<delegate_user>::value);
14500 static_assert(std::is_move_constructible<delegate_user>::value);
14501 static_assert(std::is_move_assignable<delegate_user>::value);
14502 #endif
14503 
14504 namespace internal
14505 {
14506  inline std::string enum_to_str(delegate_user::permission_level level)
14507  {
14508  std::string str;
14509  switch (level)
14510  {
14512  str = "None";
14513  break;
14514 
14516  str = "Editor";
14517  break;
14518 
14520  str = "Author";
14521  break;
14522 
14524  str = "Reviewer";
14525  break;
14526 
14528  str = "Custom";
14529  break;
14530 
14531  default:
14532  throw exception("Unknown permission level");
14533  }
14534  return str;
14535  }
14536 
14538  str_to_permission_level(const std::string& str)
14539  {
14541  if (str == "Editor")
14542  {
14544  }
14545  else if (str == "Author")
14546  {
14548  }
14549  else if (str == "Reviewer")
14550  {
14552  }
14553  else if (str == "Custom")
14554  {
14556  }
14557  return level;
14558  }
14559 } // namespace internal
14560 
14565 {
14568  no_match,
14569 
14572  own_new,
14573 
14575  owned,
14576 
14578  accepted,
14579 
14581  declined,
14582 
14584  max
14585 };
14586 
14587 namespace internal
14588 {
14589  inline std::string enum_to_str(delegation_state state)
14590  {
14591  switch (state)
14592  {
14594  return "NoMatch";
14596  return "OwnNew";
14598  return "Owned";
14600  return "Accepted";
14602  return "Declined";
14603  case delegation_state::max:
14604  return "Max";
14605  default:
14606  throw exception("Unexpected <DelegationState>");
14607  }
14608  }
14609 } // namespace internal
14610 
14612 enum class status
14613 {
14615  not_started,
14616 
14618  in_progress,
14619 
14621  completed,
14622 
14625 
14627  deferred
14628 };
14629 
14630 namespace internal
14631 {
14632  inline std::string enum_to_str(status s)
14633  {
14634  switch (s)
14635  {
14636  case status::not_started:
14637  return "NotStarted";
14638  case status::in_progress:
14639  return "InProgress";
14640  case status::completed:
14641  return "Completed";
14643  return "WaitingOnOthers";
14644  case status::deferred:
14645  return "Deferred";
14646  default:
14647  throw exception("Unexpected <Status>");
14648  }
14649  }
14650 } // namespace internal
14651 
14653 enum class month
14654 {
14656  jan,
14657 
14659  feb,
14660 
14662  mar,
14663 
14665  apr,
14666 
14668  may,
14669 
14671  june,
14672 
14674  july,
14675 
14677  aug,
14678 
14680  sept,
14681 
14683  oct,
14684 
14686  nov,
14687 
14689  dec
14690 };
14691 
14692 namespace internal
14693 {
14694  inline std::string enum_to_str(month m)
14695  {
14696  switch (m)
14697  {
14698  case month::jan:
14699  return "January";
14700  case month::feb:
14701  return "February";
14702  case month::mar:
14703  return "March";
14704  case month::apr:
14705  return "April";
14706  case month::may:
14707  return "May";
14708  case month::june:
14709  return "June";
14710  case month::july:
14711  return "July";
14712  case month::aug:
14713  return "August";
14714  case month::sept:
14715  return "September";
14716  case month::oct:
14717  return "October";
14718  case month::nov:
14719  return "November";
14720  case month::dec:
14721  return "December";
14722  default:
14723  throw exception("Unexpected <Month>");
14724  }
14725  }
14726 
14727  inline month str_to_month(const std::string& str)
14728  {
14729  month mon;
14730  if (str == "January")
14731  {
14732  mon = month::jan;
14733  }
14734  else if (str == "February")
14735  {
14736  mon = month::feb;
14737  }
14738  else if (str == "March")
14739  {
14740  mon = month::mar;
14741  }
14742  else if (str == "April")
14743  {
14744  mon = month::apr;
14745  }
14746  else if (str == "May")
14747  {
14748  mon = month::may;
14749  }
14750  else if (str == "June")
14751  {
14752  mon = month::june;
14753  }
14754  else if (str == "July")
14755  {
14756  mon = month::july;
14757  }
14758  else if (str == "August")
14759  {
14760  mon = month::aug;
14761  }
14762  else if (str == "September")
14763  {
14764  mon = month::sept;
14765  }
14766  else if (str == "October")
14767  {
14768  mon = month::oct;
14769  }
14770  else if (str == "November")
14771  {
14772  mon = month::nov;
14773  }
14774  else if (str == "December")
14775  {
14776  mon = month::dec;
14777  }
14778  else
14779  {
14780  throw exception("Unexpected <Month>");
14781  }
14782  return mon;
14783  }
14784 } // namespace internal
14785 
14787 enum class day_of_week
14788 {
14790  sun,
14791 
14793  mon,
14794 
14796  tue,
14797 
14799  wed,
14800 
14802  thu,
14803 
14805  fri,
14806 
14808  sat,
14809 
14811  day,
14812 
14814  weekday,
14815 
14817  weekend_day
14818 };
14819 
14820 namespace internal
14821 {
14822  inline std::string enum_to_str(day_of_week d)
14823  {
14824  switch (d)
14825  {
14826  case day_of_week::sun:
14827  return "Sunday";
14828  case day_of_week::mon:
14829  return "Monday";
14830  case day_of_week::tue:
14831  return "Tuesday";
14832  case day_of_week::wed:
14833  return "Wednesday";
14834  case day_of_week::thu:
14835  return "Thursday";
14836  case day_of_week::fri:
14837  return "Friday";
14838  case day_of_week::sat:
14839  return "Saturday";
14840  case day_of_week::day:
14841  return "Day";
14842  case day_of_week::weekday:
14843  return "Weekday";
14845  return "WeekendDay";
14846  default:
14847  throw exception("Unexpected <DaysOfWeek>");
14848  }
14849  }
14850 
14851  inline day_of_week str_to_day_of_week(const std::string& str)
14852  {
14853  if (str == "Sunday")
14854  {
14855  return day_of_week::sun;
14856  }
14857  else if (str == "Monday")
14858  {
14859  return day_of_week::mon;
14860  }
14861  else if (str == "Tuesday")
14862  {
14863  return day_of_week::tue;
14864  }
14865  else if (str == "Wednesday")
14866  {
14867  return day_of_week::wed;
14868  }
14869  else if (str == "Thursday")
14870  {
14871  return day_of_week::thu;
14872  }
14873  else if (str == "Friday")
14874  {
14875  return day_of_week::fri;
14876  }
14877  else if (str == "Saturday")
14878  {
14879  return day_of_week::sat;
14880  }
14881  else if (str == "Day")
14882  {
14883  return day_of_week::day;
14884  }
14885  else if (str == "Weekday")
14886  {
14887  return day_of_week::weekday;
14888  }
14889  else if (str == "WeekendDay")
14890  {
14891  return day_of_week::weekend_day;
14892  }
14893  else
14894  {
14895  throw exception("Unexpected <DaysOfWeek>");
14896  }
14897  }
14898 } // namespace internal
14899 
14908 {
14910  first,
14911 
14913  second,
14914 
14916  third,
14917 
14919  fourth,
14920 
14922  last
14923 };
14924 
14925 namespace internal
14926 {
14927  inline std::string enum_to_str(day_of_week_index i)
14928  {
14929  switch (i)
14930  {
14932  return "First";
14934  return "Second";
14936  return "Third";
14938  return "Fourth";
14940  return "Last";
14941  default:
14942  throw exception("Unexpected <DayOfWeekIndex>");
14943  }
14944  }
14945 
14946  inline day_of_week_index str_to_day_of_week_index(const std::string& str)
14947  {
14948  if (str == "First")
14949  {
14950  return day_of_week_index::first;
14951  }
14952  else if (str == "Second")
14953  {
14955  }
14956  else if (str == "Third")
14957  {
14958  return day_of_week_index::third;
14959  }
14960  else if (str == "Fourth")
14961  {
14963  }
14964  else if (str == "Last")
14965  {
14966  return day_of_week_index::last;
14967  }
14968  else
14969  {
14970  throw exception("Unexpected <DayOfWeekIndex>");
14971  }
14972  }
14973 } // namespace internal
14974 
14976 class task final : public item
14977 {
14978 public:
14979 #ifdef EWS_HAS_DEFAULT_AND_DELETE
14980  task() = default;
14981 #else
14982  task() {}
14983 #endif
14984 
14986  explicit task(item_id id) : item(std::move(id)) {}
14987 
14988 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
14989  task(item_id&& id, internal::xml_subtree&& properties)
14990  : item(std::move(id), std::move(properties))
14991  {
14992  }
14993 #endif
14994 
14998  int get_actual_work() const
14999  {
15000  const auto val = xml().get_value_as_string("ActualWork");
15001  if (val.empty())
15002  {
15003  return 0;
15004  }
15005  return std::stoi(val);
15006  }
15007 
15011  void set_actual_work(int actual_work)
15012  {
15013  xml().set_or_update("ActualWork", std::to_string(actual_work));
15014  }
15015 
15022  {
15023  return date_time(xml().get_value_as_string("AssignedTime"));
15024  }
15025 
15027  std::string get_billing_information() const
15028  {
15029  return xml().get_value_as_string("BillingInformation");
15030  }
15031 
15033  void set_billing_information(const std::string& billing_info)
15034  {
15035  xml().set_or_update("BillingInformation", billing_info);
15036  }
15037 
15044  int get_change_count() const
15045  {
15046  const auto val = xml().get_value_as_string("ChangeCount");
15047  if (val.empty())
15048  {
15049  return 0;
15050  }
15051  return std::stoi(val);
15052  }
15053 
15060  std::vector<std::string> get_companies() const
15061  {
15062  return get_array_of_strings_helper("Companies");
15063  }
15064 
15069  void set_companies(const std::vector<std::string>& companies)
15070  {
15071  set_array_of_strings_helper(companies, "Companies");
15072  }
15073 
15076  {
15077  return date_time(xml().get_value_as_string("CompleteDate"));
15078  }
15079 
15081  std::vector<std::string> get_contacts() const
15082  {
15083  return get_array_of_strings_helper("Contacts");
15084  }
15085 
15087  void set_contacts(const std::vector<std::string>& contacts)
15088  {
15089  set_array_of_strings_helper(contacts, "Contacts");
15090  }
15091 
15096  {
15097  const auto& val = xml().get_value_as_string("DelegationState");
15098 
15099  if (val.empty() || val == "NoMatch")
15100  {
15102  }
15103  else if (val == "OwnNew")
15104  {
15106  }
15107  else if (val == "Owned")
15108  {
15109  return delegation_state::owned;
15110  }
15111  else if (val == "Accepted")
15112  {
15114  }
15115  else if (val == "Declined")
15116  {
15118  }
15119  else if (val == "Max")
15120  {
15121  return delegation_state::max;
15122  }
15123  else
15124  {
15125  throw exception("Unexpected <DelegationState>");
15126  }
15127  }
15128 
15130  std::string get_delegator() const
15131  {
15132  return xml().get_value_as_string("Delegator");
15133  }
15134 
15136  void set_due_date(const date_time& due_date)
15137  {
15138  xml().set_or_update("DueDate", due_date.to_string());
15139  }
15140 
15143  {
15144  return date_time(xml().get_value_as_string("DueDate"));
15145  }
15146 
15147 // TODO
15148 // This is a read-only property.
15149 #if 0
15150  int is_assignment_editable() const
15151  {
15152  // Possible values:
15153  // 0 The default for all task items
15154  // 1 A task request
15155  // 2 A task acceptance from a recipient of a task request
15156  // 3 A task declination from a recipient of a task request
15157  // 4 An update to a previous task request
15158  // 5 Not used
15159  }
15160 #endif
15161 
15166  bool is_complete() const
15167  {
15168  return xml().get_value_as_string("IsComplete") == "true";
15169  }
15170 
15172  bool is_recurring() const
15173  {
15174  return xml().get_value_as_string("IsRecurring") == "true";
15175  }
15176 
15180  bool is_team_task() const
15181  {
15182  return xml().get_value_as_string("IsTeamTask") == "true";
15183  }
15184 
15188  std::string get_mileage() const
15189  {
15190  return xml().get_value_as_string("Mileage");
15191  }
15192 
15194  void set_mileage(const std::string& mileage)
15195  {
15196  xml().set_or_update("Mileage", mileage);
15197  }
15198 
15199 // TODO: Not in AllProperties shape in EWS 2013, investigate
15200 // The name of the user who owns the task.
15201 // This is a read-only property
15202 #if 0
15203  std::string get_owner() const
15204  {
15205  return xml().get_value_as_string("Owner");
15206  }
15207 #endif
15208 
15213  {
15214  const auto val = xml().get_value_as_string("PercentComplete");
15215  if (val.empty())
15216  {
15217  return 0;
15218  }
15219  return std::stoi(val);
15220  }
15221 
15229  void set_percent_complete(int value)
15230  {
15231  xml().set_or_update("PercentComplete", std::to_string(value));
15232  }
15233 
15234  // Used for recurring tasks
15235  // TODO: get_recurrence
15236 
15238  void set_start_date(const date_time& start_date)
15239  {
15240  xml().set_or_update("StartDate", start_date.to_string());
15241  }
15242 
15245  {
15246  return date_time(xml().get_value_as_string("StartDate"));
15247  }
15248 
15251  {
15252  const auto& val = xml().get_value_as_string("Status");
15253  if (val == "NotStarted")
15254  {
15255  return status::not_started;
15256  }
15257  else if (val == "InProgress")
15258  {
15259  return status::in_progress;
15260  }
15261  else if (val == "Completed")
15262  {
15263  return status::completed;
15264  }
15265  else if (val == "WaitingOnOthers")
15266  {
15268  }
15269  else if (val == "Deferred")
15270  {
15271  return status::deferred;
15272  }
15273  else
15274  {
15275  throw exception("Unexpected <Status>");
15276  }
15277  }
15278 
15281  {
15282  xml().set_or_update("Status", internal::enum_to_str(s));
15283  }
15284 
15289  std::string get_status_description() const
15290  {
15291  return xml().get_value_as_string("StatusDescription");
15292  }
15293 
15295  int get_total_work() const
15296  {
15297  const auto val = xml().get_value_as_string("TotalWork");
15298  if (val.empty())
15299  {
15300  return 0;
15301  }
15302  return std::stoi(val);
15303  }
15304 
15306  void set_total_work(int total_work)
15307  {
15308  xml().set_or_update("TotalWork", std::to_string(total_work));
15309  }
15310 
15311  // Every property below is 2010 or 2013 dialect
15312 
15313  // TODO: add remaining properties
15314 
15316  static task from_xml_element(const rapidxml::xml_node<>& elem)
15317  {
15318  auto id_node =
15319  elem.first_node_ns(internal::uri<>::microsoft::types(), "ItemId");
15320  check(id_node, "Expected <ItemId>");
15321  return task(item_id::from_xml_element(*id_node),
15322  internal::xml_subtree(elem));
15323  }
15324 
15325 private:
15326  template <typename U> friend class basic_service;
15327 
15328  const std::string& item_tag_name() const EWS_NOEXCEPT
15329  {
15330  static const std::string name("Task");
15331  return name;
15332  }
15333 };
15334 
15335 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
15336  defined(EWS_HAS_CXX17_STATIC_ASSERT)
15337 static_assert(std::is_default_constructible<task>::value);
15338 static_assert(std::is_copy_constructible<task>::value);
15339 static_assert(std::is_copy_assignable<task>::value);
15340 static_assert(std::is_move_constructible<task>::value);
15341 static_assert(std::is_move_assignable<task>::value);
15342 #endif
15343 
15344 class complete_name final
15345 {
15346 public:
15347 #ifdef EWS_HAS_DEFAULT_AND_DELETE
15348  complete_name() = default;
15349 #else
15350  complete_name() {}
15351 #endif
15352 
15353  complete_name(std::string title, std::string firstname,
15354  std::string middlename, std::string lastname,
15355  std::string suffix, std::string initials,
15356  std::string fullname, std::string nickname)
15357  : title_(std::move(title)), firstname_(std::move(firstname)),
15358  middlename_(std::move(middlename)), lastname_(std::move(lastname)),
15359  suffix_(std::move(suffix)), initials_(std::move(initials)),
15360  fullname_(std::move(fullname)), nickname_(std::move(nickname))
15361  {
15362  }
15363 
15364  static complete_name from_xml_element(const rapidxml::xml_node<char>& node)
15365  {
15366  using namespace rapidxml::internal;
15367  std::string title;
15368  std::string firstname;
15369  std::string middlename;
15370  std::string lastname;
15371  std::string suffix;
15372  std::string initials;
15373  std::string fullname;
15374  std::string nickname;
15375  for (auto child = node.first_node(); child != nullptr;
15376  child = child->next_sibling())
15377  {
15378  if (compare("Title", strlen("Title"), child->local_name(),
15379  child->local_name_size()))
15380  {
15381  title = std::string(child->value(), child->value_size());
15382  }
15383  else if (compare("FirstName", strlen("FirstName"),
15384  child->local_name(), child->local_name_size()))
15385  {
15386  firstname = std::string(child->value(), child->value_size());
15387  }
15388  else if (compare("MiddleName", strlen("MiddleName"),
15389  child->local_name(), child->local_name_size()))
15390  {
15391  middlename = std::string(child->value(), child->value_size());
15392  }
15393  else if (compare("LastName", strlen("LastName"),
15394  child->local_name(), child->local_name_size()))
15395  {
15396  lastname = std::string(child->value(), child->value_size());
15397  }
15398  else if (compare("Suffix", strlen("Suffix"), child->local_name(),
15399  child->local_name_size()))
15400  {
15401  suffix = std::string(child->value(), child->value_size());
15402  }
15403  else if (compare("Initials", strlen("Initials"),
15404  child->local_name(), child->local_name_size()))
15405  {
15406  initials = std::string(child->value(), child->value_size());
15407  }
15408  else if (compare("FullName", strlen("FullName"),
15409  child->local_name(), child->local_name_size()))
15410  {
15411  fullname = std::string(child->value(), child->value_size());
15412  }
15413  else if (compare("Nickname", strlen("Nickname"),
15414  child->local_name(), child->local_name_size()))
15415  {
15416  nickname = std::string(child->value(), child->value_size());
15417  }
15418  }
15419 
15420  return complete_name(title, firstname, middlename, lastname, suffix,
15421  initials, fullname, nickname);
15422  }
15423 
15424  const std::string& get_title() const EWS_NOEXCEPT { return title_; }
15425  const std::string& get_first_name() const EWS_NOEXCEPT
15426  {
15427  return firstname_;
15428  }
15429  const std::string& get_middle_name() const EWS_NOEXCEPT
15430  {
15431  return middlename_;
15432  }
15433  const std::string& get_last_name() const EWS_NOEXCEPT { return lastname_; }
15434  const std::string& get_suffix() const EWS_NOEXCEPT { return suffix_; }
15435  const std::string& get_initials() const EWS_NOEXCEPT { return initials_; }
15436  const std::string& get_full_name() const EWS_NOEXCEPT { return fullname_; }
15437  const std::string& get_nickname() const EWS_NOEXCEPT { return nickname_; }
15438 
15439 private:
15440  std::string title_;
15441  std::string firstname_;
15442  std::string middlename_;
15443  std::string lastname_;
15444  std::string suffix_;
15445  std::string initials_;
15446  std::string fullname_;
15447  std::string nickname_;
15448 };
15449 
15450 class email_address final
15451 {
15452 public:
15453  enum class key
15454  {
15455  email_address_1,
15456  email_address_2,
15457  email_address_3
15458  };
15459 
15460  explicit email_address(key k, std::string value)
15461  : key_(std::move(k)), value_(std::move(value))
15462  {
15463  }
15464 
15465  static email_address
15466  from_xml_element(const rapidxml::xml_node<char>& node); // defined below
15467  std::string to_xml() const;
15468  key get_key() const EWS_NOEXCEPT { return key_; }
15469  const std::string& get_value() const EWS_NOEXCEPT { return value_; }
15470 
15471 private:
15472  key key_;
15473  std::string value_;
15474  friend bool operator==(const email_address&, const email_address&);
15475 };
15476 
15477 namespace internal
15478 {
15479  inline email_address::key
15480  str_to_email_address_key(const std::string& keystring)
15481  {
15482  email_address::key k;
15483  if (keystring == "EmailAddress1")
15484  {
15485  k = email_address::key::email_address_1;
15486  }
15487  else if (keystring == "EmailAddress2")
15488  {
15489  k = email_address::key::email_address_2;
15490  }
15491  else if (keystring == "EmailAddress3")
15492  {
15493  k = email_address::key::email_address_3;
15494  }
15495  else
15496  {
15497  throw exception("Unrecognized key: " + keystring);
15498  }
15499  return k;
15500  }
15501 
15502  inline std::string enum_to_str(email_address::key k)
15503  {
15504  switch (k)
15505  {
15506  case email_address::key::email_address_1:
15507  return "EmailAddress1";
15508  case email_address::key::email_address_2:
15509  return "EmailAddress2";
15510  case email_address::key::email_address_3:
15511  return "EmailAddress3";
15512  default:
15513  throw exception("Bad enum value");
15514  }
15515  }
15516 } // namespace internal
15517 
15518 inline email_address
15519 email_address::from_xml_element(const rapidxml::xml_node<char>& node)
15520 {
15521  using namespace internal;
15522  using rapidxml::internal::compare;
15523 
15524  // <t:EmailAddresses>
15525  // <Entry Key="EmailAddress1">donald.duck@duckburg.de</Entry>
15526  // <Entry Key="EmailAddress3">dragonmaster1999@yahoo.com</Entry>
15527  // </t:EmailAddresses>
15528 
15529  check(compare(node.local_name(), node.local_name_size(), "Entry",
15530  strlen("Entry")),
15531  "Expected <Entry> element");
15532  auto key = node.first_attribute("Key");
15533  check(key, "Expected attribute 'Key'");
15534  return email_address(
15535  str_to_email_address_key(std::string(key->value(), key->value_size())),
15536  std::string(node.value(), node.value_size()));
15537 }
15538 
15539 inline std::string email_address::to_xml() const
15540 {
15541  std::stringstream sstr;
15542  sstr << " <t:"
15543  << "EmailAddresses"
15544  << ">";
15545  sstr << " <t:Entry Key=";
15546  sstr << "\"" << internal::enum_to_str(get_key());
15547  sstr << "\">";
15548  sstr << get_value();
15549  sstr << "</t:Entry>";
15550  sstr << " </t:"
15551  << "EmailAddresses"
15552  << ">";
15553  return sstr.str();
15554 }
15555 
15556 inline bool operator==(const email_address& lhs, const email_address& rhs)
15557 {
15558  return (lhs.key_ == rhs.key_) && (lhs.value_ == rhs.value_);
15559 }
15560 
15561 class physical_address final
15562 {
15563 public:
15564  enum class key
15565  {
15566  home,
15567  business,
15568  other
15569  };
15570 
15571  physical_address(key k, std::string street, std::string city,
15572  std::string state, std::string cor,
15573  std::string postal_code)
15574  : key_(std::move(k)), street_(std::move(street)),
15575  city_(std::move(city)), state_(std::move(state)),
15576  country_or_region_(std::move(cor)),
15577  postal_code_(std::move(postal_code))
15578  {
15579  }
15580 
15581  static physical_address
15582  from_xml_element(const rapidxml::xml_node<char>& node); // defined below
15583  std::string to_xml() const;
15584  key get_key() const EWS_NOEXCEPT { return key_; }
15585  const std::string& street() const EWS_NOEXCEPT { return street_; }
15586  const std::string& city() const EWS_NOEXCEPT { return city_; }
15587  const std::string& state() const EWS_NOEXCEPT { return state_; }
15588  const std::string& country_or_region() const EWS_NOEXCEPT
15589  {
15590  return country_or_region_;
15591  }
15592  const std::string& postal_code() const EWS_NOEXCEPT { return postal_code_; }
15593 
15594 private:
15595  key key_;
15596  std::string street_;
15597  std::string city_;
15598  std::string state_;
15599  std::string country_or_region_;
15600  std::string postal_code_;
15601 
15602  friend bool operator==(const physical_address&, const physical_address&);
15603 };
15604 
15605 inline bool operator==(const physical_address& lhs, const physical_address& rhs)
15606 {
15607  return (lhs.key_ == rhs.key_) && (lhs.street_ == rhs.street_) &&
15608  (lhs.city_ == rhs.city_) && (lhs.state_ == rhs.state_) &&
15609  (lhs.country_or_region_ == rhs.country_or_region_) &&
15610  (lhs.postal_code_ == rhs.postal_code_);
15611 }
15612 
15613 namespace internal
15614 {
15615  inline physical_address::key
15616  string_to_physical_address_key(const std::string& keystring)
15617  {
15618  physical_address::key k;
15619  if (keystring == "Home")
15620  {
15621  k = physical_address::key::home;
15622  }
15623  else if (keystring == "Business")
15624  {
15625  k = physical_address::key::business;
15626  }
15627  else if (keystring == "Other")
15628  {
15629  k = physical_address::key::other;
15630  }
15631  else
15632  {
15633  throw exception("Unrecognized key: " + keystring);
15634  }
15635  return k;
15636  }
15637 
15638  inline std::string enum_to_str(physical_address::key k)
15639  {
15640  switch (k)
15641  {
15642  case physical_address::key::home:
15643  return "Home";
15644  case physical_address::key::business:
15645  return "Business";
15646  case physical_address::key::other:
15647  return "Other";
15648  default:
15649  throw exception("Bad enum value");
15650  }
15651  }
15652 } // namespace internal
15653 
15654 inline physical_address
15655 physical_address::from_xml_element(const rapidxml::xml_node<char>& node)
15656 {
15657  using namespace internal;
15658  using rapidxml::internal::compare;
15659 
15660  check(compare(node.local_name(), node.local_name_size(), "Entry",
15661  strlen("Entry")),
15662  "Expected <Entry>, got something else");
15663 
15664  // <Entry Key="Home">
15665  // <Street>
15666  // <City>
15667  // <State>
15668  // <CountryOrRegion>
15669  // <PostalCode>
15670  // </Entry>
15671 
15672  auto key_attr = node.first_attribute();
15673  check(key_attr, "Expected <Entry> to have an attribute");
15674  check(compare(key_attr->name(), key_attr->name_size(), "Key", 3),
15675  "Expected <Entry> to have an attribute 'Key'");
15676  const key key = string_to_physical_address_key(key_attr->value());
15677 
15678  std::string street;
15679  std::string city;
15680  std::string state;
15681  std::string cor;
15682  std::string postal_code;
15683 
15684  for (auto child = node.first_node(); child != nullptr;
15685  child = child->next_sibling())
15686  {
15687  if (compare("Street", strlen("Street"), child->local_name(),
15688  child->local_name_size()))
15689  {
15690  street = std::string(child->value(), child->value_size());
15691  }
15692  if (compare("City", strlen("City"), child->local_name(),
15693  child->local_name_size()))
15694  {
15695  city = std::string(child->value(), child->value_size());
15696  }
15697  if (compare("State", strlen("State"), child->local_name(),
15698  child->local_name_size()))
15699  {
15700  state = std::string(child->value(), child->value_size());
15701  }
15702  if (compare("CountryOrRegion", strlen("CountryOrRegion"),
15703  child->local_name(), child->local_name_size()))
15704  {
15705  cor = std::string(child->value(), child->value_size());
15706  }
15707  if (compare("PostalCode", strlen("PostalCode"), child->local_name(),
15708  child->local_name_size()))
15709  {
15710  postal_code = std::string(child->value(), child->value_size());
15711  }
15712  }
15713  return physical_address(key, street, city, state, cor, postal_code);
15714 }
15715 
15716 inline std::string physical_address::to_xml() const
15717 {
15718  std::stringstream sstr;
15719  sstr << " <t:"
15720  << "PhysicalAddresses"
15721  << ">";
15722  sstr << " <t:Entry Key=";
15723  sstr << "\"" << internal::enum_to_str(get_key());
15724  sstr << "\">";
15725  if (!street().empty())
15726  {
15727  sstr << "<t:Street>";
15728  sstr << street();
15729  sstr << "</t:Street>";
15730  }
15731  if (!city().empty())
15732  {
15733  sstr << "<t:City>";
15734  sstr << city();
15735  sstr << "</t:City>";
15736  }
15737  if (!state().empty())
15738  {
15739  sstr << "<t:State>";
15740  sstr << state();
15741  sstr << "</t:State>";
15742  }
15743  if (!country_or_region().empty())
15744  {
15745  sstr << "<t:CountryOrRegion>";
15746  sstr << country_or_region();
15747  sstr << "</t:CountryOrRegion>";
15748  }
15749  if (!postal_code().empty())
15750  {
15751  sstr << "<t:PostalCode>";
15752  sstr << postal_code();
15753  sstr << "</t:PostalCode>";
15754  }
15755  sstr << "</t:Entry>";
15756  sstr << " </t:"
15757  << "PhysicalAddresses"
15758  << ">";
15759  return sstr.str();
15760 }
15761 
15762 namespace internal
15763 {
15764  enum file_as_mapping
15765  {
15766  none,
15767  last_comma_first,
15768  first_space_last,
15769  company,
15770  last_comma_first_company,
15771  company_last_first,
15772  last_first,
15773  last_first_company,
15774  company_last_comma_first,
15775  last_first_suffix,
15776  last_space_first_company,
15777  company_last_space_first,
15778  last_space_first
15779  };
15780 
15781  inline file_as_mapping str_to_map(const std::string& maptype)
15782  {
15783  file_as_mapping map;
15784 
15785  if (maptype == "LastCommaFirst")
15786  {
15787  map = file_as_mapping::last_comma_first;
15788  }
15789  else if (maptype == "FirstSpaceLast")
15790  {
15791  map = file_as_mapping::first_space_last;
15792  }
15793  else if (maptype == "Company")
15794  {
15795  map = file_as_mapping::company;
15796  }
15797  else if (maptype == "LastCommaFirstCompany")
15798  {
15799  map = file_as_mapping::last_comma_first_company;
15800  }
15801  else if (maptype == "CompanyLastFirst")
15802  {
15803  map = file_as_mapping::company_last_first;
15804  }
15805  else if (maptype == "LastFirst")
15806  {
15807  map = file_as_mapping::last_first;
15808  }
15809  else if (maptype == "LastFirstCompany")
15810  {
15811  map = file_as_mapping::last_first_company;
15812  }
15813  else if (maptype == "CompanyLastCommaFirst")
15814  {
15815  map = file_as_mapping::company_last_comma_first;
15816  }
15817  else if (maptype == "LastFirstSuffix")
15818  {
15819  map = file_as_mapping::last_first_suffix;
15820  }
15821  else if (maptype == "LastSpaceFirstCompany")
15822  {
15823  map = file_as_mapping::last_space_first_company;
15824  }
15825  else if (maptype == "CompanyLastSpaceFirst")
15826  {
15827  map = file_as_mapping::company_last_space_first;
15828  }
15829  else if (maptype == "LastSpaceFirst")
15830  {
15831  map = file_as_mapping::last_space_first;
15832  }
15833  else if (maptype == "None" || maptype == "")
15834  {
15835  map = file_as_mapping::none;
15836  }
15837  else
15838  {
15839  throw exception(std::string("Unrecognized FileAsMapping Type: ") +
15840  maptype);
15841  }
15842  return map;
15843  }
15844 
15845  inline std::string enum_to_str(internal::file_as_mapping maptype)
15846  {
15847  std::string mappingtype;
15848  switch (maptype)
15849  {
15850  case file_as_mapping::none:
15851  mappingtype = "None";
15852  break;
15853  case file_as_mapping::last_comma_first:
15854  mappingtype = "LastCommaFirst";
15855  break;
15856  case file_as_mapping::first_space_last:
15857  mappingtype = "FirstSpaceLast";
15858  break;
15859  case file_as_mapping::company:
15860  mappingtype = "Company";
15861  break;
15862  case file_as_mapping::last_comma_first_company:
15863  mappingtype = "LastCommaFirstCompany";
15864  break;
15865  case file_as_mapping::company_last_first:
15866  mappingtype = "CompanyLastFirst";
15867  break;
15868  case file_as_mapping::last_first:
15869  mappingtype = "LastFirst";
15870  break;
15871  case file_as_mapping::last_first_company:
15872  mappingtype = "LastFirstCompany";
15873  break;
15874  case file_as_mapping::company_last_comma_first:
15875  mappingtype = "CompanyLastCommaFirst";
15876  break;
15877  case file_as_mapping::last_first_suffix:
15878  mappingtype = "LastFirstSuffix";
15879  break;
15880  case file_as_mapping::last_space_first_company:
15881  mappingtype = "LastSpaceFirstCompany";
15882  break;
15883  case file_as_mapping::company_last_space_first:
15884  mappingtype = "CompanyLastSpaceFirst";
15885  break;
15886  case file_as_mapping::last_space_first:
15887  mappingtype = "LastSpaceFirst";
15888  break;
15889  default:
15890  break;
15891  }
15892  return mappingtype;
15893  }
15894 } // namespace internal
15895 
15896 class im_address final
15897 {
15898 public:
15899  enum class key
15900  {
15901  imaddress1,
15902  imaddress2,
15903  imaddress3
15904  };
15905 
15906  im_address(key k, std::string value)
15907  : key_(std::move(k)), value_(std::move(value))
15908  {
15909  }
15910 
15911  static im_address from_xml_element(const rapidxml::xml_node<char>& node);
15912  std::string to_xml() const;
15913 
15914  key get_key() const EWS_NOEXCEPT { return key_; }
15915  const std::string& get_value() const EWS_NOEXCEPT { return value_; }
15916 
15917 private:
15918  key key_;
15919  std::string value_;
15920  friend bool operator==(const im_address&, const im_address&);
15921 };
15922 
15923 namespace internal
15924 {
15925  inline std::string enum_to_str(im_address::key k)
15926  {
15927  switch (k)
15928  {
15929  case im_address::key::imaddress1:
15930  return "ImAddress1";
15931  case im_address::key::imaddress2:
15932  return "ImAddress2";
15933  case im_address::key::imaddress3:
15934  return "ImAddress3";
15935  default:
15936  throw exception("Bad enum value");
15937  }
15938  }
15939 
15940  inline im_address::key str_to_im_address_key(const std::string& keystring)
15941  {
15942  im_address::key k;
15943  if (keystring == "ImAddress1")
15944  {
15945  k = im_address::key::imaddress1;
15946  }
15947  else if (keystring == "ImAddress2")
15948  {
15949  k = im_address::key::imaddress2;
15950  }
15951  else if (keystring == "ImAddress3")
15952  {
15953  k = im_address::key::imaddress3;
15954  }
15955  else
15956  {
15957  throw exception("Unrecognized key: " + keystring);
15958  }
15959  return k;
15960  }
15961 } // namespace internal
15962 
15963 inline im_address
15964 im_address::from_xml_element(const rapidxml::xml_node<char>& node)
15965 {
15966  using namespace internal;
15967  using rapidxml::internal::compare;
15968 
15969  check(compare(node.local_name(), node.local_name_size(), "Entry",
15970  strlen("Entry")),
15971  "Expected <Entry>, got something else");
15972  auto key = node.first_attribute("Key");
15973  check(key, "Expected attribute 'Key'");
15974  return im_address(
15975  str_to_im_address_key(std::string(key->value(), key->value_size())),
15976  std::string(node.value(), node.value_size()));
15977 }
15978 
15979 inline std::string im_address::to_xml() const
15980 {
15981  std::stringstream sstr;
15982  sstr << " <t:"
15983  << "ImAddresses"
15984  << ">";
15985  sstr << " <t:Entry Key=";
15986  sstr << "\"" << internal::enum_to_str(key_);
15987  sstr << "\">";
15988  sstr << get_value();
15989  sstr << "</t:Entry>";
15990  sstr << " </t:"
15991  << "ImAddresses"
15992  << ">";
15993  return sstr.str();
15994 }
15995 
15996 inline bool operator==(const im_address& lhs, const im_address& rhs)
15997 {
15998  return (lhs.key_ == rhs.key_) && (lhs.value_ == rhs.value_);
15999 }
16000 
16001 class phone_number final
16002 {
16003 public:
16004  enum class key
16005  {
16006  assistant_phone,
16007  business_fax,
16008  business_phone,
16009  business_phone_2,
16010  callback,
16011  car_phone,
16012  company_main_phone,
16013  home_fax,
16014  home_phone,
16015  home_phone_2,
16016  isdn,
16017  mobile_phone,
16018  other_fax,
16019  other_telephone,
16020  pager,
16021  primary_phone,
16022  radio_phone,
16023  telex,
16024  ttytdd_phone
16025  };
16026 
16027  phone_number(key k, std::string val)
16028  : key_(std::move(k)), value_(std::move(val))
16029  {
16030  }
16031 
16032  static phone_number from_xml_element(const rapidxml::xml_node<char>& node);
16033  std::string to_xml() const;
16034  key get_key() const EWS_NOEXCEPT { return key_; }
16035  const std::string& get_value() const EWS_NOEXCEPT { return value_; }
16036 
16037 private:
16038  key key_;
16039  std::string value_;
16040  friend bool operator==(const phone_number&, const phone_number&);
16041 };
16042 
16043 namespace internal
16044 {
16045  inline phone_number::key
16046  str_to_phone_number_key(const std::string& keystring)
16047  {
16048  phone_number::key k;
16049  if (keystring == "AssistantPhone")
16050  {
16051  k = phone_number::key::assistant_phone;
16052  }
16053  else if (keystring == "BusinessFax")
16054  {
16055  k = phone_number::key::business_fax;
16056  }
16057  else if (keystring == "BusinessPhone")
16058  {
16059  k = phone_number::key::business_phone;
16060  }
16061  else if (keystring == "BusinessPhone2")
16062  {
16063  k = phone_number::key::business_phone_2;
16064  }
16065  else if (keystring == "Callback")
16066  {
16067  k = phone_number::key::callback;
16068  }
16069  else if (keystring == "CarPhone")
16070  {
16071  k = phone_number::key::car_phone;
16072  }
16073  else if (keystring == "CompanyMainPhone")
16074  {
16075  k = phone_number::key::company_main_phone;
16076  }
16077  else if (keystring == "HomeFax")
16078  {
16079  k = phone_number::key::home_fax;
16080  }
16081  else if (keystring == "HomePhone")
16082  {
16083  k = phone_number::key::home_phone;
16084  }
16085  else if (keystring == "HomePhone2")
16086  {
16087  k = phone_number::key::home_phone_2;
16088  }
16089  else if (keystring == "Isdn")
16090  {
16091  k = phone_number::key::isdn;
16092  }
16093  else if (keystring == "MobilePhone")
16094  {
16095  k = phone_number::key::mobile_phone;
16096  }
16097  else if (keystring == "OtherFax")
16098  {
16099  k = phone_number::key::other_fax;
16100  }
16101  else if (keystring == "OtherTelephone")
16102  {
16103  k = phone_number::key::other_telephone;
16104  }
16105  else if (keystring == "Pager")
16106  {
16107  k = phone_number::key::pager;
16108  }
16109  else if (keystring == "PrimaryPhone")
16110  {
16111  k = phone_number::key::primary_phone;
16112  }
16113  else if (keystring == "RadioPhone")
16114  {
16115  k = phone_number::key::radio_phone;
16116  }
16117  else if (keystring == "Telex")
16118  {
16119  k = phone_number::key::telex;
16120  }
16121  else if (keystring == "TtyTddPhone")
16122  {
16123  k = phone_number::key::ttytdd_phone;
16124  }
16125  else
16126  {
16127  throw exception("Unrecognized key: " + keystring);
16128  }
16129  return k;
16130  }
16131 
16132  inline std::string enum_to_str(phone_number::key k)
16133  {
16134  switch (k)
16135  {
16136  case phone_number::key::assistant_phone:
16137  return "AssistantPhone";
16138  case phone_number::key::business_fax:
16139  return "BusinessFax";
16140  case phone_number::key::business_phone:
16141  return "BusinessPhone";
16142  case phone_number::key::business_phone_2:
16143  return "BusinessPhone2";
16144  case phone_number::key::callback:
16145  return "Callback";
16146  case phone_number::key::car_phone:
16147  return "CarPhone";
16148  case phone_number::key::company_main_phone:
16149  return "CompanyMainPhone";
16150  case phone_number::key::home_fax:
16151  return "HomeFax";
16152  case phone_number::key::home_phone:
16153  return "HomePhone";
16154  case phone_number::key::home_phone_2:
16155  return "HomePhone2";
16156  case phone_number::key::isdn:
16157  return "Isdn";
16158  case phone_number::key::mobile_phone:
16159  return "MobilePhone";
16160  case phone_number::key::other_fax:
16161  return "OtherFax";
16162  case phone_number::key::other_telephone:
16163  return "OtherTelephone";
16164  case phone_number::key::pager:
16165  return "Pager";
16166  case phone_number::key::primary_phone:
16167  return "PrimaryPhone";
16168  case phone_number::key::radio_phone:
16169  return "RadioPhone";
16170  case phone_number::key::telex:
16171  return "Telex";
16172  case phone_number::key::ttytdd_phone:
16173  return "TtyTddPhone";
16174  default:
16175  throw exception("Bad enum value");
16176  }
16177  }
16178 } // namespace internal
16179 
16180 inline phone_number
16181 phone_number::from_xml_element(const rapidxml::xml_node<char>& node)
16182 {
16183  using namespace internal;
16184  using rapidxml::internal::compare;
16185 
16186  // <t:PhoneNumbers>
16187  // <Entry Key="AssistantPhone">0123456789</Entry>
16188  // <Entry Key="BusinessFax">9876543210</Entry>
16189  // </t:PhoneNumbers>
16190 
16191  check(compare(node.local_name(), node.local_name_size(), "Entry",
16192  strlen("Entry")),
16193  "Expected <Entry>, got something else");
16194  auto key = node.first_attribute("Key");
16195  check(key, "Expected attribute 'Key'");
16196  return phone_number(
16197  str_to_phone_number_key(std::string(key->value(), key->value_size())),
16198  std::string(node.value(), node.value_size()));
16199 }
16200 
16201 inline std::string phone_number::to_xml() const
16202 {
16203  std::stringstream sstr;
16204  sstr << " <t:"
16205  << "PhoneNumbers"
16206  << ">";
16207  sstr << " <t:Entry Key=";
16208  sstr << "\"" << internal::enum_to_str(key_);
16209  sstr << "\">";
16210  sstr << get_value();
16211  sstr << "</t:Entry>";
16212  sstr << " </t:"
16213  << "PhoneNumbers"
16214  << ">";
16215  return sstr.str();
16216 }
16217 
16218 inline bool operator==(const phone_number& lhs, const phone_number& rhs)
16219 {
16220  return (lhs.key_ == rhs.key_) && (lhs.value_ == rhs.value_);
16221 }
16222 
16224 class contact final : public item
16225 {
16226 public:
16227 #ifdef EWS_HAS_DEFAULT_AND_DELETE
16228  contact() = default;
16229 #else
16230  contact() {}
16231 #endif
16232 
16233  explicit contact(item_id id) : item(id) {}
16234 
16235 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
16236  contact(item_id&& id, internal::xml_subtree&& properties)
16237  : item(std::move(id), std::move(properties))
16238  {
16239  }
16240 #endif
16241 
16243  void set_file_as(const std::string& fileas)
16244  {
16245  xml().set_or_update("FileAs", fileas);
16246  }
16247 
16248  std::string get_file_as() const
16249  {
16250  return xml().get_value_as_string("FileAs");
16251  }
16252 
16256  void set_file_as_mapping(internal::file_as_mapping maptype)
16257  {
16258  auto mapping = internal::enum_to_str(maptype);
16259  xml().set_or_update("FileAsMapping", mapping);
16260  }
16261 
16262  internal::file_as_mapping get_file_as_mapping() const
16263  {
16264  return internal::str_to_map(xml().get_value_as_string("FileAsMapping"));
16265  }
16266 
16268  void set_display_name(const std::string& display_name)
16269  {
16270  xml().set_or_update("DisplayName", display_name);
16271  }
16272 
16274  std::string get_display_name() const
16275  {
16276  return xml().get_value_as_string("DisplayName");
16277  }
16278 
16281  void set_given_name(const std::string& given_name)
16282  {
16283  xml().set_or_update("GivenName", given_name);
16284  }
16285 
16287  std::string get_given_name() const
16288  {
16289  return xml().get_value_as_string("GivenName");
16290  }
16291 
16293  void set_initials(const std::string& initials)
16294  {
16295  xml().set_or_update("Initials", initials);
16296  }
16297 
16299  std::string get_initials() const
16300  {
16301  return xml().get_value_as_string("Initials");
16302  }
16303 
16305  void set_middle_name(const std::string& middle_name)
16306  {
16307  xml().set_or_update("MiddleName", middle_name);
16308  }
16309 
16311  std::string get_middle_name() const
16312  {
16313  return xml().get_value_as_string("MiddleName");
16314  }
16315 
16317  void set_nickname(const std::string& nickname)
16318  {
16319  xml().set_or_update("Nickname", nickname);
16320  }
16321 
16323  std::string get_nickname() const
16324  {
16325  return xml().get_value_as_string("Nickname");
16326  }
16327 
16330  {
16331  auto node = xml().get_node("CompleteName");
16332  if (node == nullptr)
16333  {
16334  return complete_name();
16335  }
16336  return complete_name::from_xml_element(*node);
16337  }
16338 
16340  void set_company_name(const std::string& company_name)
16341  {
16342  xml().set_or_update("CompanyName", company_name);
16343  }
16344 
16346  std::string get_company_name() const
16347  {
16348  return xml().get_value_as_string("CompanyName");
16349  }
16350 
16352  std::vector<email_address> get_email_addresses() const
16353  {
16354  const auto addresses = xml().get_node("EmailAddresses");
16355  if (!addresses)
16356  {
16357  return std::vector<email_address>();
16358  }
16359  std::vector<email_address> result;
16360  for (auto entry = addresses->first_node(); entry != nullptr;
16361  entry = entry->next_sibling())
16362  {
16363  result.push_back(email_address::from_xml_element(*entry));
16364  }
16365  return result;
16366  }
16367 
16368  void set_email_address(const email_address& address)
16369  {
16370  using internal::create_node;
16371  using rapidxml::internal::compare;
16372  auto doc = xml().document();
16373  auto email_addresses = xml().get_node("EmailAddresses");
16374 
16375  if (email_addresses)
16376  {
16377  bool entry_exists = false;
16378  auto entry = email_addresses->first_node();
16379  for (; entry != nullptr; entry = entry->next_sibling())
16380  {
16381  auto key_attr = entry->first_attribute();
16382  check(key_attr, "Expected an attribute");
16383  check(
16384  compare(key_attr->name(), key_attr->name_size(), "Key", 3),
16385  "Expected an attribute 'Key'");
16386  const auto key = internal::enum_to_str(address.get_key());
16387  if (compare(key_attr->value(), key_attr->value_size(),
16388  key.c_str(), key.size()))
16389  {
16390  entry_exists = true;
16391  break;
16392  }
16393  }
16394  if (entry_exists)
16395  {
16396  email_addresses->remove_node(entry);
16397  }
16398  }
16399  else
16400  {
16401  email_addresses = &create_node(*doc, "t:EmailAddresses");
16402  }
16403 
16404  // create entry & key
16405  const auto value = address.get_value();
16406  auto new_entry = &create_node(*email_addresses, "t:Entry", value);
16407  auto ptr_to_key = doc->allocate_string("Key");
16408  const auto key = internal::enum_to_str(address.get_key());
16409  auto ptr_to_value = doc->allocate_string(key.c_str());
16410  new_entry->append_attribute(
16411  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16412  }
16413 
16415  std::vector<physical_address> get_physical_addresses() const
16416  {
16417  const auto addresses = xml().get_node("PhysicalAddresses");
16418  if (!addresses)
16419  {
16420  return std::vector<physical_address>();
16421  }
16422  std::vector<physical_address> result;
16423  for (auto entry = addresses->first_node(); entry != nullptr;
16424  entry = entry->next_sibling())
16425  {
16426  result.push_back(physical_address::from_xml_element(*entry));
16427  }
16428  return result;
16429  }
16430 
16431  void set_physical_address(const physical_address& address)
16432  {
16433  using internal::create_node;
16434  using rapidxml::internal::compare;
16435  auto doc = xml().document();
16436  auto addresses = xml().get_node("PhysicalAddresses");
16437  // <PhysicalAddresses>
16438  // <Entry Key="Home">
16439  // <Street>
16440  // <City>
16441  // <State>
16442  // <CountryOrRegion>
16443  // <PostalCode>
16444  // <Entry/>
16445  // <Entry Key="Business">
16446  // <Street>
16447  // <City>
16448  // <State>
16449  // <CountryOrRegion>
16450  // <PostalCode>
16451  // <Entry/>
16452  // <PhysicalAddresses/>
16453 
16454  if (addresses)
16455  {
16456  bool entry_exists = false;
16457  auto entry = addresses->first_node();
16458  for (; entry != nullptr; entry = entry->next_sibling())
16459  {
16460  auto key_attr = entry->first_attribute();
16461  check(key_attr, "Expected an attribute");
16462  check(
16463  compare(key_attr->name(), key_attr->name_size(), "Key", 3),
16464  "Expected an attribute 'Key'");
16465  const auto key = internal::enum_to_str(address.get_key());
16466  if (compare(key_attr->value(), key_attr->value_size(),
16467  key.c_str(), key.size()))
16468  {
16469  entry_exists = true;
16470  break;
16471  }
16472  }
16473  if (entry_exists)
16474  {
16475  addresses->remove_node(entry);
16476  }
16477  }
16478  else
16479  {
16480  addresses = &create_node(*doc, "t:PhysicalAddresses");
16481  }
16482 
16483  // create entry & key
16484  auto new_entry = &create_node(*addresses, "t:Entry");
16485 
16486  auto ptr_to_key = doc->allocate_string("Key");
16487  auto keystr = internal::enum_to_str(address.get_key());
16488  auto ptr_to_value = doc->allocate_string(keystr.c_str());
16489  new_entry->append_attribute(
16490  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16491 
16492  if (!address.street().empty())
16493  {
16494  create_node(*new_entry, "t:Street", address.street());
16495  }
16496  if (!address.city().empty())
16497  {
16498  create_node(*new_entry, "t:City", address.city());
16499  }
16500  if (!address.state().empty())
16501  {
16502  create_node(*new_entry, "t:State", address.state());
16503  }
16504  if (!address.country_or_region().empty())
16505  {
16506  create_node(*new_entry, "t:CountryOrRegion",
16507  address.country_or_region());
16508  }
16509  if (!address.postal_code().empty())
16510  {
16511  create_node(*new_entry, "t:PostalCode", address.postal_code());
16512  }
16513  }
16514 
16515  // A collection of phone numbers for the contact
16516  void set_phone_number(const phone_number& number)
16517  {
16518  using internal::create_node;
16519  using rapidxml::internal::compare;
16520  auto doc = xml().document();
16521  auto phone_numbers = xml().get_node("PhoneNumbers");
16522 
16523  if (phone_numbers)
16524  {
16525  bool entry_exists = false;
16526  auto entry = phone_numbers->first_node();
16527  for (; entry != nullptr; entry = entry->next_sibling())
16528  {
16529  auto key_attr = entry->first_attribute();
16530  check(key_attr, "Expected an attribute");
16531  check(
16532  compare(key_attr->name(), key_attr->name_size(), "Key", 3),
16533  "Expected an attribute 'Key'");
16534  const auto key = internal::enum_to_str(number.get_key());
16535  if (compare(key_attr->value(), key_attr->value_size(),
16536  key.c_str(), key.size()))
16537  {
16538  entry_exists = true;
16539  break;
16540  }
16541  }
16542  if (entry_exists)
16543  {
16544  phone_numbers->remove_node(entry);
16545  }
16546  }
16547  else
16548  {
16549  phone_numbers = &create_node(*doc, "t:PhoneNumbers");
16550  }
16551 
16552  // create entry & key
16553  const auto value = number.get_value();
16554  auto new_entry = &create_node(*phone_numbers, "t:Entry", value);
16555  auto ptr_to_key = doc->allocate_string("Key");
16556  const auto key = internal::enum_to_str(number.get_key());
16557  auto ptr_to_value = doc->allocate_string(key.c_str());
16558  new_entry->append_attribute(
16559  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16560  }
16561 
16562  std::vector<phone_number> get_phone_numbers() const
16563  {
16564  const auto numbers = xml().get_node("PhoneNumbers");
16565  if (!numbers)
16566  {
16567  return std::vector<phone_number>();
16568  }
16569  std::vector<phone_number> result;
16570  for (auto entry = numbers->first_node(); entry != nullptr;
16571  entry = entry->next_sibling())
16572  {
16573  result.push_back(phone_number::from_xml_element(*entry));
16574  }
16575  return result;
16576  }
16577 
16579  void set_assistant_name(const std::string& assistant_name)
16580  {
16581  xml().set_or_update("AssistantName", assistant_name);
16582  }
16583 
16585  std::string get_assistant_name() const
16586  {
16587  return xml().get_value_as_string("AssistantName");
16588  }
16589 
16591  // Be careful with the formating of the date string
16592  // It has to be in the format YYYY-MM-DD(THH:MM:SSZ) <- can be left out
16593  // if the time of the day isn't important, will automatically be set to
16594  // YYYY-MM-DDT00:00:00Z
16595  //
16596  // This also applies to any other contact property with a date type
16597  // string
16598  void set_birthday(const std::string& birthday)
16599  {
16600  xml().set_or_update("Birthday", birthday);
16601  }
16602 
16603  std::string get_birthday() const
16604  {
16605  return xml().get_value_as_string("Birthday");
16606  }
16607 
16609  void set_business_homepage(const std::string& business_homepage)
16610  {
16611  xml().set_or_update("BusinessHomePage", business_homepage);
16612  }
16613 
16615  std::string get_business_homepage() const
16616  {
16617  return xml().get_value_as_string("BusinessHomePage");
16618  }
16619 
16621  void set_children(const std::vector<std::string>& children)
16622  {
16623  set_array_of_strings_helper(children, "Children");
16624  }
16625 
16626  std::vector<std::string> get_children() const
16627  {
16628  return get_array_of_strings_helper("Children");
16629  }
16630 
16632  void set_companies(const std::vector<std::string>& companies)
16633  {
16634  set_array_of_strings_helper(companies, "Companies");
16635  }
16636 
16637  std::vector<std::string> get_companies() const
16638  {
16639  return get_array_of_strings_helper("Companies");
16640  }
16641 
16645  std::string get_contact_source() const
16646  {
16647  return xml().get_value_as_string("ContactSource");
16648  }
16649 
16651  void set_department(const std::string& department)
16652  {
16653  xml().set_or_update("Department", department);
16654  }
16655 
16657  std::string get_department() const
16658  {
16659  return xml().get_value_as_string("Department");
16660  }
16661 
16664  void set_generation(const std::string& generation)
16665  {
16666  xml().set_or_update("Generation", generation);
16667  }
16668 
16670  std::string get_generation() const
16671  {
16672  return xml().get_value_as_string("Generation");
16673  }
16674 
16676 
16678  {
16679  using internal::create_node;
16680  using rapidxml::internal::compare;
16681  auto doc = xml().document();
16682  auto im_addresses = xml().get_node("ImAddresses");
16683 
16684  if (im_addresses)
16685  {
16686  bool entry_exists = false;
16687  auto entry = im_addresses->first_node();
16688  for (; entry != nullptr; entry = entry->next_sibling())
16689  {
16690  auto key_attr = entry->first_attribute();
16691  check(key_attr, "Expected an attribute");
16692  check(
16693  compare(key_attr->name(), key_attr->name_size(), "Key", 3),
16694  "Expected an attribute 'Key'");
16695  const auto key = internal::enum_to_str(im_address.get_key());
16696  if (compare(key_attr->value(), key_attr->value_size(),
16697  key.c_str(), key.size()))
16698  {
16699  entry_exists = true;
16700  break;
16701  }
16702  }
16703  if (entry_exists)
16704  {
16705  im_addresses->remove_node(entry);
16706  }
16707  }
16708  else
16709  {
16710  im_addresses = &create_node(*doc, "t:ImAddresses");
16711  }
16712 
16713  // create entry & key
16714  const auto value = im_address.get_value();
16715  auto new_entry = &create_node(*im_addresses, "t:Entry", value);
16716  auto ptr_to_key = doc->allocate_string("Key");
16717  const auto key = internal::enum_to_str(im_address.get_key());
16718  auto ptr_to_value = doc->allocate_string(key.c_str());
16719  new_entry->append_attribute(
16720  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16721  }
16722 
16723  std::vector<im_address> get_im_addresses() const
16724  {
16725  const auto addresses = xml().get_node("ImAddresses");
16726  if (!addresses)
16727  {
16728  return std::vector<im_address>();
16729  }
16730  std::vector<im_address> result;
16731  for (auto entry = addresses->first_node(); entry != nullptr;
16732  entry = entry->next_sibling())
16733  {
16734  result.push_back(im_address::from_xml_element(*entry));
16735  }
16736  return result;
16737  }
16738 
16740  void set_job_title(const std::string& title)
16741  {
16742  xml().set_or_update("JobTitle", title);
16743  }
16744 
16746  std::string get_job_title() const
16747  {
16748  return xml().get_value_as_string("JobTitle");
16749  }
16750 
16752  void set_manager(const std::string& manager)
16753  {
16754  xml().set_or_update("Manager", manager);
16755  }
16756 
16758  std::string get_manager() const
16759  {
16760  return xml().get_value_as_string("Manager");
16761  }
16762 
16765  void set_mileage(const std::string& mileage)
16766  {
16767  xml().set_or_update("Mileage", mileage);
16768  }
16769 
16771  std::string get_mileage() const
16772  {
16773  return xml().get_value_as_string("Mileage");
16774  }
16775 
16777  void set_office_location(const std::string& office_location)
16778  {
16779  xml().set_or_update("OfficeLocation", office_location);
16780  }
16781 
16783  std::string get_office_location() const
16784  {
16785  return xml().get_value_as_string("OfficeLocation");
16786  }
16787 
16788  // The physical addresses in the PhysicalAddresses collection that
16789  // represents the mailing address for the contact
16790  // TODO: get_postal_address_index
16791 
16793  void set_profession(const std::string& profession)
16794  {
16795  xml().set_or_update("Profession", profession);
16796  }
16797 
16799  std::string get_profession() const
16800  {
16801  return xml().get_value_as_string("Profession");
16802  }
16803 
16805  void set_spouse_name(const std::string& spouse_name)
16806  {
16807  xml().set_or_update("SpouseName", spouse_name);
16808  }
16809 
16811  std::string get_spouse_name() const
16812  {
16813  return xml().get_value_as_string("SpouseName");
16814  }
16815 
16818  void set_surname(const std::string& surname)
16819  {
16820  xml().set_or_update("Surname", surname);
16821  }
16822 
16825  std::string get_surname() const
16826  {
16827  return xml().get_value_as_string("Surname");
16828  }
16829 
16831  void set_wedding_anniversary(const std::string& anniversary)
16832  {
16833  xml().set_or_update("WeddingAnniversary", anniversary);
16834  }
16835 
16836  std::string get_wedding_anniversary() const
16837  {
16838  return xml().get_value_as_string("WeddingAnniversary");
16839  }
16840 
16841  // Everything below is beyond EWS 2007 subset
16842 
16843  // has_picture
16844  // phonetic_full_name
16845  // phonetic_first_name
16846  // phonetic_last_name
16847  // alias
16848  // notes
16849  // photo
16850  // user_smime_certificate
16851  // msexchange_certificate
16852  // directory_id
16853  // manager_mailbox
16854  // direct_reports
16855 
16856  std::string get_user_smime_certificate() const
16857  {
16858  const auto node = xml().get_node("UserSMIMECertificate");
16859  if (!node)
16860  {
16861  return "";
16862  }
16863  auto base64binary = node->first_node_ns(
16864  internal::uri<>::microsoft::types(), "Base64Binary");
16865  return base64binary ? std::string(base64binary->value(),
16866  base64binary->value_size())
16867  : "";
16868  }
16869 
16870  std::string get_msexchange_certificate() const
16871  {
16872  const auto node = xml().get_node("MSExchangeCertificate");
16873  if (!node)
16874  {
16875  return "";
16876  }
16877  auto base64binary = node->first_node_ns(
16878  internal::uri<>::microsoft::types(), "Base64Binary");
16879  return base64binary ? std::string(base64binary->value(),
16880  base64binary->value_size())
16881  : "";
16882  }
16883 
16885  static contact from_xml_element(const rapidxml::xml_node<>& elem)
16886  {
16887  auto id_node =
16888  elem.first_node_ns(internal::uri<>::microsoft::types(), "ItemId");
16889  check(id_node, "Expected <ItemId>");
16890  return contact(item_id::from_xml_element(*id_node),
16891  internal::xml_subtree(elem));
16892  }
16893 
16896  static contact
16897  from_xml_element_without_item_id(const rapidxml::xml_node<>& elem)
16898  {
16899  item_id id;
16900  return contact(std::move(id), internal::xml_subtree(elem));
16901  }
16902 
16903 private:
16904  template <typename U> friend class basic_service;
16905 
16906  const std::string& item_tag_name() const EWS_NOEXCEPT
16907  {
16908  static const std::string name("Contact");
16909  return name;
16910  }
16911 
16912  // Helper function for get_email_address_{1,2,3}
16913  std::string get_email_address_by_key(const char* key) const
16914  {
16915  using rapidxml::internal::compare;
16916 
16917  // <Entry Key="" Name="" RoutingType="" MailboxType="" />
16918  const auto addresses = xml().get_node("EmailAddresses");
16919  if (!addresses)
16920  {
16921  return "";
16922  }
16923  for (auto entry = addresses->first_node(); entry;
16924  entry = entry->next_sibling())
16925  {
16926  for (auto attr = entry->first_attribute(); attr;
16927  attr = attr->next_attribute())
16928  {
16929  if (compare(attr->name(), attr->name_size(), "Key", 3) &&
16930  compare(attr->value(), attr->value_size(), key,
16931  strlen(key)))
16932  {
16933  return std::string(entry->value(), entry->value_size());
16934  }
16935  }
16936  }
16937  // None with such key
16938  return "";
16939  }
16940 
16941  // Helper function for set_email_address_{1,2,3}
16942  void set_email_address_by_key(const char* key, mailbox&& mail)
16943  {
16944  using internal::create_node;
16945  using rapidxml::internal::compare;
16946 
16947  auto doc = xml().document();
16948  auto addresses = xml().get_node("EmailAddresses");
16949  if (addresses)
16950  {
16951  // Check if there is already any entry for given key
16952 
16953  bool exists = false;
16954  auto entry = addresses->first_node();
16955  for (; entry && !exists; entry = entry->next_sibling())
16956  {
16957  for (auto attr = entry->first_attribute(); attr;
16958  attr = attr->next_attribute())
16959  {
16960  if (compare(attr->name(), attr->name_size(), "Key", 3) &&
16961  compare(attr->value(), attr->value_size(), key,
16962  strlen(key)))
16963  {
16964  exists = true;
16965  break;
16966  }
16967  }
16968  }
16969  if (exists)
16970  {
16971  addresses->remove_node(entry);
16972  }
16973  }
16974  else
16975  {
16976  // Need to construct <EmailAddresses> node first
16977  addresses = &create_node(*doc, "t:EmailAddresses");
16978  }
16979 
16980  // <Entry Key="" Name="" RoutingType="" MailboxType="" />
16981  auto new_entry = &create_node(*addresses, "t:Entry", mail.value());
16982  auto ptr_to_key = doc->allocate_string("Key");
16983  auto ptr_to_value = doc->allocate_string(key);
16984  new_entry->append_attribute(
16985  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16986  if (!mail.name().empty())
16987  {
16988  ptr_to_key = doc->allocate_string("Name");
16989  ptr_to_value = doc->allocate_string(mail.name().c_str());
16990  new_entry->append_attribute(
16991  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16992  }
16993  if (!mail.routing_type().empty())
16994  {
16995  ptr_to_key = doc->allocate_string("RoutingType");
16996  ptr_to_value = doc->allocate_string(mail.routing_type().c_str());
16997  new_entry->append_attribute(
16998  doc->allocate_attribute(ptr_to_key, ptr_to_value));
16999  }
17000  if (!mail.mailbox_type().empty())
17001  {
17002  ptr_to_key = doc->allocate_string("MailboxType");
17003  ptr_to_value = doc->allocate_string(mail.mailbox_type().c_str());
17004  new_entry->append_attribute(
17005  doc->allocate_attribute(ptr_to_key, ptr_to_value));
17006  }
17007  }
17008 };
17009 
17010 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17011  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17012 static_assert(std::is_default_constructible<contact>::value);
17013 static_assert(std::is_copy_constructible<contact>::value);
17014 static_assert(std::is_copy_assignable<contact>::value);
17015 static_assert(std::is_move_constructible<contact>::value);
17016 static_assert(std::is_move_assignable<contact>::value);
17017 #endif
17018 
17025 class occurrence_info final
17026 {
17027 public:
17028 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17029  occurrence_info() = default;
17030 #else
17031  occurrence_info() {}
17032 #endif
17033 
17034  occurrence_info(item_id id, date_time start, date_time end,
17035  date_time original_start)
17036  : item_id_(std::move(id)), start_(std::move(start)),
17037  end_(std::move(end)), original_start_(std::move(original_start))
17038  {
17039  }
17040 
17042  bool none() const EWS_NOEXCEPT { return !item_id_.valid(); }
17043 
17044  const item_id& get_item_id() const EWS_NOEXCEPT { return item_id_; }
17045 
17046  const date_time& get_start() const EWS_NOEXCEPT { return start_; }
17047 
17048  const date_time& get_end() const EWS_NOEXCEPT { return end_; }
17049 
17050  const date_time& get_original_start() const EWS_NOEXCEPT
17051  {
17052  return original_start_;
17053  }
17054 
17057  static occurrence_info from_xml_element(const rapidxml::xml_node<>& elem)
17058  {
17059  using rapidxml::internal::compare;
17060 
17061  date_time original_start;
17062  date_time end;
17063  date_time start;
17064  item_id id;
17065 
17066  for (auto node = elem.first_node(); node; node = node->next_sibling())
17067  {
17068  if (compare(node->local_name(), node->local_name_size(),
17069  "OriginalStart", strlen("OriginalStart")))
17070  {
17071  original_start =
17072  date_time(std::string(node->value(), node->value_size()));
17073  }
17074  else if (compare(node->local_name(), node->local_name_size(), "End",
17075  strlen("End")))
17076  {
17077  end = date_time(std::string(node->value(), node->value_size()));
17078  }
17079  else if (compare(node->local_name(), node->local_name_size(),
17080  "Start", strlen("Start")))
17081  {
17082  start =
17083  date_time(std::string(node->value(), node->value_size()));
17084  }
17085  else if (compare(node->local_name(), node->local_name_size(),
17086  "ItemId", strlen("ItemId")))
17087  {
17088  id = item_id::from_xml_element(*node);
17089  }
17090  else
17091  {
17092  throw exception("Unexpected child element in <Mailbox>");
17093  }
17094  }
17095 
17096  return occurrence_info(std::move(id), std::move(start), std::move(end),
17097  std::move(original_start));
17098  }
17099 
17100 private:
17101  item_id item_id_;
17102  date_time start_;
17103  date_time end_;
17104  date_time original_start_;
17105 };
17106 
17107 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17108  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17109 static_assert(std::is_default_constructible<occurrence_info>::value);
17110 static_assert(std::is_copy_constructible<occurrence_info>::value);
17111 static_assert(std::is_copy_assignable<occurrence_info>::value);
17112 static_assert(std::is_move_constructible<occurrence_info>::value);
17113 static_assert(std::is_move_assignable<occurrence_info>::value);
17114 #endif
17115 
17118 {
17119 public:
17120 virtual std::string get_occurence_name() { return "recurrence_pattern"; }
17121 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17122  virtual ~recurrence_pattern() = default;
17123 
17124  recurrence_pattern(const recurrence_pattern&) = delete;
17125  recurrence_pattern& operator=(const recurrence_pattern&) = delete;
17126 #else
17127  virtual ~recurrence_pattern() {}
17128 
17129 private:
17131  recurrence_pattern& operator=(const recurrence_pattern&);
17132 
17133 public:
17134 #endif
17135 
17136  std::string to_xml() const { return this->to_xml_impl(); }
17137 
17142  rapidxml::xml_node<>& to_xml_element(rapidxml::xml_node<>& parent) const
17143  {
17144  return this->to_xml_element_impl(parent);
17145  }
17146 
17149  static std::unique_ptr<recurrence_pattern>
17150  from_xml_element(const rapidxml::xml_node<>& elem); // Defined below
17151 
17152 protected:
17153 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17154  recurrence_pattern() = default;
17155 #else
17156  recurrence_pattern() {}
17157 #endif
17158 
17159 private:
17160  virtual std::string to_xml_impl() const = 0;
17161 
17162  virtual rapidxml::xml_node<>&
17163  to_xml_element_impl(rapidxml::xml_node<>&) const = 0;
17164 };
17165 
17166 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17167  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17168 static_assert(!std::is_default_constructible<recurrence_pattern>::value);
17169 static_assert(!std::is_copy_constructible<recurrence_pattern>::value);
17170 static_assert(!std::is_copy_assignable<recurrence_pattern>::value);
17171 static_assert(!std::is_move_constructible<recurrence_pattern>::value);
17172 static_assert(!std::is_move_assignable<recurrence_pattern>::value);
17173 #endif
17174 
17181 {
17182 public:
17184  day_of_week_index index, month m)
17185  : days_of_week_(days_of_week), index_(index), month_(m)
17186  {
17187  }
17188 
17189  std::string get_occurence_name() override
17190  {
17191  return "relative_yearly_recurrence";
17192  }
17193 
17194  day_of_week get_days_of_week() const EWS_NOEXCEPT { return days_of_week_; }
17195 
17196  day_of_week_index get_day_of_week_index() const EWS_NOEXCEPT
17197  {
17198  return index_;
17199  }
17200 
17201  month get_month() const EWS_NOEXCEPT { return month_; }
17202 
17203 private:
17204  day_of_week days_of_week_;
17205  day_of_week_index index_;
17206  month month_;
17207 
17208  std::string to_xml_impl() const override
17209  {
17210  using namespace internal;
17211 
17212  std::stringstream sstr;
17213  sstr << "<t:RelativeYearlyRecurrence>"
17214  << "<t:DaysOfWeek>" << enum_to_str(days_of_week_)
17215  << "</t:DaysOfWeek>"
17216  << "<t:DayOfWeekIndex>" << enum_to_str(index_)
17217  << "</t:DayOfWeekIndex>"
17218  << "<t:Month>" << enum_to_str(month_) << "</t:Month>"
17219  << "</t:RelativeYearlyRecurrence>";
17220  return sstr.str();
17221  }
17222 
17223  rapidxml::xml_node<>&
17224  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17225  {
17226  check(parent.document(), "Parent node needs to be part of a document");
17227 
17228  using namespace internal;
17229  auto& pattern_node = create_node(parent, "t:RelativeYearlyRecurrence");
17230  create_node(pattern_node, "t:DaysOfWeek", enum_to_str(days_of_week_));
17231  create_node(pattern_node, "t:DayOfWeekIndex", enum_to_str(index_));
17232  create_node(pattern_node, "t:Month", enum_to_str(month_));
17233  return pattern_node;
17234  }
17235 };
17236 
17237 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17238  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17239 static_assert(
17240  !std::is_default_constructible<relative_yearly_recurrence>::value);
17241 static_assert(!std::is_copy_constructible<relative_yearly_recurrence>::value);
17242 static_assert(!std::is_copy_assignable<relative_yearly_recurrence>::value);
17243 static_assert(!std::is_move_constructible<relative_yearly_recurrence>::value);
17244 static_assert(!std::is_move_assignable<relative_yearly_recurrence>::value);
17245 #endif
17246 
17249 {
17250 public:
17251  absolute_yearly_recurrence(uint32_t day_of_month, month m)
17252  : day_of_month_(day_of_month), month_(m)
17253  {
17254  }
17255 
17256  std::string get_occurence_name() override
17257  {
17258  return "absolute_yearly_recurrence";
17259  }
17260 
17261  uint32_t get_day_of_month() const EWS_NOEXCEPT { return day_of_month_; }
17262 
17263  month get_month() const EWS_NOEXCEPT { return month_; }
17264 
17265 private:
17266  uint32_t day_of_month_;
17267  month month_;
17268 
17269  std::string to_xml_impl() const override
17270  {
17271  using namespace internal;
17272 
17273  std::stringstream sstr;
17274  sstr << "<t:AbsoluteYearlyRecurrence>"
17275  << "<t:DayOfMonth>" << day_of_month_ << "</t:DayOfMonth>"
17276  << "<t:Month>" << enum_to_str(month_) << "</t:Month>"
17277  << "</t:AbsoluteYearlyRecurrence>";
17278  return sstr.str();
17279  }
17280 
17281  rapidxml::xml_node<>&
17282  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17283  {
17284  using namespace internal;
17285  check(parent.document(), "Parent node needs to be part of a document");
17286 
17287  auto& pattern_node = create_node(parent, "t:AbsoluteYearlyRecurrence");
17288  create_node(pattern_node, "t:DayOfMonth",
17289  std::to_string(day_of_month_));
17290  create_node(pattern_node, "t:Month", internal::enum_to_str(month_));
17291  return pattern_node;
17292  }
17293 };
17294 
17295 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17296  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17297 static_assert(
17298  !std::is_default_constructible<absolute_yearly_recurrence>::value);
17299 static_assert(!std::is_copy_constructible<absolute_yearly_recurrence>::value);
17300 static_assert(!std::is_copy_assignable<absolute_yearly_recurrence>::value);
17301 static_assert(!std::is_move_constructible<absolute_yearly_recurrence>::value);
17302 static_assert(!std::is_move_assignable<absolute_yearly_recurrence>::value);
17303 #endif
17304 
17320 {
17321 public:
17322  absolute_monthly_recurrence(uint32_t interval, uint32_t day_of_month)
17323  : interval_(interval), day_of_month_(day_of_month)
17324  {
17325  }
17326 
17327  std::string get_occurence_name() override
17328  {
17329  return "absolute_monthly_recurrence";
17330  }
17331 
17332  uint32_t get_interval() const EWS_NOEXCEPT { return interval_; }
17333 
17334  uint32_t get_days_of_month() const EWS_NOEXCEPT { return day_of_month_; }
17335 
17336 private:
17337  uint32_t interval_;
17338  uint32_t day_of_month_;
17339 
17340  std::string to_xml_impl() const override
17341  {
17342  using namespace internal;
17343 
17344  std::stringstream sstr;
17345  sstr << "<t:AbsoluteMonthlyRecurrence>"
17346  << "<t:Interval>" << interval_ << "</t:Interval>"
17347  << "<t:DayOfMonth>" << day_of_month_ << "</t:DayOfMonth>"
17348  << "</t:AbsoluteMonthlyRecurrence>";
17349  return sstr.str();
17350  }
17351 
17352  rapidxml::xml_node<>&
17353  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17354  {
17355  using internal::create_node;
17356  check(parent.document(), "Parent node needs to be part of a document");
17357 
17358  auto& pattern_node = create_node(parent, "t:AbsoluteMonthlyRecurrence");
17359  create_node(pattern_node, "t:Interval", std::to_string(interval_));
17360  create_node(pattern_node, "t:DayOfMonth",
17361  std::to_string(day_of_month_));
17362  return pattern_node;
17363  }
17364 };
17365 
17366 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17367  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17368 static_assert(
17369  !std::is_default_constructible<absolute_monthly_recurrence>::value);
17370 static_assert(!std::is_copy_constructible<absolute_monthly_recurrence>::value);
17371 static_assert(!std::is_copy_assignable<absolute_monthly_recurrence>::value);
17372 static_assert(!std::is_move_constructible<absolute_monthly_recurrence>::value);
17373 static_assert(!std::is_move_assignable<absolute_monthly_recurrence>::value);
17374 #endif
17375 
17394 {
17395 public:
17396  relative_monthly_recurrence(uint32_t interval, day_of_week days_of_week,
17397  day_of_week_index index)
17398  : interval_(interval), days_of_week_(days_of_week), index_(index)
17399  {
17400  }
17401 
17402  std::string get_occurence_name() override
17403  {
17404  return "relative_monthly_recurrence";
17405  }
17406 
17407  uint32_t get_interval() const EWS_NOEXCEPT { return interval_; }
17408 
17409  day_of_week get_days_of_week() const EWS_NOEXCEPT { return days_of_week_; }
17410 
17411  day_of_week_index get_day_of_week_index() const EWS_NOEXCEPT
17412  {
17413  return index_;
17414  }
17415 
17416 private:
17417  uint32_t interval_;
17418  day_of_week days_of_week_;
17419  day_of_week_index index_;
17420 
17421  std::string to_xml_impl() const override
17422  {
17423  using namespace internal;
17424 
17425  std::stringstream sstr;
17426  sstr << "<t:RelativeMonthlyRecurrence>"
17427  << "<t:Interval>" << interval_ << "</t:Interval>"
17428  << "<t:DaysOfWeek>" << enum_to_str(days_of_week_)
17429  << "</t:DaysOfWeek>"
17430  << "<t:DayOfWeekIndex>" << enum_to_str(index_)
17431  << "</t:DayOfWeekIndex>"
17432  << "</t:RelativeMonthlyRecurrence>";
17433  return sstr.str();
17434  }
17435 
17436  rapidxml::xml_node<>&
17437  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17438  {
17439  using internal::create_node;
17440  auto& pattern_node = create_node(parent, "t:RelativeMonthlyRecurrence");
17441  create_node(pattern_node, "t:Interval", std::to_string(interval_));
17442  create_node(pattern_node, "t:DaysOfWeek",
17443  internal::enum_to_str(days_of_week_));
17444  create_node(pattern_node, "t:DayOfWeekIndex",
17445  internal::enum_to_str(index_));
17446  return pattern_node;
17447  }
17448 };
17449 
17450 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17451  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17452 static_assert(
17453  !std::is_default_constructible<relative_monthly_recurrence>::value);
17454 static_assert(!std::is_copy_constructible<relative_monthly_recurrence>::value);
17455 static_assert(!std::is_copy_assignable<relative_monthly_recurrence>::value);
17456 static_assert(!std::is_move_constructible<relative_monthly_recurrence>::value);
17457 static_assert(!std::is_move_assignable<relative_monthly_recurrence>::value);
17458 #endif
17459 
17470 {
17471 public:
17472  weekly_recurrence(uint32_t interval, day_of_week days_of_week,
17473  day_of_week first_day_of_week = day_of_week::mon)
17474  : interval_(interval), days_of_week_(),
17475  first_day_of_week_(first_day_of_week)
17476  {
17477  days_of_week_.push_back(days_of_week);
17478  }
17479 
17480  weekly_recurrence(uint32_t interval, std::vector<day_of_week> days_of_week,
17481  day_of_week first_day_of_week = day_of_week::mon)
17482  : interval_(interval), days_of_week_(std::move(days_of_week)),
17483  first_day_of_week_(first_day_of_week)
17484  {
17485  }
17486 
17487  std::string get_occurence_name() override { return "weekly_recurrence"; }
17488 
17489  uint32_t get_interval() const EWS_NOEXCEPT { return interval_; }
17490 
17491  const std::vector<day_of_week>& get_days_of_week() const EWS_NOEXCEPT
17492  {
17493  return days_of_week_;
17494  }
17495 
17496  day_of_week get_first_day_of_week() const EWS_NOEXCEPT
17497  {
17498  return first_day_of_week_;
17499  }
17500 
17501 private:
17502  uint32_t interval_;
17503  std::vector<day_of_week> days_of_week_;
17504  day_of_week first_day_of_week_;
17505 
17506  std::string to_xml_impl() const override
17507  {
17508  using namespace internal;
17509 
17510  std::string value;
17511  for (const auto& day : days_of_week_)
17512  {
17513  value += enum_to_str(day) + " ";
17514  }
17515  value.resize(value.size() - 1);
17516  std::stringstream sstr;
17517  sstr << "<t:WeeklyRecurrence>"
17518  << "<t:Interval>" << interval_ << "</t:Interval>"
17519  << "<t:DaysOfWeek>" << value << "</t:DaysOfWeek>"
17520  << "<t:FirstDayOfWeek>" << enum_to_str(first_day_of_week_)
17521  << "</t:FirstDayOfWeek>"
17522  << "</t:WeeklyRecurrence>";
17523  return sstr.str();
17524  }
17525 
17526  rapidxml::xml_node<>&
17527  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17528  {
17529  using namespace internal;
17530  check(parent.document(), "Parent node needs to be part of a document");
17531 
17532  auto& pattern_node = create_node(parent, "t:WeeklyRecurrence");
17533  create_node(pattern_node, "t:Interval", std::to_string(interval_));
17534  std::string value;
17535  for (const auto& day : days_of_week_)
17536  {
17537  value += enum_to_str(day) + " ";
17538  }
17539  value.pop_back();
17540  create_node(pattern_node, "t:DaysOfWeek", value);
17541  create_node(pattern_node, "t:FirstDayOfWeek",
17542  enum_to_str(first_day_of_week_));
17543  return pattern_node;
17544  }
17545 };
17546 
17547 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17548  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17549 static_assert(!std::is_default_constructible<weekly_recurrence>::value);
17550 static_assert(!std::is_copy_constructible<weekly_recurrence>::value);
17551 static_assert(!std::is_copy_assignable<weekly_recurrence>::value);
17552 static_assert(!std::is_move_constructible<weekly_recurrence>::value);
17553 static_assert(!std::is_move_assignable<weekly_recurrence>::value);
17554 #endif
17555 
17558 {
17559 public:
17560  explicit daily_recurrence(uint32_t interval) : interval_(interval) {}
17561 
17562  std::string get_occurence_name() override { return "daily_recurrence"; }
17563 
17564  uint32_t get_interval() const EWS_NOEXCEPT { return interval_; }
17565 
17566 private:
17567  uint32_t interval_;
17568 
17569  std::string to_xml_impl() const override
17570  {
17571  using namespace internal;
17572 
17573  std::stringstream sstr;
17574  sstr << "<t:DailyRecurrence>"
17575  << "<t:Interval>" << interval_ << "</t:Interval>"
17576  << "</t:DailyRecurrence>";
17577  return sstr.str();
17578  }
17579 
17580  rapidxml::xml_node<>&
17581  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17582  {
17583  using internal::create_node;
17584  check(parent.document(), "Parent node needs to be part of a document");
17585 
17586  auto& pattern_node = create_node(parent, "t:DailyRecurrence");
17587  create_node(pattern_node, "t:Interval", std::to_string(interval_));
17588  return pattern_node;
17589  }
17590 };
17591 
17592 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17593  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17594 static_assert(!std::is_default_constructible<daily_recurrence>::value);
17595 static_assert(!std::is_copy_constructible<daily_recurrence>::value);
17596 static_assert(!std::is_copy_assignable<daily_recurrence>::value);
17597 static_assert(!std::is_move_constructible<daily_recurrence>::value);
17598 static_assert(!std::is_move_assignable<daily_recurrence>::value);
17599 #endif
17600 
17603 {
17604 public:
17605  virtual std::string get_reccurence_range_name() { return "recurrence_range"; }
17606 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17607  virtual ~recurrence_range() = default;
17608 
17609  recurrence_range(const recurrence_range&) = delete;
17610  recurrence_range& operator=(const recurrence_range&) = delete;
17611 #else
17612  virtual ~recurrence_range() {}
17613 
17614 private:
17616  recurrence_range& operator=(const recurrence_range&);
17617 
17618 public:
17619 #endif
17620  std::string to_xml() const { return this->to_xml_impl(); }
17621 
17626  rapidxml::xml_node<>& to_xml_element(rapidxml::xml_node<>& parent) const
17627  {
17628  return this->to_xml_element_impl(parent);
17629  }
17630 
17632  static std::unique_ptr<recurrence_range>
17633  from_xml_element(const rapidxml::xml_node<>& elem); // Defined below
17634 
17635 protected:
17636 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17637  recurrence_range() = default;
17638 #else
17639  recurrence_range() {}
17640 #endif
17641 
17642 private:
17643  virtual std::string to_xml_impl() const = 0;
17644 
17645  virtual rapidxml::xml_node<>&
17646  to_xml_element_impl(rapidxml::xml_node<>&) const = 0;
17647 };
17648 
17649 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17650  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17651 static_assert(!std::is_default_constructible<recurrence_range>::value);
17652 static_assert(!std::is_copy_constructible<recurrence_range>::value);
17653 static_assert(!std::is_copy_assignable<recurrence_range>::value);
17654 static_assert(!std::is_move_constructible<recurrence_range>::value);
17655 static_assert(!std::is_move_assignable<recurrence_range>::value);
17656 #endif
17657 
17660 {
17661 public:
17662  explicit no_end_recurrence_range(date start_date)
17663  : start_date_(std::move(start_date))
17664  {
17665  }
17666 
17667  std::string get_reccurence_range_name() override { return "no_end_recurrence_range"; }
17668 
17669  const date_time& get_start_date() const EWS_NOEXCEPT { return start_date_; }
17670 
17671 private:
17672  date start_date_;
17673 
17674  std::string to_xml_impl() const override
17675  {
17676  using namespace internal;
17677 
17678  std::stringstream sstr;
17679  sstr << "<t:NoEndRecurrence>"
17680  << "<t:StartDate>" << start_date_.to_string() << "</t:StartDate>"
17681  << "</t:NoEndRecurrence>";
17682  return sstr.str();
17683  }
17684 
17685  rapidxml::xml_node<>&
17686  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17687  {
17688  using namespace internal;
17689  check(parent.document(), "Parent node needs to be part of a document");
17690 
17691  auto& pattern_node = create_node(parent, "t:NoEndRecurrence");
17692  create_node(pattern_node, "t:StartDate", start_date_.to_string());
17693  return pattern_node;
17694  }
17695 };
17696 
17697 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17698  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17699 static_assert(!std::is_default_constructible<no_end_recurrence_range>::value);
17700 static_assert(!std::is_copy_constructible<no_end_recurrence_range>::value);
17701 static_assert(!std::is_copy_assignable<no_end_recurrence_range>::value);
17702 static_assert(!std::is_move_constructible<no_end_recurrence_range>::value);
17703 static_assert(!std::is_move_assignable<no_end_recurrence_range>::value);
17704 #endif
17705 
17708 {
17709 public:
17710  end_date_recurrence_range(date start_date, date end_date)
17711  : start_date_(std::move(start_date)), end_date_(std::move(end_date))
17712  {
17713  }
17714 
17715  std::string get_reccurence_range_name() override { return "end_date_recurrence_range"; }
17716 
17717  const date_time& get_start_date() const EWS_NOEXCEPT { return start_date_; }
17718 
17719  const date_time& get_end_date() const EWS_NOEXCEPT { return end_date_; }
17720 
17721 private:
17722  date start_date_;
17723  date end_date_;
17724 
17725  std::string to_xml_impl() const override
17726  {
17727  using namespace internal;
17728 
17729  std::stringstream sstr;
17730  sstr << "<t:EndDateRecurrence>"
17731  << "<t:StartDate>" << start_date_.to_string() << "</t:StartDate>"
17732  << "<t:EndDate>" << end_date_.to_string() << "</t:EndDate>"
17733  << "</t:EndDateRecurrence>";
17734  return sstr.str();
17735  }
17736 
17737  rapidxml::xml_node<>&
17738  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17739  {
17740  using internal::create_node;
17741  check(parent.document(), "Parent node needs to be part of a document");
17742 
17743  auto& pattern_node = create_node(parent, "t:EndDateRecurrence");
17744  create_node(pattern_node, "t:StartDate", start_date_.to_string());
17745  create_node(pattern_node, "t:EndDate", end_date_.to_string());
17746  return pattern_node;
17747  }
17748 };
17749 
17750 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17751  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17752 static_assert(!std::is_default_constructible<end_date_recurrence_range>::value);
17753 static_assert(!std::is_copy_constructible<end_date_recurrence_range>::value);
17754 static_assert(!std::is_copy_assignable<end_date_recurrence_range>::value);
17755 static_assert(!std::is_move_constructible<end_date_recurrence_range>::value);
17756 static_assert(!std::is_move_assignable<end_date_recurrence_range>::value);
17757 #endif
17758 
17761 {
17762 public:
17763  numbered_recurrence_range(date start_date, uint32_t no_of_occurrences)
17764  : start_date_(std::move(start_date)),
17765  no_of_occurrences_(no_of_occurrences)
17766  {
17767  }
17768 
17769  std::string get_reccurence_range_name() override { return "numbered_recurrence_range"; }
17770 
17771  const date_time& get_start_date() const EWS_NOEXCEPT { return start_date_; }
17772 
17773  uint32_t get_number_of_occurrences() const EWS_NOEXCEPT
17774  {
17775  return no_of_occurrences_;
17776  }
17777 
17778 private:
17779  date start_date_;
17780  uint32_t no_of_occurrences_;
17781 
17782  std::string to_xml_impl() const override
17783  {
17784  using namespace internal;
17785 
17786  std::stringstream sstr;
17787  sstr << "<t:NumberedRecurrence>"
17788  << "<t:StartDate>" << start_date_.to_string() << "</t:StartDate>"
17789  << "<t:NumberOfOccurrences>" << no_of_occurrences_
17790  << "</t:NumberOfOccurrences>"
17791  << "</t:NumberedRecurrence>";
17792  return sstr.str();
17793  }
17794 
17795  rapidxml::xml_node<>&
17796  to_xml_element_impl(rapidxml::xml_node<>& parent) const override
17797  {
17798  using namespace internal;
17799  check(parent.document(), "Parent node needs to be part of a document");
17800 
17801  auto& pattern_node = create_node(parent, "t:NumberedRecurrence");
17802  create_node(pattern_node, "t:StartDate", start_date_.to_string());
17803  create_node(pattern_node, "t:NumberOfOccurrences",
17804  std::to_string(no_of_occurrences_));
17805  return pattern_node;
17806  }
17807 };
17808 
17809 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
17810  defined(EWS_HAS_CXX17_STATIC_ASSERT)
17811 static_assert(!std::is_default_constructible<numbered_recurrence_range>::value);
17812 static_assert(!std::is_copy_constructible<numbered_recurrence_range>::value);
17813 static_assert(!std::is_copy_assignable<numbered_recurrence_range>::value);
17814 static_assert(!std::is_move_constructible<numbered_recurrence_range>::value);
17815 static_assert(!std::is_move_assignable<numbered_recurrence_range>::value);
17816 #endif
17817 
17819 class calendar_item final : public item
17820 {
17821 public:
17822 #ifdef EWS_HAS_DEFAULT_AND_DELETE
17823  calendar_item() = default;
17824 #else
17825  calendar_item() {}
17826 #endif
17827 
17829  explicit calendar_item(item_id id) : item(id) {}
17830 
17831 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
17832  calendar_item(item_id&& id, internal::xml_subtree&& properties)
17833  : item(std::move(id), std::move(properties))
17834  {
17835  }
17836 #endif
17837 
17840  {
17841  return date_time(xml().get_value_as_string("Start"));
17842  }
17843 
17845  void set_start(const date_time& datetime)
17846  {
17847  xml().set_or_update("Start", datetime.to_string());
17848  }
17849 
17852  {
17853  return date_time(xml().get_value_as_string("End"));
17854  }
17855 
17857  void set_end(const date_time& datetime)
17858  {
17859  xml().set_or_update("End", datetime.to_string());
17860  }
17861 
17866  {
17867  return date_time(xml().get_value_as_string("OriginalStart"));
17868  }
17869 
17871  bool is_all_day_event() const
17872  {
17873  return xml().get_value_as_string("IsAllDayEvent") == "true";
17874  }
17875 
17877  void set_all_day_event_enabled(bool enabled)
17878  {
17879  xml().set_or_update("IsAllDayEvent", enabled ? "true" : "false");
17880  }
17881 
17884  {
17885  const auto val = xml().get_value_as_string("LegacyFreeBusyStatus");
17886  // Default seems to be 'Busy' if not explicitly set
17887  if (val.empty() || val == "Busy")
17888  {
17889  return free_busy_status::busy;
17890  }
17891  if (val == "Tentative")
17892  {
17894  }
17895  if (val == "Free")
17896  {
17897  return free_busy_status::free;
17898  }
17899  if (val == "OOF")
17900  {
17902  }
17903  if (val == "NoData")
17904  {
17906  }
17907  if (val == "WorkingElsewhere")
17908  {
17910  }
17911  throw exception("Unexpected <LegacyFreeBusyStatus>");
17912  }
17913 
17916  {
17917  xml().set_or_update("LegacyFreeBusyStatus",
17918  internal::enum_to_str(status));
17919  }
17920 
17923  std::string get_location() const
17924  {
17925  return xml().get_value_as_string("Location");
17926  }
17927 
17930  void set_location(const std::string& location)
17931  {
17932  xml().set_or_update("Location", location);
17933  }
17934 
17936  std::string get_when() const { return xml().get_value_as_string("When"); }
17937 
17939  void set_when(const std::string& desc)
17940  {
17941  xml().set_or_update("When", desc);
17942  }
17943 
17947  bool is_meeting() const
17948  {
17949  return xml().get_value_as_string("IsMeeting") == "true";
17950  }
17951 
17956  bool is_cancelled() const
17957  {
17958  return xml().get_value_as_string("IsCancelled") == "true";
17959  }
17960 
17966  bool is_recurring() const
17967  {
17968  return xml().get_value_as_string("IsRecurring") == "true";
17969  }
17970 
17976  {
17977  return xml().get_value_as_string("MeetingRequestWasSent") == "true";
17978  }
17979 
17984  {
17985  return xml().get_value_as_string("IsResponseRequested") == "true";
17986  }
17987 
17992  {
17993  const auto val = xml().get_value_as_string("CalendarItemType");
17994  // By default, newly created calendar items are of type 'Single'
17995  if (val.empty() || val == "Single")
17996  {
17998  }
17999  if (val == "Occurrence")
18000  {
18002  }
18003  if (val == "Exception")
18004  {
18006  }
18007  if (val == "RecurringMaster")
18008  {
18010  }
18011  throw exception("Unexpected <CalendarItemType>");
18012  }
18013 
18019  {
18020  const auto val = xml().get_value_as_string("MyResponseType");
18021  if (val.empty())
18022  {
18023  return response_type::unknown;
18024  }
18025  return internal::str_to_response_type(val);
18026  }
18027 
18033  {
18034  const auto organizer = xml().get_node("Organizer");
18035  if (!organizer)
18036  {
18037  return mailbox(); // None
18038  }
18039  return mailbox::from_xml_element(*(organizer->first_node()));
18040  }
18041 
18043  std::vector<attendee> get_required_attendees() const
18044  {
18045  return get_attendees_helper("RequiredAttendees");
18046  }
18047 
18049  void set_required_attendees(const std::vector<attendee>& attendees) const
18050  {
18051  set_attendees_helper("RequiredAttendees", attendees);
18052  }
18053 
18055  std::vector<attendee> get_optional_attendees() const
18056  {
18057  return get_attendees_helper("OptionalAttendees");
18058  }
18059 
18061  void set_optional_attendees(const std::vector<attendee>& attendees) const
18062  {
18063  set_attendees_helper("OptionalAttendees", attendees);
18064  }
18065 
18067  std::vector<attendee> get_resources() const
18068  {
18069  return get_attendees_helper("Resources");
18070  }
18071 
18073  void set_resources(const std::vector<attendee>& resources) const
18074  {
18075  set_attendees_helper("Resources", resources);
18076  }
18077 
18086  {
18087  const auto val = xml().get_value_as_string("ConflictingMeetingCount");
18088  return val.empty() ? 0 : std::stoi(val);
18089  }
18090 
18099  {
18100  const auto val = xml().get_value_as_string("AdjacentMeetingCount");
18101  return val.empty() ? 0 : std::stoi(val);
18102  }
18103 
18104  // TODO: issue #19
18105  // <ConflictingMeetings/>
18106  // <AdjacentMeetings/>
18107 
18112  {
18113  return duration(xml().get_value_as_string("Duration"));
18114  }
18115 
18129  std::string get_time_zone() const
18130  {
18131  return xml().get_value_as_string("TimeZone");
18132  }
18133 
18139  {
18140  return date_time(xml().get_value_as_string("AppointmentReplyTime"));
18141  }
18142 
18147  {
18148  const auto val = xml().get_value_as_string("AppointmentSequenceNumber");
18149  return val.empty() ? 0 : std::stoi(val);
18150  }
18151 
18166  {
18167  const auto val = xml().get_value_as_string("AppointmentState");
18168  return val.empty() ? 0 : std::stoi(val);
18169  }
18170 
18176  std::pair<std::unique_ptr<recurrence_pattern>,
18177  std::unique_ptr<recurrence_range>>
18179  {
18180  typedef std::pair<std::unique_ptr<recurrence_pattern>,
18181  std::unique_ptr<recurrence_range>>
18182  return_type;
18183  auto node = xml().get_node("Recurrence");
18184  if (!node)
18185  {
18186  return return_type();
18187  }
18188  return std::make_pair(recurrence_pattern::from_xml_element(*node),
18190  }
18191 
18193  void set_recurrence(const recurrence_pattern& pattern,
18194  const recurrence_range& range)
18195  {
18196  auto doc = xml().document();
18197  auto recurrence_node = xml().get_node("Recurrence");
18198  if (recurrence_node)
18199  {
18200  // Remove existing node first
18201  doc->remove_node(recurrence_node);
18202  }
18203 
18204  recurrence_node = &internal::create_node(*doc, "t:Recurrence");
18205 
18206  pattern.to_xml_element(*recurrence_node);
18207  range.to_xml_element(*recurrence_node);
18208  }
18209 
18212  {
18213  auto node = xml().get_node("FirstOccurrence");
18214  if (!node)
18215  {
18216  return occurrence_info();
18217  }
18218  return occurrence_info::from_xml_element(*node);
18219  }
18220 
18223  {
18224  auto node = xml().get_node("LastOccurrence");
18225  if (!node)
18226  {
18227  return occurrence_info();
18228  }
18229  return occurrence_info::from_xml_element(*node);
18230  }
18231 
18233  std::vector<occurrence_info> get_modified_occurrences() const
18234  {
18235  auto node = xml().get_node("ModifiedOccurrences");
18236  if (!node)
18237  {
18238  return std::vector<occurrence_info>();
18239  }
18240 
18241  auto occurrences = std::vector<occurrence_info>();
18242  for (auto occurrence = node->first_node(); occurrence;
18243  occurrence = occurrence->next_sibling())
18244  {
18245  occurrences.emplace_back(
18247  }
18248  return occurrences;
18249  }
18250 
18252  std::vector<occurrence_info> get_deleted_occurrences() const
18253  {
18254  auto node = xml().get_node("DeletedOccurrences");
18255  if (!node)
18256  {
18257  return std::vector<occurrence_info>();
18258  }
18259 
18260  auto occurrences = std::vector<occurrence_info>();
18261  for (auto occurrence = node->first_node(); occurrence;
18262  occurrence = occurrence->next_sibling())
18263  {
18264  occurrences.emplace_back(
18266  }
18267  return occurrences;
18268  }
18269 
18272  {
18273  internal::xml_subtree::attribute id_attribute = {
18274  "Id", internal::enum_to_str(tz)};
18275  std::vector<internal::xml_subtree::attribute> attributes;
18276  attributes.emplace_back(id_attribute);
18277  xml().set_or_update("StartTimeZone", attributes);
18278  }
18279 
18282  {
18283  const auto val = xml().get_value_as_string("StartTimeZoneId");
18284  if (!val.empty())
18285  return internal::str_to_time_zone(val);
18286 
18287  const auto node = xml().get_node("StartTimeZone");
18288  if (!node)
18289  return time_zone::none;
18290  const auto att = node->first_attribute("Id");
18291  if (!att)
18292  return time_zone::none;
18293  return internal::str_to_time_zone(att->value());
18294  }
18295 
18298  {
18299  internal::xml_subtree::attribute id_attribute = {
18300  "Id", internal::enum_to_str(tz)};
18301  std::vector<internal::xml_subtree::attribute> attributes;
18302  attributes.emplace_back(id_attribute);
18303  xml().set_or_update("EndTimeZone", attributes);
18304  }
18305 
18308  {
18309  const auto val = xml().get_value_as_string("EndTimeZoneId");
18310  if (!val.empty())
18311  return internal::str_to_time_zone(val);
18312 
18313  const auto node = xml().get_node("EndTimeZone");
18314  if (!node)
18315  return time_zone::none;
18316  const auto att = node->first_attribute("Id");
18317  if (!att)
18318  return time_zone::none;
18319  return internal::str_to_time_zone(att->value());
18320  }
18321 
18324  {
18325  internal::xml_subtree::attribute id_attribute = {
18326  "Id", internal::enum_to_str(tz)};
18327  std::vector<internal::xml_subtree::attribute> attributes;
18328  attributes.emplace_back(id_attribute);
18329  xml().set_or_update("MeetingTimeZone", attributes);
18330  }
18331 
18334  {
18335  const auto val = xml().get_value_as_string("MeetingTimeZoneId");
18336  if (!val.empty())
18337  return internal::str_to_time_zone(val);
18338 
18339  const auto node = xml().get_node("MeetingTimeZone");
18340  if (!node)
18341  return time_zone::none;
18342  const auto att = node->first_attribute("Id");
18343  if (!att)
18344  return time_zone::none;
18345  return internal::str_to_time_zone(att->value());
18346  }
18347 
18357  {
18358  const auto val = xml().get_value_as_string("ConferenceType");
18359  return val.empty() ? 0 : std::stoi(val);
18360  }
18361 
18366  void set_conference_type(int value)
18367  {
18368  xml().set_or_update("ConferenceType", std::to_string(value));
18369  }
18370 
18374  {
18375  return xml().get_value_as_string("AllowNewTimeProposal") == "true";
18376  }
18377 
18385  {
18386  xml().set_or_update("AllowNewTimeProposal", allowed ? "true" : "false");
18387  }
18388 
18390  bool is_online_meeting() const
18391  {
18392  return xml().get_value_as_string("IsOnlineMeeting") == "true";
18393  }
18394 
18400  void set_online_meeting_enabled(bool enabled)
18401  {
18402  xml().set_or_update("IsOnlineMeeting", enabled ? "true" : "false");
18403  }
18404 
18406  std::string get_meeting_workspace_url() const
18407  {
18408  return xml().get_value_as_string("MeetingWorkspaceUrl");
18409  }
18410 
18416  void set_meeting_workspace_url(const std::string& url)
18417  {
18418  xml().set_or_update("MeetingWorkspaceUrl", url);
18419  }
18420 
18422  std::string get_net_show_url() const
18423  {
18424  return xml().get_value_as_string("NetShowUrl");
18425  }
18426 
18432  void set_net_show_url(const std::string& url)
18433  {
18434  xml().set_or_update("NetShowUrl", url);
18435  }
18436 
18438  static calendar_item from_xml_element(const rapidxml::xml_node<>& elem)
18439  {
18440  auto id_node =
18441  elem.first_node_ns(internal::uri<>::microsoft::types(), "ItemId");
18442  check(id_node, "Expected <ItemId>");
18443  return calendar_item(item_id::from_xml_element(*id_node),
18444  internal::xml_subtree(elem));
18445  }
18446 
18447 private:
18448  inline std::vector<attendee>
18449  get_attendees_helper(const char* node_name) const
18450  {
18451  const auto attendees = xml().get_node(node_name);
18452  if (!attendees)
18453  {
18454  return std::vector<attendee>();
18455  }
18456 
18457  std::vector<attendee> result;
18458  for (auto attendee_node = attendees->first_node(); attendee_node;
18459  attendee_node = attendee_node->next_sibling())
18460  {
18461  result.emplace_back(attendee::from_xml_element(*attendee_node));
18462  }
18463  return result;
18464  }
18465 
18466  inline void
18467  set_attendees_helper(const char* node_name,
18468  const std::vector<attendee>& attendees) const
18469  {
18470  auto doc = xml().document();
18471 
18472  auto attendees_node = xml().get_node(node_name);
18473  if (attendees_node)
18474  {
18475  doc->remove_node(attendees_node);
18476  }
18477 
18478  attendees_node =
18479  &internal::create_node(*doc, "t:" + std::string(node_name));
18480 
18481  for (const auto& a : attendees)
18482  {
18483  a.to_xml_element(*attendees_node);
18484  }
18485  }
18486 
18487  template <typename U> friend class basic_service;
18488 
18489  const std::string& item_tag_name() const EWS_NOEXCEPT
18490  {
18491  static const std::string name("CalendarItem");
18492  return name;
18493  }
18494 };
18495 
18496 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
18497  defined(EWS_HAS_CXX17_STATIC_ASSERT)
18498 static_assert(std::is_default_constructible<calendar_item>::value);
18499 static_assert(std::is_copy_constructible<calendar_item>::value);
18500 static_assert(std::is_copy_assignable<calendar_item>::value);
18501 static_assert(std::is_move_constructible<calendar_item>::value);
18502 static_assert(std::is_move_assignable<calendar_item>::value);
18503 #endif
18504 
18506 class message final : public item
18507 {
18508 public:
18510 #ifdef EWS_HAS_DEFAULT_AND_DELETE
18511  message() = default;
18512 #else
18513  message() {}
18514 #endif
18515 
18517  explicit message(item_id id) : item(id) {}
18518 
18519 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
18520  message(item_id&& id, internal::xml_subtree&& properties)
18521  : item(std::move(id), std::move(properties))
18522  {
18523  }
18524 #endif
18525 
18528  {
18529  const auto sender_node = xml().get_node("Sender");
18530  if (!sender_node)
18531  {
18532  return mailbox(); // None
18533  }
18534  return mailbox::from_xml_element(*(sender_node->first_node()));
18535  }
18536 
18538  void set_sender(const ews::mailbox& m)
18539  {
18540  auto doc = xml().document();
18541  auto sender_node = xml().get_node("Sender");
18542  if (sender_node)
18543  {
18544  doc->remove_node(sender_node);
18545  }
18546  sender_node = &internal::create_node(*doc, "t:Sender");
18547  m.to_xml_element(*sender_node);
18548  }
18549 
18551  std::vector<mailbox> get_to_recipients() const
18552  {
18553  return get_recipients_impl("ToRecipients");
18554  }
18555 
18560  void set_to_recipients(const std::vector<mailbox>& recipients)
18561  {
18562  set_recipients_impl("ToRecipients", recipients);
18563  }
18564 
18566  std::vector<mailbox> get_cc_recipients() const
18567  {
18568  return get_recipients_impl("CcRecipients");
18569  }
18570 
18576  void set_cc_recipients(const std::vector<mailbox>& recipients)
18577  {
18578  set_recipients_impl("CcRecipients", recipients);
18579  }
18580 
18582  std::vector<mailbox> get_bcc_recipients() const
18583  {
18584  return get_recipients_impl("BccRecipients");
18585  }
18586 
18592  void set_bcc_recipients(const std::vector<mailbox>& recipients)
18593  {
18594  set_recipients_impl("BccRecipients", recipients);
18595  }
18596 
18597  // <IsReadReceiptRequested/>
18598  // <IsDeliveryReceiptRequested/>
18599  // <ConversationIndex/>
18600  // <ConversationTopic/>
18601 
18604  {
18605  const auto from_node = xml().get_node("From");
18606  if (!from_node)
18607  {
18608  return mailbox(); // None set
18609  }
18610  return mailbox::from_xml_element(*(from_node->first_node()));
18611  }
18612 
18614  void set_from(const ews::mailbox& m)
18615  {
18616  auto doc = xml().document();
18617  auto from_node = xml().get_node("From");
18618  if (from_node)
18619  {
18620  doc->remove_node(from_node);
18621  }
18622  from_node = &internal::create_node(*doc, "t:From");
18623  m.to_xml_element(*from_node);
18624  }
18625 
18631  std::string get_internet_message_id() const
18632  {
18633  return xml().get_value_as_string("InternetMessageId");
18634  }
18635 
18645  void set_internet_message_id(const std::string& value)
18646  {
18647  xml().set_or_update("InternetMessageId", value);
18648  }
18649 
18651  bool is_read() const
18652  {
18653  return xml().get_value_as_string("IsRead") == "true";
18654  }
18655 
18660  void set_is_read(bool value)
18661  {
18662  xml().set_or_update("IsRead", value ? "true" : "false");
18663  }
18664 
18665  // <IsResponseRequested/>
18666  // <References/>
18667 
18669  std::vector<mailbox> get_reply_to() const
18670  {
18671  return get_recipients_impl("ReplyTo");
18672  }
18673 
18679  void set_reply_to(const std::vector<mailbox>& recipients)
18680  {
18681  set_recipients_impl("ReplyTo", recipients);
18682  }
18683 
18685  static message from_xml_element(const rapidxml::xml_node<>& elem)
18686  {
18687  auto id_node =
18688  elem.first_node_ns(internal::uri<>::microsoft::types(), "ItemId");
18689  check(id_node, "Expected <ItemId>");
18690  return message(item_id::from_xml_element(*id_node),
18691  internal::xml_subtree(elem));
18692  }
18693 
18694 private:
18695  template <typename U> friend class basic_service;
18696 
18697  const std::string& item_tag_name() const EWS_NOEXCEPT
18698  {
18699  static const std::string name("Message");
18700  return name;
18701  }
18702 
18703  std::vector<mailbox> get_recipients_impl(const char* node_name) const
18704  {
18705  const auto recipients = xml().get_node(node_name);
18706  if (!recipients)
18707  {
18708  return std::vector<mailbox>();
18709  }
18710  std::vector<mailbox> result;
18711  for (auto mailbox_node = recipients->first_node(); mailbox_node;
18712  mailbox_node = mailbox_node->next_sibling())
18713  {
18714  result.emplace_back(mailbox::from_xml_element(*mailbox_node));
18715  }
18716  return result;
18717  }
18718 
18719  void set_recipients_impl(const char* node_name,
18720  const std::vector<mailbox>& recipients)
18721  {
18722  auto doc = xml().document();
18723 
18724  auto recipients_node = xml().get_node(node_name);
18725  if (recipients_node)
18726  {
18727  doc->remove_node(recipients_node);
18728  }
18729 
18730  recipients_node =
18731  &internal::create_node(*doc, std::string("t:") + node_name);
18732 
18733  for (const auto& recipient : recipients)
18734  {
18735  recipient.to_xml_element(*recipients_node);
18736  }
18737  }
18738 };
18739 
18740 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
18741  defined(EWS_HAS_CXX17_STATIC_ASSERT)
18742 static_assert(std::is_default_constructible<message>::value);
18743 static_assert(std::is_copy_constructible<message>::value);
18744 static_assert(std::is_copy_assignable<message>::value);
18745 static_assert(std::is_move_constructible<message>::value);
18746 static_assert(std::is_move_assignable<message>::value);
18747 #endif
18748 
18751 {
18752 public:
18753  // Intentionally not explicit
18754  property_path(const char* uri) : uri_(uri) { class_name(); }
18755 
18756 #ifdef EWS_HAS_DEFAULT_AND_DELETE
18757  virtual ~property_path() = default;
18758  property_path(const property_path&) = default;
18759  property_path& operator=(const property_path&) = default;
18760 #else
18761  virtual ~property_path() {}
18762 #endif
18763 
18764  std::string to_xml() const { return this->to_xml_impl(); }
18765 
18766  std::string to_xml(const std::string& value) const
18767  {
18768  return this->to_xml_impl(value);
18769  }
18770 
18772  const std::string& field_uri() const EWS_NOEXCEPT { return uri_; }
18773 
18774 protected:
18775  std::string class_name() const
18776  {
18777  // TODO: we know at compile-time to which class a property belongs
18778  const auto n = uri_.find(':');
18779  check((n != std::string::npos), "Expected a ':' in URI");
18780  const auto substr = uri_.substr(0, n);
18781  if (substr == "folder")
18782  {
18783  return "Folder";
18784  }
18785  else if (substr == "item")
18786  {
18787  return "Item";
18788  }
18789  else if (substr == "message")
18790  {
18791  return "Message";
18792  }
18793  else if (substr == "meeting")
18794  {
18795  return "Meeting";
18796  }
18797  else if (substr == "meetingRequest")
18798  {
18799  return "MeetingRequest";
18800  }
18801  else if (substr == "calendar")
18802  {
18803  return "CalendarItem";
18804  }
18805  else if (substr == "task")
18806  {
18807  return "Task";
18808  }
18809  else if (substr == "contacts")
18810  {
18811  return "Contact";
18812  }
18813  else if (substr == "distributionlist")
18814  {
18815  return "DistributionList";
18816  }
18817  else if (substr == "postitem")
18818  {
18819  return "PostItem";
18820  }
18821  else if (substr == "conversation")
18822  {
18823  return "Conversation";
18824  }
18825  // Persona missing
18826  // else if (substr == "")
18827  // {
18828  // return "";
18829  // }
18830  throw exception("Unknown property path");
18831  }
18832 
18833  virtual std::string to_xml_impl() const
18834  {
18835  std::stringstream sstr;
18836  sstr << "<t:FieldURI FieldURI=\"";
18837  sstr << uri_ << "\"/>";
18838  return sstr.str();
18839  }
18840 
18841  virtual std::string to_xml_impl(const std::string& value) const
18842  {
18843  std::stringstream sstr;
18844  sstr << "<t:FieldURI FieldURI=\"";
18845  sstr << uri_ << "\"/>";
18846  sstr << "<t:" << class_name() << ">";
18847  sstr << "<t:" << property_name() << ">";
18848  sstr << value;
18849  sstr << "</t:" << property_name() << ">";
18850  sstr << "</t:" << class_name() << ">";
18851  return sstr.str();
18852  }
18853 
18854 private:
18855  std::string property_name() const
18856  {
18857  const auto n = uri_.rfind(':');
18858  check((n != std::string::npos), "Expected a ':' in URI");
18859  return uri_.substr(n + 1);
18860  }
18861 
18862  std::string uri_;
18863 };
18864 
18865 inline bool operator==(const property_path& lhs, const property_path& rhs)
18866 {
18867  return lhs.field_uri() == rhs.field_uri();
18868 }
18869 
18870 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
18871  defined(EWS_HAS_CXX17_STATIC_ASSERT)
18872 static_assert(!std::is_default_constructible<property_path>::value);
18873 static_assert(std::is_copy_constructible<property_path>::value);
18874 static_assert(std::is_copy_assignable<property_path>::value);
18875 static_assert(std::is_move_constructible<property_path>::value);
18876 static_assert(std::is_move_assignable<property_path>::value);
18877 #endif
18878 
18881 {
18882 public:
18883  indexed_property_path(const char* uri, const char* index)
18884  : property_path(uri), index_(index)
18885  {
18886  }
18887 
18888 private:
18889  // TODO: why no const char* overload?
18890 
18891  std::string to_xml_impl() const override
18892  {
18893  std::stringstream sstr;
18894  sstr << "<t:IndexedFieldURI FieldURI=";
18895  sstr << "\"" << field_uri() << "\"";
18896  sstr << " FieldIndex=";
18897  sstr << "\"";
18898  sstr << index_;
18899  sstr << "\"";
18900  sstr << "/>";
18901  return sstr.str();
18902  }
18903 
18904  std::string to_xml_impl(const std::string& value) const override
18905  {
18906  std::stringstream sstr;
18907  sstr << "<t:IndexedFieldURI FieldURI=";
18908  sstr << "\"" << field_uri() << "\"";
18909  sstr << " FieldIndex=";
18910  sstr << "\"";
18911  sstr << index_;
18912  sstr << "\"";
18913  sstr << "/>";
18914  sstr << "<t:" << class_name() << ">";
18915  sstr << value;
18916  sstr << " </t:" << class_name() << ">";
18917  return sstr.str();
18918  }
18919 
18920  std::string index_;
18921 };
18922 
18923 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
18924  defined(EWS_HAS_CXX17_STATIC_ASSERT)
18925 static_assert(!std::is_default_constructible<indexed_property_path>::value);
18926 static_assert(std::is_copy_constructible<indexed_property_path>::value);
18927 static_assert(std::is_copy_assignable<indexed_property_path>::value);
18928 static_assert(std::is_move_constructible<indexed_property_path>::value);
18929 static_assert(std::is_move_assignable<indexed_property_path>::value);
18930 #endif
18931 
18932 // TODO: extended_property_path missing?
18933 
18934 namespace folder_property_path
18935 {
18936  static const property_path folder_id = "folder:FolderId";
18937  static const property_path parent_folder_id = "folder:ParentFolderId";
18938  static const property_path display_name = "folder:DisplayName";
18939  static const property_path unread_count = "folder:UnreadCount";
18940  static const property_path total_count = "folder:TotalCount";
18941  static const property_path child_folder_count = "folder:ChildFolderCount";
18942  static const property_path folder_class = "folder:FolderClass";
18943  static const property_path search_parameters = "folder:SearchParameters";
18944  static const property_path managed_folder_information =
18945  "folder:ManagedFolderInformation";
18946  static const property_path permission_set = "folder:PermissionSet";
18947  static const property_path effective_rights = "folder:EffectiveRights";
18948  static const property_path sharing_effective_rights =
18949  "folder:SharingEffectiveRights";
18950 } // namespace folder_property_path
18951 
18952 namespace item_property_path
18953 {
18954  static const property_path item_id = "item:ItemId";
18955  static const property_path parent_folder_id = "item:ParentFolderId";
18956  static const property_path item_class = "item:ItemClass";
18957  static const property_path mime_content = "item:MimeContent";
18958  static const property_path attachments = "item:Attachments";
18959  static const property_path subject = "item:Subject";
18960  static const property_path date_time_received = "item:DateTimeReceived";
18961  static const property_path size = "item:Size";
18962  static const property_path categories = "item:Categories";
18963  static const property_path has_attachments = "item:HasAttachments";
18964  static const property_path importance = "item:Importance";
18965  static const property_path in_reply_to = "item:InReplyTo";
18966  static const property_path internet_message_headers =
18967  "item:InternetMessageHeaders";
18968  static const property_path is_associated = "item:IsAssociated";
18969  static const property_path is_draft = "item:IsDraft";
18970  static const property_path is_from_me = "item:IsFromMe";
18971  static const property_path is_resend = "item:IsResend";
18972  static const property_path is_submitted = "item:IsSubmitted";
18973  static const property_path is_unmodified = "item:IsUnmodified";
18974  static const property_path date_time_sent = "item:DateTimeSent";
18975  static const property_path date_time_created = "item:DateTimeCreated";
18976  static const property_path body = "item:Body";
18977  static const property_path response_objects = "item:ResponseObjects";
18978  static const property_path sensitivity = "item:Sensitivity";
18979  static const property_path reminder_due_by = "item:ReminderDueBy";
18980  static const property_path reminder_is_set = "item:ReminderIsSet";
18981  static const property_path reminder_next_time = "item:ReminderNextTime";
18982  static const property_path reminder_minutes_before_start =
18983  "item:ReminderMinutesBeforeStart";
18984  static const property_path display_to = "item:DisplayTo";
18985  static const property_path display_cc = "item:DisplayCc";
18986  static const property_path culture = "item:Culture";
18987  static const property_path effective_rights = "item:EffectiveRights";
18988  static const property_path last_modified_name = "item:LastModifiedName";
18989  static const property_path last_modified_time = "item:LastModifiedTime";
18990  static const property_path conversation_id = "item:ConversationId";
18991  static const property_path unique_body = "item:UniqueBody";
18992  static const property_path flag = "item:Flag";
18993  static const property_path store_entry_id = "item:StoreEntryId";
18994  static const property_path instance_key = "item:InstanceKey";
18995  static const property_path normalized_body = "item:NormalizedBody";
18996  static const property_path entity_extraction_result =
18997  "item:EntityExtractionResult";
18998  static const property_path policy_tag = "item:PolicyTag";
18999  static const property_path archive_tag = "item:ArchiveTag";
19000  static const property_path retention_date = "item:RetentionDate";
19001  static const property_path preview = "item:Preview";
19002  static const property_path next_predicted_action =
19003  "item:NextPredictedAction";
19004  static const property_path grouping_action = "item:GroupingAction";
19005  static const property_path predicted_action_reasons =
19006  "item:PredictedActionReasons";
19007  static const property_path is_clutter = "item:IsClutter";
19008  static const property_path rights_management_license_data =
19009  "item:RightsManagementLicenseData";
19010  static const property_path block_status = "item:BlockStatus";
19011  static const property_path has_blocked_images = "item:HasBlockedImages";
19012  static const property_path web_client_read_from_query_string =
19013  "item:WebClientReadFormQueryString";
19014  static const property_path web_client_edit_from_query_string =
19015  "item:WebClientEditFormQueryString";
19016  static const property_path text_body = "item:TextBody";
19017  static const property_path icon_index = "item:IconIndex";
19018  static const property_path mime_content_utf8 = "item:MimeContentUTF8";
19019 } // namespace item_property_path
19020 
19021 namespace message_property_path
19022 {
19023  static const property_path conversation_index = "message:ConversationIndex";
19024  static const property_path conversation_topic = "message:ConversationTopic";
19025  static const property_path internet_message_id =
19026  "message:InternetMessageId";
19027  static const property_path is_read = "message:IsRead";
19028  static const property_path is_response_requested =
19029  "message:IsResponseRequested";
19030  static const property_path is_read_receipt_requested =
19031  "message:IsReadReceiptRequested";
19032  static const property_path is_delivery_receipt_requested =
19033  "message:IsDeliveryReceiptRequested";
19034  static const property_path received_by = "message:ReceivedBy";
19035  static const property_path received_representing =
19036  "message:ReceivedRepresenting";
19037  static const property_path references = "message:References";
19038  static const property_path reply_to = "message:ReplyTo";
19039  static const property_path from = "message:From";
19040  static const property_path sender = "message:Sender";
19041  static const property_path to_recipients = "message:ToRecipients";
19042  static const property_path cc_recipients = "message:CcRecipients";
19043  static const property_path bcc_recipients = "message:BccRecipients";
19044  static const property_path approval_request_data =
19045  "message:ApprovalRequestData";
19046  static const property_path voting_information = "message:VotingInformation";
19047  static const property_path reminder_message_data =
19048  "message:ReminderMessageData";
19049 } // namespace message_property_path
19050 
19051 namespace meeting_property_path
19052 {
19053  static const property_path associated_calendar_item_id =
19054  "meeting:AssociatedCalendarItemId";
19055  static const property_path is_delegated = "meeting:IsDelegated";
19056  static const property_path is_out_of_date = "meeting:IsOutOfDate";
19057  static const property_path has_been_processed = "meeting:HasBeenProcessed";
19058  static const property_path response_type = "meeting:ResponseType";
19059  static const property_path proposed_start = "meeting:ProposedStart";
19060  static const property_path proposed_end = "meeting:PropsedEnd";
19061 } // namespace meeting_property_path
19062 
19063 namespace meeting_request_property_path
19064 {
19065  static const property_path meeting_request_type =
19066  "meetingRequest:MeetingRequestType";
19067  static const property_path intended_free_busy_status =
19068  "meetingRequest:IntendedFreeBusyStatus";
19069  static const property_path change_highlights =
19070  "meetingRequest:ChangeHighlights";
19071 } // namespace meeting_request_property_path
19072 
19073 namespace calendar_property_path
19074 {
19075  static const property_path start = "calendar:Start";
19076  static const property_path end = "calendar:End";
19077  static const property_path original_start = "calendar:OriginalStart";
19078  static const property_path start_wall_clock = "calendar:StartWallClock";
19079  static const property_path end_wall_clock = "calendar:EndWallClock";
19080  static const property_path start_time_zone_id = "calendar:StartTimeZoneId";
19081  static const property_path end_time_zone_id = "calendar:EndTimeZoneId";
19082  static const property_path is_all_day_event = "calendar:IsAllDayEvent";
19083  static const property_path legacy_free_busy_status =
19084  "calendar:LegacyFreeBusyStatus";
19085  static const property_path location = "calendar:Location";
19086  static const property_path when = "calendar:When";
19087  static const property_path is_meeting = "calendar:IsMeeting";
19088  static const property_path is_cancelled = "calendar:IsCancelled";
19089  static const property_path is_recurring = "calendar:IsRecurring";
19090  static const property_path meeting_request_was_sent =
19091  "calendar:MeetingRequestWasSent";
19092  static const property_path is_response_requested =
19093  "calendar:IsResponseRequested";
19094  static const property_path calendar_item_type = "calendar:CalendarItemType";
19095  static const property_path my_response_type = "calendar:MyResponseType";
19096  static const property_path organizer = "calendar:Organizer";
19097  static const property_path required_attendees =
19098  "calendar:RequiredAttendees";
19099  static const property_path optional_attendees =
19100  "calendar:OptionalAttendees";
19101  static const property_path resources = "calendar:Resources";
19102  static const property_path conflicting_meeting_count =
19103  "calendar:ConflictingMeetingCount";
19104  static const property_path adjacent_meeting_count =
19105  "calendar:AdjacentMeetingCount";
19106  static const property_path conflicting_meetings =
19107  "calendar:ConflictingMeetings";
19108  static const property_path adjacent_meetings = "calendar:AdjacentMeetings";
19109  static const property_path duration = "calendar:Duration";
19110  static const property_path time_zone = "calendar:TimeZone";
19111  static const property_path appointment_reply_time =
19112  "calendar:AppointmentReplyTime";
19113  static const property_path appointment_sequence_number =
19114  "calendar:AppointmentSequenceNumber";
19115  static const property_path appointment_state = "calendar:AppointmentState";
19116  static const property_path recurrence = "calendar:Recurrence";
19117  static const property_path first_occurrence = "calendar:FirstOccurrence";
19118  static const property_path last_occurrence = "calendar:LastOccurrence";
19119  static const property_path modified_occurrences =
19120  "calendar:ModifiedOccurrences";
19121  static const property_path deleted_occurrences =
19122  "calendar:DeletedOccurrences";
19123  static const property_path meeting_time_zone = "calendar:MeetingTimeZone";
19124  static const property_path conference_type = "calendar:ConferenceType";
19125  static const property_path allow_new_time_proposal =
19126  "calendar:AllowNewTimeProposal";
19127  static const property_path is_online_meeting = "calendar:IsOnlineMeeting";
19128  static const property_path meeting_workspace_url =
19129  "calendar:MeetingWorkspaceUrl";
19130  static const property_path net_show_url = "calendar:NetShowUrl";
19131  static const property_path uid = "calendar:UID";
19132  static const property_path recurrence_id = "calendar:RecurrenceId";
19133  static const property_path date_time_stamp = "calendar:DateTimeStamp";
19134  static const property_path start_time_zone = "calendar:StartTimeZone";
19135  static const property_path end_time_zone = "calendar:EndTimeZone";
19136  static const property_path join_online_meeting_url =
19137  "calendar:JoinOnlineMeetingUrl";
19138  static const property_path online_meeting_settings =
19139  "calendar:OnlineMeetingSettings";
19140  static const property_path is_organizer = "calendar:IsOrganizer";
19141 } // namespace calendar_property_path
19142 
19143 namespace task_property_path
19144 {
19145  static const property_path actual_work = "task:ActualWork";
19146  static const property_path assigned_time = "task:AssignedTime";
19147  static const property_path billing_information = "task:BillingInformation";
19148  static const property_path change_count = "task:ChangeCount";
19149  static const property_path companies = "task:Companies";
19150  static const property_path complete_date = "task:CompleteDate";
19151  static const property_path contacts = "task:Contacts";
19152  static const property_path delegation_state = "task:DelegationState";
19153  static const property_path delegator = "task:Delegator";
19154  static const property_path due_date = "task:DueDate";
19155  static const property_path is_assignment_editable =
19156  "task:IsAssignmentEditable";
19157  static const property_path is_complete = "task:IsComplete";
19158  static const property_path is_recurring = "task:IsRecurring";
19159  static const property_path is_team_task = "task:IsTeamTask";
19160  static const property_path mileage = "task:Mileage";
19161  static const property_path owner = "task:Owner";
19162  static const property_path percent_complete = "task:PercentComplete";
19163  static const property_path recurrence = "task:Recurrence";
19164  static const property_path start_date = "task:StartDate";
19165  static const property_path status = "task:Status";
19166  static const property_path status_description = "task:StatusDescription";
19167  static const property_path total_work = "task:TotalWork";
19168 } // namespace task_property_path
19169 
19170 namespace contact_property_path
19171 {
19172  static const property_path alias = "contacts:Alias";
19173  static const property_path assistant_name = "contacts:AssistantName";
19174  static const property_path birthday = "contacts:Birthday";
19175  static const property_path business_home_page = "contacts:BusinessHomePage";
19176  static const property_path children = "contacts:Children";
19177  static const property_path companies = "contacts:Companies";
19178  static const property_path company_name = "contacts:CompanyName";
19179  static const property_path complete_name = "contacts:CompleteName";
19180  static const property_path contact_source = "contacts:ContactSource";
19181  static const property_path culture = "contacts:Culture";
19182  static const property_path department = "contacts:Department";
19183  static const property_path display_name = "contacts:DisplayName";
19184  static const property_path directory_id = "contacts:DirectoryId";
19185  static const property_path direct_reports = "contacts:DirectReports";
19186  static const property_path email_addresses = "contacts:EmailAddresses";
19187  static const property_path email_address = "contacts:EmailAddress";
19188  static const indexed_property_path email_address_1("contacts:EmailAddress",
19189  "EmailAddress1");
19190  static const indexed_property_path email_address_2("contacts:EmailAddress",
19191  "EmailAddress2");
19192  static const indexed_property_path email_address_3("contacts:EmailAddress",
19193  "EmailAddress3");
19194  static const property_path file_as = "contacts:FileAs";
19195  static const property_path file_as_mapping = "contacts:FileAsMapping";
19196  static const property_path generation = "contacts:Generation";
19197  static const property_path given_name = "contacts:GivenName";
19198  static const property_path im_addresses = "contacts:ImAddresses";
19199  static const property_path im_address = "contacts:ImAddress";
19200  static const indexed_property_path im_address_1("contacts:ImAddress",
19201  "ImAddress1");
19202  static const indexed_property_path im_address_2("contacts:ImAddress",
19203  "ImAddress2");
19204  static const indexed_property_path im_address_3("contacts:ImAddress",
19205  "ImAddress3");
19206  static const property_path initials = "contacts:Initials";
19207  static const property_path job_title = "contacts:JobTitle";
19208  static const property_path manager = "contacts:Manager";
19209  static const property_path manager_mailbox = "contacts:ManagerMailbox";
19210  static const property_path middle_name = "contacts:MiddleName";
19211  static const property_path mileage = "contacts:Mileage";
19212  static const property_path ms_exchange_certificate =
19213  "contacts:MSExchangeCertificate";
19214  static const property_path nickname = "contacts:Nickname";
19215  static const property_path notes = "contacts:Notes";
19216  static const property_path office_location = "contacts:OfficeLocation";
19217  static const property_path phone_numbers = "contacts:PhoneNumbers";
19218 
19219  namespace phone_number
19220  {
19221  static const indexed_property_path
19222  assistant_phone("contacts:PhoneNumber", "AssistantPhone");
19223  static const indexed_property_path business_fax("contacts:PhoneNumber",
19224  "BusinessFax");
19225  static const indexed_property_path
19226  business_phone("contacts:PhoneNumber", "BusinessPhone");
19227  static const indexed_property_path
19228  business_phone_2("contacts:PhoneNumber", "BusinessPhone2");
19229  static const indexed_property_path callback("contacts:PhoneNumber",
19230  "Callback");
19231  static const indexed_property_path car_phone("contacts:PhoneNumber",
19232  "CarPhone");
19233  static const indexed_property_path
19234  company_main_phone("contacts:PhoneNumber", "CompanyMainPhone");
19235  static const indexed_property_path home_fax("contacts:PhoneNumber",
19236  "HomeFax");
19237  static const indexed_property_path home_phone("contacts:PhoneNumber",
19238  "HomePhone");
19239  static const indexed_property_path home_phone_2("contacts:PhoneNumber",
19240  "HomePhone2");
19241  static const indexed_property_path isdn("contacts:PhoneNumber", "Isdn");
19242 
19243  static const indexed_property_path mobile_phone("contacts:PhoneNumber",
19244  "MobilePhone");
19245  static const indexed_property_path other_fax("contacts:PhoneNumber",
19246  "OtherFax");
19247  static const indexed_property_path
19248  other_telephone("contacts:PhoneNumber", "OtherTelephone");
19249  static const indexed_property_path pager("contacts:PhoneNumber",
19250  "Pager");
19251  static const indexed_property_path primary_phone("contacts:PhoneNumber",
19252  "PrimaryPhone");
19253  static const indexed_property_path radio_phone("contacts:PhoneNumber",
19254  "RadioPhone");
19255  static const indexed_property_path telex("contacts:PhoneNumber",
19256  "Telex");
19257  static const indexed_property_path tty_tdd_phone("contacts:PhoneNumber",
19258  "TtyTddPhone");
19259  } // namespace phone_number
19260 
19261  static const property_path phonetic_full_name = "contacts:PhoneticFullName";
19262  static const property_path phonetic_first_name =
19263  "contacts:PhoneticFirstName";
19264  static const property_path phonetic_last_name = "contacts:PhoneticLastName";
19265  static const property_path photo = "contacts:Photo";
19266  static const property_path physical_addresses =
19267  "contacts:PhysicalAddresses";
19268 
19269  namespace physical_address
19270  {
19271  namespace business
19272  {
19273  static const indexed_property_path
19274  street("contacts:PhysicalAddress:Street", "Business");
19275  static const indexed_property_path
19276  city("contacts:PhysicalAddress:City", "Business");
19277  static const indexed_property_path
19278  state("contacts:PhysicalAddress:State", "Business");
19279  static const indexed_property_path
19280  country_or_region("contacts:PhysicalAddress:CountryOrRegion",
19281  "Business");
19282  static const indexed_property_path
19283  postal_code("contacts:PhysicalAddress:PostalCode", "Business");
19284  } // namespace business
19285  namespace home
19286  {
19287  static const indexed_property_path
19288  street("contacts:PhysicalAddress:Street", "Home");
19289  static const indexed_property_path
19290  city("contacts:PhysicalAddress:City", "Home");
19291  static const indexed_property_path
19292  state("contacts:PhysicalAddress:State", "Home");
19293  static const indexed_property_path
19294  country_or_region("contacts:PhysicalAddress:CountryOrRegion",
19295  "Home");
19296  static const indexed_property_path
19297  postal_code("contacts:PhysicalAddress:PostalCode", "Home");
19298  } // namespace home
19299  namespace other
19300  {
19301  static const indexed_property_path
19302  street("contacts:PhysicalAddress:Street", "Other");
19303  static const indexed_property_path
19304  city("contacts:PhysicalAddress:City", "Other");
19305  static const indexed_property_path
19306  state("contacts:PhysicalAddress:State", "Other");
19307  static const indexed_property_path
19308  country_or_region("contacts:PhysicalAddress:CountryOrRegion",
19309  "Other");
19310  static const indexed_property_path
19311  postal_code("contacts:PhysicalAddress:PostalCode", "Other");
19312  } // namespace other
19313  } // namespace physical_address
19314 
19315  static const property_path postal_address_index =
19316  "contacts:PostalAddressIndex";
19317  static const property_path profession = "contacts:Profession";
19318  static const property_path spouse_name = "contacts:SpouseName";
19319  static const property_path surname = "contacts:Surname";
19320  static const property_path wedding_anniversary =
19321  "contacts:WeddingAnniversary";
19322  static const property_path smime_certificate =
19323  "contacts:UserSMIMECertificate";
19324  static const property_path has_picture = "contacts:HasPicture";
19325 } // namespace contact_property_path
19326 
19327 namespace distribution_list_property_path
19328 {
19329  static const property_path members = "distributionlist:Members";
19330 }
19331 
19332 namespace post_item_property_path
19333 {
19334  static const property_path posted_time = "postitem:PostedTime";
19335 }
19336 
19337 namespace conversation_property_path
19338 {
19339  static const property_path conversation_id = "conversation:ConversationId";
19340  static const property_path conversation_topic =
19341  "conversation:ConversationTopic";
19342  static const property_path unique_recipients =
19343  "conversation:UniqueRecipients";
19344  static const property_path global_unique_recipients =
19345  "conversation:GlobalUniqueRecipients";
19346  static const property_path unique_unread_senders =
19347  "conversation:UniqueUnreadSenders";
19348  static const property_path global_unique_unread_readers =
19349  "conversation:GlobalUniqueUnreadSenders";
19350  static const property_path unique_senders = "conversation:UniqueSenders";
19351  static const property_path global_unique_senders =
19352  "conversation:GlobalUniqueSenders";
19353  static const property_path last_delivery_time =
19354  "conversation:LastDeliveryTime";
19355  static const property_path global_last_delivery_time =
19356  "conversation:GlobalLastDeliveryTime";
19357  static const property_path categories = "conversation:Categories";
19358  static const property_path global_categories =
19359  "conversation:GlobalCategories";
19360  static const property_path flag_status = "conversation:FlagStatus";
19361  static const property_path global_flag_status =
19362  "conversation:GlobalFlagStatus";
19363  static const property_path has_attachments = "conversation:HasAttachments";
19364  static const property_path global_has_attachments =
19365  "conversation:GlobalHasAttachments";
19366  static const property_path has_irm = "conversation:HasIrm";
19367  static const property_path global_has_irm = "conversation:GlobalHasIrm";
19368  static const property_path message_count = "conversation:MessageCount";
19369  static const property_path global_message_count =
19370  "conversation:GlobalMessageCount";
19371  static const property_path unread_count = "conversation:UnreadCount";
19372  static const property_path global_unread_count =
19373  "conversation:GlobalUnreadCount";
19374  static const property_path size = "conversation:Size";
19375  static const property_path global_size = "conversation:GlobalSize";
19376  static const property_path item_classes = "conversation:ItemClasses";
19377  static const property_path global_item_classes =
19378  "conversation:GlobalItemClasses";
19379  static const property_path importance = "conversation:Importance";
19380  static const property_path global_importance =
19381  "conversation:GlobalImportance";
19382  static const property_path item_ids = "conversation:ItemIds";
19383  static const property_path global_item_ids = "conversation:GlobalItemIds";
19384  static const property_path last_modified_time =
19385  "conversation:LastModifiedTime";
19386  static const property_path instance_key = "conversation:InstanceKey";
19387  static const property_path preview = "conversation:Preview";
19388  static const property_path global_parent_folder_id =
19389  "conversation:GlobalParentFolderId";
19390  static const property_path next_predicted_action =
19391  "conversation:NextPredictedAction";
19392  static const property_path grouping_action = "conversation:GroupingAction";
19393  static const property_path icon_index = "conversation:IconIndex";
19394  static const property_path global_icon_index =
19395  "conversation:GlobalIconIndex";
19396  static const property_path draft_item_ids = "conversation:DraftItemIds";
19397  static const property_path has_clutter = "conversation:HasClutter";
19398 } // namespace conversation_property_path
19399 
19403 class property final
19404 {
19405 public:
19406  // TODO: shouldn't the c'tors take const& instead?
19407 
19409  explicit property(property_path path) : value_(path.to_xml()) {}
19410 
19413  explicit property(indexed_property_path path) : value_(path.to_xml()) {}
19414 
19415  // Use this constructor (and following overloads) whenever you want to
19416  // set or update an item's property
19417  property(property_path path, const std::string& value)
19418  : value_(path.to_xml(internal::escape(value)))
19419  {
19420  }
19421 
19422  property(property_path path, const char* value)
19423  : value_(path.to_xml(internal::escape(value)))
19424  {
19425  }
19426 
19427  property(property_path path, int value)
19428  : value_(path.to_xml(std::to_string(value)))
19429  {
19430  }
19431 
19432  property(property_path path, long value)
19433  : value_(path.to_xml(std::to_string(value)))
19434  {
19435  }
19436 
19437  property(property_path path, long long value)
19438  : value_(path.to_xml(std::to_string(value)))
19439  {
19440  }
19441 
19442  property(property_path path, unsigned value)
19443  : value_(path.to_xml(std::to_string(value)))
19444  {
19445  }
19446 
19447  property(property_path path, unsigned long value)
19448  : value_(path.to_xml(std::to_string(value)))
19449  {
19450  }
19451 
19452  property(property_path path, unsigned long long value)
19453  : value_(path.to_xml(std::to_string(value)))
19454  {
19455  }
19456 
19457  property(property_path path, float value)
19458  : value_(path.to_xml(std::to_string(value)))
19459  {
19460  }
19461 
19462  property(property_path path, double value)
19463  : value_(path.to_xml(std::to_string(value)))
19464  {
19465  }
19466 
19467  property(property_path path, long double value)
19468  : value_(path.to_xml(std::to_string(value)))
19469  {
19470  }
19471 
19472  property(property_path path, bool value)
19473  : value_(path.to_xml((value ? "true" : "false")))
19474  {
19475  }
19476 
19477 #ifdef EWS_HAS_DEFAULT_TEMPLATE_ARGS_FOR_FUNCTIONS
19478  template <typename T,
19479  typename = typename std::enable_if<std::is_enum<T>::value>::type>
19480  property(property_path path, T enum_value)
19481  : value_(path.to_xml(internal::enum_to_str(enum_value)))
19482  {
19483  }
19484 #else
19485  property(property_path path, free_busy_status enum_value)
19486  : value_(path.to_xml(internal::enum_to_str(enum_value)))
19487  {
19488  }
19489 
19490  property(property_path path, sensitivity enum_value)
19491  : value_(path.to_xml(internal::enum_to_str(enum_value)))
19492  {
19493  }
19494 #endif
19495 
19496  property(property_path path, const body& value)
19497  : value_(path.to_xml(value.to_xml()))
19498  {
19499  }
19500 
19501  property(property_path path, const date_time& value)
19502  : value_(path.to_xml(value.to_string()))
19503  {
19504  }
19505 
19506  property(property_path path, const mailbox& value)
19507  : value_(path.to_xml(value.to_xml()))
19508  {
19509  }
19510 
19511  property(property_path path, const recurrence_pattern& pattern,
19512  const recurrence_range& range)
19513  : value_()
19514  {
19515  std::stringstream sstr;
19516  sstr << "<t:Recurrence>" << pattern.to_xml() << range.to_xml()
19517  << "</t:Recurrence>";
19518  value_ = path.to_xml(sstr.str());
19519  }
19520 
19521  template <typename T>
19522  property(property_path path, const std::vector<T>& value) : value_()
19523  {
19524  std::stringstream sstr;
19525  for (const auto& elem : value)
19526  {
19527  sstr << elem.to_xml();
19528  }
19529  value_ = path.to_xml(sstr.str());
19530  }
19531 
19532  property(property_path path, const std::vector<std::string>& value)
19533  : value_()
19534  {
19535  std::stringstream sstr;
19536  for (const auto& str : value)
19537  {
19538  sstr << "<t:String>" << str << "</t:String>";
19539  }
19540  value_ = path.to_xml(sstr.str());
19541  }
19542 
19543  property(const indexed_property_path& path, const physical_address& address)
19544  : value_(path.to_xml(address.to_xml()))
19545  {
19546  }
19547 
19548  property(const indexed_property_path& path, const im_address& address)
19549  : value_(path.to_xml(address.to_xml()))
19550  {
19551  }
19552 
19553  property(const indexed_property_path& path, const email_address& address)
19554  : value_(path.to_xml(address.to_xml()))
19555  {
19556  }
19557 
19558  property(const indexed_property_path& path, const phone_number& number)
19559  : value_(path.to_xml(number.to_xml()))
19560  {
19561  }
19562 
19563  const std::string& to_xml() const EWS_NOEXCEPT { return value_; }
19564 
19565 private:
19566  std::string value_;
19567 };
19568 
19569 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19570  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19571 static_assert(!std::is_default_constructible<property>::value);
19572 static_assert(std::is_copy_constructible<property>::value);
19573 static_assert(std::is_copy_assignable<property>::value);
19574 static_assert(std::is_move_constructible<property>::value);
19575 static_assert(std::is_move_assignable<property>::value);
19576 #endif
19577 
19579 class item_shape final
19580 {
19581 public:
19582  item_shape()
19583  : base_shape_(base_shape::default_shape), body_type_(body_type::best),
19584  filter_html_content_(false), include_mime_content_(false),
19585  convert_html_code_page_to_utf8_(true)
19586  {
19587  }
19588 
19589  item_shape(base_shape shape) // intentionally not explicit
19590  : base_shape_(shape), body_type_(body_type::best),
19591  filter_html_content_(false), include_mime_content_(false),
19592  convert_html_code_page_to_utf8_(true)
19593  {
19594  }
19595 
19596  item_shape(base_shape shape,
19597  std::vector<extended_field_uri>&& extended_field_uris)
19598  : base_shape_(shape), body_type_(body_type::best),
19599  extended_field_uris_(std::move(extended_field_uris)),
19600  filter_html_content_(false), include_mime_content_(false),
19601  convert_html_code_page_to_utf8_(true)
19602  {
19603  }
19604 
19605  explicit item_shape(std::vector<property_path>&& additional_properties)
19606  : base_shape_(base_shape::default_shape), body_type_(body_type::best),
19607  additional_properties_(std::move(additional_properties)),
19608  filter_html_content_(false), include_mime_content_(false),
19609  convert_html_code_page_to_utf8_(true)
19610  {
19611  }
19612 
19613  explicit item_shape(std::vector<extended_field_uri>&& extended_field_uris)
19614  : base_shape_(base_shape::default_shape), body_type_(body_type::best),
19615  extended_field_uris_(std::move(extended_field_uris)),
19616  filter_html_content_(false), include_mime_content_(false),
19617  convert_html_code_page_to_utf8_(true)
19618  {
19619  }
19620 
19621  item_shape(std::vector<property_path>&& additional_properties,
19622  std::vector<extended_field_uri>&& extended_field_uris)
19623  : base_shape_(base_shape::default_shape), body_type_(body_type::best),
19624  additional_properties_(std::move(additional_properties)),
19625  extended_field_uris_(std::move(extended_field_uris)),
19626  filter_html_content_(false), include_mime_content_(false),
19627  convert_html_code_page_to_utf8_(true)
19628  {
19629  }
19630 
19631  std::string to_xml() const
19632  {
19633  std::stringstream sstr;
19634 
19635  sstr << "<m:ItemShape>"
19636 
19637  "<t:BaseShape>";
19638  sstr << internal::enum_to_str(base_shape_);
19639  sstr << "</t:BaseShape>"
19640 
19641  "<t:BodyType>";
19642  sstr << internal::body_type_str(body_type_);
19643  sstr << "</t:BodyType>"
19644 
19645  "<t:AdditionalProperties>";
19646  for (const auto& prop : additional_properties_)
19647  {
19648  sstr << prop.to_xml();
19649  }
19650  for (auto field : extended_field_uris_)
19651  {
19652  sstr << field.to_xml();
19653  }
19654  sstr << "</t:AdditionalProperties>"
19655 
19656  "<t:FilterHtmlContent>";
19657  sstr << (filter_html_content_ ? "true" : "false");
19658  sstr << "</t:FilterHtmlContent>"
19659 
19660  "<t:IncludeMimeContent>";
19661  sstr << (include_mime_content_ ? "true" : "false");
19662  sstr << "</t:IncludeMimeContent>"
19663 
19664  "<t:ConvertHtmlCodePageToUTF8>";
19665  sstr << (convert_html_code_page_to_utf8_ ? "true" : "false");
19666  sstr << "</t:ConvertHtmlCodePageToUTF8>"
19667 
19668  "</m:ItemShape>";
19669 
19670  return sstr.str();
19671  }
19672 
19673  base_shape get_base_shape() const EWS_NOEXCEPT { return base_shape_; }
19674 
19675  body_type get_body_type() const EWS_NOEXCEPT { return body_type_; }
19676 
19677  const std::vector<property_path>&
19678  get_additional_properties() const EWS_NOEXCEPT
19679  {
19680  return additional_properties_;
19681  }
19682 
19683  const std::vector<extended_field_uri>&
19684  get_extended_field_uris() const EWS_NOEXCEPT
19685  {
19686  return extended_field_uris_;
19687  }
19688 
19689  bool has_filter_html_content() const EWS_NOEXCEPT
19690  {
19691  return filter_html_content_;
19692  }
19693 
19694  bool has_include_mime_content() const EWS_NOEXCEPT
19695  {
19696  return include_mime_content_;
19697  }
19698 
19699  bool has_convert_html_code_page_to_utf8() const EWS_NOEXCEPT
19700  {
19701  return convert_html_code_page_to_utf8_;
19702  }
19703 
19704  void set_base_shape(base_shape base_shape) { base_shape_ = base_shape; }
19705 
19706  void set_body_type(body_type body_type) { body_type_ = body_type; }
19707 
19708  void set_filter_html_content(bool filter_html_content)
19709  {
19710  filter_html_content_ = filter_html_content;
19711  }
19712 
19713  void set_include_mime_content(bool include_mime_content)
19714  {
19715  include_mime_content_ = include_mime_content;
19716  }
19717 
19718  void
19719  set_convert_html_code_page_to_utf8_(bool convert_html_code_page_to_utf8)
19720  {
19721  convert_html_code_page_to_utf8_ = convert_html_code_page_to_utf8;
19722  }
19723 
19724 private:
19725  base_shape base_shape_;
19726  body_type body_type_;
19727  std::vector<property_path> additional_properties_;
19728  std::vector<extended_field_uri> extended_field_uris_;
19729  bool filter_html_content_;
19730  bool include_mime_content_;
19731  bool convert_html_code_page_to_utf8_;
19732 };
19733 
19734 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19735  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19736 static_assert(std::is_default_constructible<item_shape>::value);
19737 static_assert(std::is_copy_constructible<item_shape>::value);
19738 static_assert(std::is_copy_assignable<item_shape>::value);
19739 static_assert(std::is_move_constructible<item_shape>::value);
19740 static_assert(std::is_move_assignable<item_shape>::value);
19741 #endif
19742 
19763 {
19764 public:
19765 #ifdef EWS_HAS_DEFAULT_AND_DELETE
19766  search_expression() = delete;
19767 #endif
19768 
19769  std::string to_xml() const { return func_(); }
19770 
19771 protected:
19772  explicit search_expression(std::function<std::string()>&& func)
19773  : func_(std::move(func))
19774  {
19775  }
19776 
19777  // Used by sub-classes to share common code
19778  search_expression(const char* term, property_path path, bool b)
19779  : func_([=]() -> std::string {
19780  std::stringstream sstr;
19781 
19782  sstr << "<t:" << term << ">";
19783  sstr << path.to_xml();
19784  sstr << "<t:FieldURIOrConstant>";
19785  sstr << "<t:Constant Value=\"";
19786  sstr << std::boolalpha << b;
19787  sstr << "\"/></t:FieldURIOrConstant></t:";
19788  sstr << term << ">";
19789  return sstr.str();
19790  })
19791  {
19792  }
19793 
19794  search_expression(const char* term, property_path path, int i)
19795  : func_([=]() -> std::string {
19796  std::stringstream sstr;
19797 
19798  sstr << "<t:" << term << ">";
19799  sstr << path.to_xml();
19800  sstr << "<t:"
19801  << "FieldURIOrConstant>";
19802  sstr << "<t:Constant Value=\"";
19803  sstr << std::to_string(i);
19804  sstr << "\"/></t:FieldURIOrConstant></t:";
19805  sstr << term << ">";
19806  return sstr.str();
19807  })
19808  {
19809  }
19810 
19811  search_expression(const char* term, property_path path, const char* str)
19812  : func_([=]() -> std::string {
19813  std::stringstream sstr;
19814 
19815  sstr << "<t:" << term << ">";
19816  sstr << path.to_xml();
19817  sstr << "<t:"
19818  << "FieldURIOrConstant>";
19819  sstr << "<t:Constant Value=\"";
19820  sstr << str;
19821  sstr << "\"/></t:FieldURIOrConstant></t:";
19822  sstr << term << ">";
19823  return sstr.str();
19824  })
19825  {
19826  }
19827 
19828  search_expression(const char* term, indexed_property_path path,
19829  const char* str)
19830  : func_([=]() -> std::string {
19831  std::stringstream sstr;
19832 
19833  sstr << "<t:" << term << ">";
19834  sstr << path.to_xml();
19835  sstr << "<t:FieldURIOrConstant>";
19836  sstr << "<t:Constant Value=\"";
19837  sstr << str;
19838  sstr << "\"/></t:FieldURIOrConstant></t:";
19839  sstr << term << ">";
19840  return sstr.str();
19841  })
19842  {
19843  }
19844 
19845  search_expression(const char* term, property_path path, date_time when)
19846  : func_([=]() -> std::string {
19847  std::stringstream sstr;
19848 
19849  sstr << "<t:" << term << ">";
19850  sstr << path.to_xml();
19851  sstr << "<t:FieldURIOrConstant>";
19852  sstr << "<t:Constant Value=\"";
19853  sstr << when.to_string();
19854  sstr << "\"/></t:FieldURIOrConstant></t:";
19855  sstr << term << ">";
19856  return sstr.str();
19857  })
19858  {
19859  }
19860 
19861 private:
19862  std::function<std::string()> func_;
19863 };
19864 
19865 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19866  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19867 static_assert(!std::is_default_constructible<search_expression>::value);
19868 static_assert(std::is_copy_constructible<search_expression>::value);
19869 static_assert(std::is_copy_assignable<search_expression>::value);
19870 static_assert(std::is_move_constructible<search_expression>::value);
19871 static_assert(std::is_move_assignable<search_expression>::value);
19872 #endif
19873 
19878 class is_equal_to final : public search_expression
19879 {
19880 public:
19881  is_equal_to(property_path path, bool b)
19882  : search_expression("IsEqualTo", std::move(path), b)
19883  {
19884  }
19885 
19886  is_equal_to(property_path path, int i)
19887  : search_expression("IsEqualTo", std::move(path), i)
19888  {
19889  }
19890 
19891  is_equal_to(property_path path, const char* str)
19892  : search_expression("IsEqualTo", std::move(path), str)
19893  {
19894  }
19895 
19896  is_equal_to(indexed_property_path path, const char* str)
19897  : search_expression("IsEqualTo", std::move(path), str)
19898  {
19899  }
19900 
19901  is_equal_to(property_path path, date_time when)
19902  : search_expression("IsEqualTo", std::move(path), std::move(when))
19903  {
19904  }
19905 
19906  // TODO: is_equal_to(property_path, property_path) {}
19907 };
19908 
19909 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19910  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19911 static_assert(!std::is_default_constructible<is_equal_to>::value);
19912 static_assert(std::is_copy_constructible<is_equal_to>::value);
19913 static_assert(std::is_copy_assignable<is_equal_to>::value);
19914 static_assert(std::is_move_constructible<is_equal_to>::value);
19915 static_assert(std::is_move_assignable<is_equal_to>::value);
19916 #endif
19917 
19923 {
19924 public:
19925  is_not_equal_to(property_path path, bool b)
19926  : search_expression("IsNotEqualTo", std::move(path), b)
19927  {
19928  }
19929 
19930  is_not_equal_to(property_path path, int i)
19931  : search_expression("IsNotEqualTo", std::move(path), i)
19932  {
19933  }
19934 
19935  is_not_equal_to(property_path path, const char* str)
19936  : search_expression("IsNotEqualTo", std::move(path), str)
19937  {
19938  }
19939 
19940  is_not_equal_to(indexed_property_path path, const char* str)
19941  : search_expression("IsNotEqualTo", std::move(path), str)
19942  {
19943  }
19944 
19946  : search_expression("IsNotEqualTo", std::move(path), std::move(when))
19947  {
19948  }
19949 };
19950 
19951 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19952  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19953 static_assert(!std::is_default_constructible<is_not_equal_to>::value);
19954 static_assert(std::is_copy_constructible<is_not_equal_to>::value);
19955 static_assert(std::is_copy_assignable<is_not_equal_to>::value);
19956 static_assert(std::is_move_constructible<is_not_equal_to>::value);
19957 static_assert(std::is_move_assignable<is_not_equal_to>::value);
19958 #endif
19959 
19962 {
19963 public:
19964  is_greater_than(property_path path, bool b)
19965  : search_expression("IsGreaterThan", std::move(path), b)
19966  {
19967  }
19968 
19969  is_greater_than(property_path path, int i)
19970  : search_expression("IsGreaterThan", std::move(path), i)
19971  {
19972  }
19973 
19974  is_greater_than(property_path path, const char* str)
19975  : search_expression("IsGreaterThan", std::move(path), str)
19976  {
19977  }
19978 
19979  is_greater_than(indexed_property_path path, const char* str)
19980  : search_expression("IsGreaterThan", std::move(path), str)
19981  {
19982  }
19983 
19985  : search_expression("IsGreaterThan", std::move(path), std::move(when))
19986  {
19987  }
19988 };
19989 
19990 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
19991  defined(EWS_HAS_CXX17_STATIC_ASSERT)
19992 static_assert(!std::is_default_constructible<is_greater_than>::value);
19993 static_assert(std::is_copy_constructible<is_greater_than>::value);
19994 static_assert(std::is_copy_assignable<is_greater_than>::value);
19995 static_assert(std::is_move_constructible<is_greater_than>::value);
19996 static_assert(std::is_move_assignable<is_greater_than>::value);
19997 #endif
19998 
20001 {
20002 public:
20004  : search_expression("IsGreaterThanOrEqualTo", std::move(path), b)
20005  {
20006  }
20007 
20009  : search_expression("IsGreaterThanOrEqualTo", std::move(path), i)
20010  {
20011  }
20012 
20013  is_greater_than_or_equal_to(property_path path, const char* str)
20014  : search_expression("IsGreaterThanOrEqualTo", std::move(path), str)
20015  {
20016  }
20017 
20018  is_greater_than_or_equal_to(indexed_property_path path, const char* str)
20019  : search_expression("IsGreaterThanOrEqualTo", std::move(path), str)
20020  {
20021  }
20022 
20024  : search_expression("IsGreaterThanOrEqualTo", std::move(path),
20025  std::move(when))
20026  {
20027  }
20028 };
20029 
20030 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20031  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20032 static_assert(
20033  !std::is_default_constructible<is_greater_than_or_equal_to>::value);
20034 static_assert(std::is_copy_constructible<is_greater_than_or_equal_to>::value);
20035 static_assert(std::is_copy_assignable<is_greater_than_or_equal_to>::value);
20036 static_assert(std::is_move_constructible<is_greater_than_or_equal_to>::value);
20037 static_assert(std::is_move_assignable<is_greater_than_or_equal_to>::value);
20038 #endif
20039 
20041 class is_less_than final : public search_expression
20042 {
20043 public:
20044  is_less_than(property_path path, bool b)
20045  : search_expression("IsLessThan", std::move(path), b)
20046  {
20047  }
20048 
20049  is_less_than(property_path path, int i)
20050  : search_expression("IsLessThan", std::move(path), i)
20051  {
20052  }
20053 
20054  is_less_than(property_path path, const char* str)
20055  : search_expression("IsLessThan", std::move(path), str)
20056  {
20057  }
20058 
20059  is_less_than(indexed_property_path path, const char* str)
20060  : search_expression("IsLessThan", std::move(path), str)
20061  {
20062  }
20063 
20065  : search_expression("IsLessThan", std::move(path), std::move(when))
20066  {
20067  }
20068 };
20069 
20070 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20071  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20072 static_assert(!std::is_default_constructible<is_less_than>::value);
20073 static_assert(std::is_copy_constructible<is_less_than>::value);
20074 static_assert(std::is_copy_assignable<is_less_than>::value);
20075 static_assert(std::is_move_constructible<is_less_than>::value);
20076 static_assert(std::is_move_assignable<is_less_than>::value);
20077 #endif
20078 
20081 {
20082 public:
20084  : search_expression("IsLessThanOrEqualTo", std::move(path), b)
20085  {
20086  }
20087 
20089  : search_expression("IsLessThanOrEqualTo", std::move(path), i)
20090  {
20091  }
20092 
20093  is_less_than_or_equal_to(property_path path, const char* str)
20094  : search_expression("IsLessThanOrEqualTo", std::move(path), str)
20095  {
20096  }
20097 
20098  is_less_than_or_equal_to(indexed_property_path path, const char* str)
20099  : search_expression("IsLessThanOrEqualTo", std::move(path), str)
20100  {
20101  }
20102 
20104  : search_expression("IsLessThanOrEqualTo", std::move(path),
20105  std::move(when))
20106  {
20107  }
20108 };
20109 
20110 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20111  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20112 static_assert(!std::is_default_constructible<is_less_than_or_equal_to>::value);
20113 static_assert(std::is_copy_constructible<is_less_than_or_equal_to>::value);
20114 static_assert(std::is_copy_assignable<is_less_than_or_equal_to>::value);
20115 static_assert(std::is_move_constructible<is_less_than_or_equal_to>::value);
20116 static_assert(std::is_move_assignable<is_less_than_or_equal_to>::value);
20117 #endif
20118 
20121 class and_ final : public search_expression
20122 {
20123 public:
20125  : search_expression([=]() -> std::string {
20126  std::stringstream sstr;
20127 
20128  sstr << "<t:And"
20129  << ">";
20130  sstr << first.to_xml();
20131  sstr << second.to_xml();
20132  sstr << "</t:And>";
20133  return sstr.str();
20134  })
20135  {
20136  }
20137 };
20138 
20139 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20140  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20141 static_assert(!std::is_default_constructible<and_>::value);
20142 static_assert(std::is_copy_constructible<and_>::value);
20143 static_assert(std::is_copy_assignable<and_>::value);
20144 static_assert(std::is_move_constructible<and_>::value);
20145 static_assert(std::is_move_assignable<and_>::value);
20146 #endif
20147 
20150 class or_ final : public search_expression
20151 {
20152 public:
20154  : search_expression([=]() -> std::string {
20155  std::stringstream sstr;
20156 
20157  sstr << "<t:Or"
20158  << ">";
20159  sstr << first.to_xml();
20160  sstr << second.to_xml();
20161  sstr << "</t:Or>";
20162  return sstr.str();
20163  })
20164  {
20165  }
20166 };
20167 
20168 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20169  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20170 static_assert(!std::is_default_constructible<or_>::value);
20171 static_assert(std::is_copy_constructible<or_>::value);
20172 static_assert(std::is_copy_assignable<or_>::value);
20173 static_assert(std::is_move_constructible<or_>::value);
20174 static_assert(std::is_move_assignable<or_>::value);
20175 #endif
20176 
20178 class not_ final : public search_expression
20179 {
20180 public:
20181  not_(const search_expression& expr)
20182  : search_expression([=]() -> std::string {
20183  std::stringstream sstr;
20184 
20185  sstr << "<t:Not"
20186  << ">";
20187  sstr << expr.to_xml();
20188  sstr << "</t:Not>";
20189  return sstr.str();
20190  })
20191  {
20192  }
20193 };
20194 
20195 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20196  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20197 static_assert(!std::is_default_constructible<not_>::value);
20198 static_assert(std::is_copy_constructible<not_>::value);
20199 static_assert(std::is_copy_assignable<not_>::value);
20200 static_assert(std::is_move_constructible<not_>::value);
20201 static_assert(std::is_move_assignable<not_>::value);
20202 #endif
20203 
20209 {
20213  full_string,
20214 
20216  prefixed,
20217 
20220  substring,
20221 
20225 
20228  exact_phrase
20229 };
20230 
20231 namespace internal
20232 {
20233  inline std::string enum_to_str(containment_mode val)
20234  {
20235  switch (val)
20236  {
20238  return "FullString";
20240  return "Prefixed";
20242  return "Substring";
20244  return "PrefixOnWords";
20246  return "ExactPhrase";
20247  default:
20248  throw exception("Bad enum value");
20249  }
20250  }
20251 } // namespace internal
20252 
20258 {
20260  exact,
20261 
20263  ignore_case,
20264 
20267 
20270  loose,
20271 };
20272 
20273 namespace internal
20274 {
20275  inline std::string enum_to_str(containment_comparison val)
20276  {
20277  switch (val)
20278  {
20280  return "Exact";
20282  return "IgnoreCase";
20284  return "IgnoreNonSpacingCharacters";
20286  return "Loose";
20287  default:
20288  throw exception("Bad enum value");
20289  }
20290  }
20291 } // namespace internal
20292 
20296 class contains final : public search_expression
20297 {
20298 public:
20299  contains(property_path path, const char* str,
20302  : search_expression([=]() -> std::string {
20303  std::stringstream sstr;
20304 
20305  sstr << "<t:Contains ";
20306  sstr << "ContainmentMode=\"" << internal::enum_to_str(mode)
20307  << "\" ";
20308  sstr << "ContainmentComparison=\""
20309  << internal::enum_to_str(comparison) << "\">";
20310  sstr << path.to_xml();
20311  sstr << "<t:Constant Value=\"";
20312  sstr << str;
20313  sstr << "\"/></t:Contains>";
20314  return sstr.str();
20315  })
20316  {
20317  }
20318 };
20319 
20320 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20321  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20322 static_assert(!std::is_default_constructible<contains>::value);
20323 static_assert(std::is_copy_constructible<contains>::value);
20324 static_assert(std::is_copy_assignable<contains>::value);
20325 static_assert(std::is_move_constructible<contains>::value);
20326 static_assert(std::is_move_assignable<contains>::value);
20327 #endif
20328 
20332 class paging_view final
20333 {
20334 public:
20335  paging_view()
20336  : max_entries_returned_(1000), offset_(0),
20337  base_point_(paging_base_point::beginning)
20338  {
20339  }
20340 
20341  paging_view(uint32_t max_entries_returned)
20342  : max_entries_returned_(max_entries_returned), offset_(0),
20343  base_point_(paging_base_point::beginning)
20344  {
20345  }
20346 
20347  paging_view(uint32_t max_entries_returned, uint32_t offset)
20348  : max_entries_returned_(max_entries_returned), offset_(offset),
20349  base_point_(paging_base_point::beginning)
20350  {
20351  }
20352 
20353  paging_view(uint32_t max_entries_returned, uint32_t offset,
20354  paging_base_point base_point)
20355  : max_entries_returned_(max_entries_returned), offset_(offset),
20356  base_point_(base_point)
20357  {
20358  }
20359 
20360  uint32_t get_max_entries_returned() const EWS_NOEXCEPT
20361  {
20362  return max_entries_returned_;
20363  }
20364 
20365  uint32_t get_offset() const EWS_NOEXCEPT { return offset_; }
20366 
20367  std::string to_xml() const
20368  {
20369  return "<m:IndexedPageItemView MaxEntriesReturned=\"" +
20370  std::to_string(max_entries_returned_) + "\" Offset=\"" +
20371  std::to_string(offset_) + "\" BasePoint=\"" +
20372  internal::enum_to_str(base_point_) + "\" />";
20373  }
20374 
20375  void advance() { offset_ += max_entries_returned_; }
20376 
20377 private:
20378  uint32_t max_entries_returned_;
20379  uint32_t offset_;
20380  paging_base_point base_point_;
20381 };
20382 
20383 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20384  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20385 static_assert(std::is_default_constructible<paging_view>::value);
20386 static_assert(std::is_copy_constructible<paging_view>::value);
20387 static_assert(std::is_copy_assignable<paging_view>::value);
20388 static_assert(std::is_move_constructible<paging_view>::value);
20389 static_assert(std::is_move_assignable<paging_view>::value);
20390 #endif
20391 
20397 {
20398 public:
20399  calendar_view(date_time start_date, date_time end_date)
20400  : start_date_(std::move(start_date)), end_date_(std::move(end_date)),
20401  max_entries_returned_(0U), max_entries_set_(false)
20402  {
20403  }
20404 
20405  calendar_view(date_time start_date, date_time end_date,
20406  uint32_t max_entries_returned)
20407  : start_date_(std::move(start_date)), end_date_(std::move(end_date)),
20408  max_entries_returned_(max_entries_returned), max_entries_set_(true)
20409  {
20410  }
20411 
20412  uint32_t get_max_entries_returned() const EWS_NOEXCEPT
20413  {
20414  return max_entries_returned_;
20415  }
20416 
20417  const date_time& get_start_date() const EWS_NOEXCEPT { return start_date_; }
20418 
20419  const date_time& get_end_date() const EWS_NOEXCEPT { return end_date_; }
20420 
20421  std::string to_xml() const
20422  {
20423  std::stringstream sstr;
20424 
20425  sstr << "<m:CalendarView ";
20426  if (max_entries_set_)
20427  {
20428  sstr << "MaxEntriesReturned=\""
20429  << std::to_string(max_entries_returned_) << "\" ";
20430  }
20431  sstr << "StartDate=\"" << start_date_.to_string() << "\" EndDate=\""
20432  << end_date_.to_string() << "\" />";
20433  return sstr.str();
20434  }
20435 
20436 private:
20437  date_time start_date_;
20438  date_time end_date_;
20439  uint32_t max_entries_returned_;
20440  bool max_entries_set_;
20441 };
20442 
20443 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20444  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20445 static_assert(!std::is_default_constructible<calendar_view>::value);
20446 static_assert(std::is_copy_constructible<calendar_view>::value);
20447 static_assert(std::is_copy_assignable<calendar_view>::value);
20448 static_assert(std::is_move_constructible<calendar_view>::value);
20449 static_assert(std::is_move_assignable<calendar_view>::value);
20450 #endif
20451 
20456 class update final
20457 {
20458 public:
20459  enum class operation
20460  {
20466  set_item_field,
20467 
20479  append_to_item_field,
20480 
20484  delete_item_field,
20485  };
20486 
20487 #ifdef EWS_HAS_DEFAULT_AND_DELETE
20488  update() = delete;
20489 #endif
20490 
20491  // intentionally not explicit
20492  update(property prop, operation action = operation::set_item_field)
20493  : prop_(std::move(prop.to_xml())), op_(std::move(action))
20494  {
20495  }
20496 
20497  update(extended_property prop, operation action = operation::set_item_field)
20498  : prop_(prop.to_xml()), op_(std::move(action))
20499  {
20500  }
20501 
20503  std::string to_item_xml() const
20504  {
20505  std::string action = "SetItemField";
20506  if (op_ == operation::append_to_item_field)
20507  {
20508  action = "AppendToItemField";
20509  }
20510  else if (op_ == operation::delete_item_field)
20511  {
20512  action = "DeleteItemField";
20513  }
20514  std::stringstream sstr;
20515  sstr << "<t:" << action << ">";
20516  sstr << prop_;
20517  sstr << "</t:" << action << ">";
20518  return sstr.str();
20519  }
20520 
20522  std::string to_folder_xml() const
20523  {
20524  std::string action = "SetFolderField";
20525  if (op_ == operation::append_to_item_field)
20526  {
20527  action = "AppendToFolderField";
20528  }
20529  else if (op_ == operation::delete_item_field)
20530  {
20531  action = "DeleteFolderField";
20532  }
20533  std::stringstream sstr;
20534  sstr << "<t:" << action << ">";
20535  sstr << prop_;
20536  sstr << "</t:" << action << ">";
20537  return sstr.str();
20538  }
20539 
20540 private:
20541  std::string prop_;
20542  update::operation op_;
20543 };
20544 
20545 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20546  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20547 static_assert(!std::is_default_constructible<update>::value);
20548 static_assert(std::is_copy_constructible<update>::value);
20549 static_assert(std::is_copy_assignable<update>::value);
20550 static_assert(std::is_move_constructible<update>::value);
20551 static_assert(std::is_move_assignable<update>::value);
20552 #endif
20553 
20555 class connecting_sid final
20556 {
20557 public:
20558  enum class type
20559  {
20560  principal_name,
20561  sid,
20562  primary_smtp_address,
20563  smtp_address
20564  };
20565 
20566 #ifdef EWS_HAS_DEFAULT_AND_DELETE
20567  connecting_sid() = delete;
20568 #endif
20569 
20571  inline connecting_sid(type, const std::string&); // implemented below
20572 
20574  const std::string& to_xml() const EWS_NOEXCEPT { return xml_; }
20575 
20576 private:
20577  std::string xml_;
20578 };
20579 
20580 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
20581  defined(EWS_HAS_CXX17_STATIC_ASSERT)
20582 static_assert(!std::is_default_constructible<connecting_sid>::value);
20583 static_assert(std::is_copy_constructible<connecting_sid>::value);
20584 static_assert(std::is_copy_assignable<connecting_sid>::value);
20585 static_assert(std::is_move_constructible<connecting_sid>::value);
20586 static_assert(std::is_move_assignable<connecting_sid>::value);
20587 #endif
20588 
20589 namespace internal
20590 {
20591  inline std::string enum_to_str(connecting_sid::type type)
20592  {
20593  switch (type)
20594  {
20595  case connecting_sid::type::principal_name:
20596  return "PrincipalName";
20597  case connecting_sid::type::sid:
20598  return "SID";
20599  case connecting_sid::type::primary_smtp_address:
20600  return "PrimarySmtpAddress";
20601  case connecting_sid::type::smtp_address:
20602  return "SmtpAddress";
20603  default:
20604  throw exception("Unrecognized ConnectingSID");
20605  }
20606  }
20607 } // namespace internal
20608 
20609 connecting_sid::connecting_sid(connecting_sid::type t, const std::string& id)
20610  : xml_()
20611 {
20612  const auto sid = internal::enum_to_str(t);
20613  xml_ = "<t:ConnectingSID><t:" + sid + ">" + id + "</t:" + sid +
20614  "></t:ConnectingSID>";
20615 }
20616 
20619 enum class ssl_options : long
20620 {
20621  none = 0L,
20622  allow_beast = CURLSSLOPT_ALLOW_BEAST
20623 #if LIBCURL_VERSION_NUM >= 0x072C00
20624  ,
20625  no_revoke = CURLSSLOPT_NO_REVOKE
20626 #endif
20627 #if LIBCURL_VERSION_NUM >= 0x074400
20628  ,
20629  no_partialchain = CURLSSLOPT_NO_PARTIALCHAIN
20630 #endif
20631 #if LIBCURL_VERSION_NUM >= 0x074600
20632  ,
20633  revoke_best_effort = CURLSSLOPT_REVOKE_BEST_EFFORT
20634 #endif
20635 #if LIBCURL_VERSION_NUM >= 0x074700
20636  ,
20637  native_ca = CURLSSLOPT_NATIVE_CA
20638 #endif
20639 };
20640 
20641 inline ssl_options operator|(const ssl_options lhs, const ssl_options rhs)
20642 {
20643  return static_cast<ssl_options>(
20644  static_cast<std::underlying_type<ssl_options>::type>(lhs) |
20645  static_cast<std::underlying_type<ssl_options>::type>(rhs));
20646 }
20647 
20648 inline bool operator==(const ssl_options lhs, const ssl_options rhs)
20649 {
20650  return static_cast<std::underlying_type<ssl_options>::type>(lhs) ==
20651  static_cast<std::underlying_type<ssl_options>::type>(rhs);
20652 }
20653 
20654 inline bool operator!=(const ssl_options lhs, const ssl_options rhs)
20655 {
20656  return static_cast<std::underlying_type<ssl_options>::type>(lhs) !=
20657  static_cast<std::underlying_type<ssl_options>::type>(rhs);
20658 }
20659 
20711 template <typename RequestHandler = internal::http_request>
20712 class basic_service final
20713 {
20714 public:
20716  typedef std::function<void(const std::string&)> debug_callback;
20717 
20718 #ifdef EWS_HAS_DEFAULT_AND_DELETE
20719  basic_service() = delete;
20720 #endif
20721 
20726  basic_service(const std::string& server_uri, const std::string& domain,
20727  const std::string& username, const std::string& password)
20728  : request_handler_(server_uri), server_version_("Exchange2013_SP1"),
20729  impersonation_(), time_zone_(time_zone::none)
20730  {
20731  request_handler_.set_method(RequestHandler::method::POST);
20732  request_handler_.set_content_type("text/xml; charset=utf-8");
20733  ntlm_credentials creds(username, password, domain);
20734  request_handler_.set_credentials(creds);
20735  }
20736 
20739  basic_service(const std::string& server_uri,
20740  const internal::credentials& creds)
20741  : request_handler_(server_uri), server_version_("Exchange2013_SP1"),
20742  impersonation_(), time_zone_(time_zone::none)
20743  {
20744  request_handler_.set_method(RequestHandler::method::POST);
20745  request_handler_.set_content_type("text/xml; charset=utf-8");
20746  request_handler_.set_credentials(creds);
20747  }
20748 
20751  basic_service(const std::string& server_uri,
20752  const internal::credentials& creds, const std::string& cainfo,
20753  const std::string& capath, const std::string& proxy_uri,
20754  const bool is_http_proxy_tunneling,
20755  const debug_callback& callback,
20756  const ssl_options ssl_opts = ssl_options::none)
20757  : request_handler_(server_uri), server_version_("Exchange2013_SP1"),
20758  impersonation_(), time_zone_(time_zone::none)
20759  {
20760  if (!cainfo.empty())
20761  {
20762  set_cainfo(cainfo);
20763  }
20764 
20765  if (!capath.empty())
20766  {
20767  set_capath(capath);
20768  }
20769 
20770  if (!proxy_uri.empty())
20771  {
20772  set_proxy(proxy_uri);
20773  }
20774 
20775  if (is_http_proxy_tunneling)
20776  {
20777  set_http_proxy_tunnel(is_http_proxy_tunneling);
20778  }
20779 
20780  if (callback)
20781  {
20782  set_debug_callback(callback);
20783  }
20784 
20785  if (
20786 #if defined _WIN32 && (_MSC_VER == 1700 || _MSC_VER == 1800)
20787  static_cast<long>(ssl_opts) != static_cast<long>(ssl_options::none)
20788 #else
20789  ssl_opts != ssl_options::none
20790 #endif
20791  )
20792  {
20793  set_ssl_options(ssl_opts);
20794  }
20795 
20796  request_handler_.set_method(RequestHandler::method::POST);
20797  request_handler_.set_content_type("text/xml; charset=utf-8");
20798  request_handler_.set_credentials(creds);
20799  }
20800 
20804  {
20805  server_version_ = internal::enum_to_str(vers);
20806  }
20807 
20810  void set_time_zone(const time_zone time_zone) { time_zone_ = time_zone; }
20811 
20814  time_zone get_time_zone() { return time_zone_; }
20815 
20823  void set_timeout(std::chrono::seconds d)
20824  {
20825  request_handler_.set_timeout(d);
20826  }
20827 
20830  void set_proxy(const std::string& url)
20831  {
20832  request_handler_.set_option(CURLOPT_PROXY, url.c_str());
20833  }
20834 
20836  void set_http_proxy_tunnel(const bool value)
20837  {
20838  request_handler_.set_option(CURLOPT_HTTPPROXYTUNNEL, (value ? 1L : 0L));
20839  }
20840 
20841 #if LIBCURL_VERSION_NUM >= 0x073400
20842  void set_proxy_cainfo(const std::string& path)
20845  {
20846  request_handler_.set_option(CURLOPT_PROXY_CAINFO, path.c_str());
20847  }
20848 
20851  void set_proxy_capath(const std::string& path)
20852  {
20853  request_handler_.set_option(CURLOPT_PROXY_CAPATH, path.c_str());
20854  }
20855 #endif
20856 
20858  void set_cainfo(const std::string& path)
20859  {
20860  request_handler_.set_option(CURLOPT_CAINFO, path.c_str());
20861  }
20862 
20864  void set_capath(const std::string& path)
20865  {
20866  request_handler_.set_option(CURLOPT_CAPATH, path.c_str());
20867  }
20868 
20870  void set_ssl_options(const ssl_options value)
20871  {
20872  request_handler_.set_option(CURLOPT_SSL_OPTIONS, value);
20873  }
20874 
20876  void set_debug_callback(const debug_callback& callback)
20877  {
20878  debug_callback_ = callback;
20879  if (callback)
20880  {
20881  request_handler_.set_option(CURLOPT_VERBOSE, 1L);
20882  request_handler_.set_option(CURLOPT_DEBUGFUNCTION,
20883  curl_debug_callback);
20884  request_handler_.set_option(CURLOPT_DEBUGDATA, &debug_callback_);
20885  }
20886  else
20887  {
20888  request_handler_.set_option(CURLOPT_VERBOSE, 0L);
20889  request_handler_.set_option(CURLOPT_DEBUGFUNCTION, nullptr);
20890  request_handler_.set_option(CURLOPT_DEBUGDATA, nullptr);
20891  }
20892  }
20893 
20894 private:
20896  static int curl_debug_callback(EWS_MAYBE_UNUSED CURL* handle,
20897  curl_infotype type, char* data, size_t size,
20898  void* user_ptr)
20899  {
20900  std::stringstream output;
20901 
20902  switch (type)
20903  {
20904  case CURLINFO_TEXT:
20905  output << "== Info: ";
20906  output.write(data, size);
20907  break;
20908  case CURLINFO_HEADER_OUT:
20909  output << "=> Send header ";
20910  output.write(data, size);
20911  break;
20912  case CURLINFO_DATA_OUT:
20913  output << "=> Send data" << std::endl;
20914  break;
20915  case CURLINFO_SSL_DATA_OUT:
20916  output << "=> Send SSL data" << std::endl;
20917  break;
20918  case CURLINFO_HEADER_IN:
20919  output << "<= Recv header ";
20920  output.write(data, size);
20921  break;
20922  case CURLINFO_DATA_IN:
20923  output << "<= Recv data" << std::endl;
20924  break;
20925  case CURLINFO_SSL_DATA_IN:
20926  output << "<= Recv SSL data" << std::endl;
20927  break;
20928  default:
20929  output << "-- Unknown info type" << std::endl;
20930  break;
20931  }
20932 
20933  if (user_ptr)
20934  {
20935  (*reinterpret_cast<debug_callback*>(user_ptr))(output.str());
20936  }
20937 
20938  return 0;
20939  }
20940 
20941 public:
20945  {
20946  return internal::str_to_server_version(server_version_);
20947  }
20948 
20949  basic_service& impersonate()
20950  {
20951  impersonation_.clear();
20952  return *this;
20953  }
20954 
20955  basic_service& impersonate(const connecting_sid& sid)
20956  {
20957  impersonation_ = sid.to_xml();
20958  return *this;
20959  }
20960 
20962  std::vector<mailbox> get_room_lists()
20963  {
20964  std::string msg = "<m:GetRoomLists />";
20965  auto response = request(msg);
20966  const auto response_message =
20967  internal::get_room_lists_response_message::parse(
20968  std::move(response));
20969  if (!response_message.success())
20970  {
20971  throw exchange_error(response_message.result());
20972  }
20973  return response_message.items();
20974  }
20975 
20977  std::vector<mailbox> get_rooms(const mailbox& room_list)
20978  {
20979  std::stringstream sstr;
20980  sstr << "<m:GetRooms>"
20981  "<m:RoomList>"
20982  "<t:EmailAddress>"
20983  << room_list.value()
20984  << "</t:EmailAddress>"
20985  "</m:RoomList>"
20986  "</m:GetRooms>";
20987 
20988  auto response = request(sstr.str());
20989  const auto response_message =
20990  internal::get_rooms_response_message::parse(std::move(response));
20991  if (!response_message.success())
20992  {
20993  throw exchange_error(response_message.result());
20994  }
20995  return response_message.items();
20996  }
20997 
21001  {
21002  return sync_folder_hierarchy(folder_id, "");
21003  }
21004 
21006  sync_folder_hierarchy(const folder_id& folder_id,
21007  const std::string& sync_state)
21008  {
21009  return sync_folder_hierarchy_impl(folder_id, sync_state);
21010  }
21011 
21013  sync_folder_items_result sync_folder_items(const folder_id& folder_id,
21014  int max_changes_returned = 512)
21015  {
21016  return sync_folder_items(folder_id, "", max_changes_returned);
21017  }
21018 
21019  sync_folder_items_result sync_folder_items(const folder_id& folder_id,
21020  const std::string& sync_state,
21021  int max_changes_returned = 512)
21022  {
21023  std::vector<item_id> ignored_items;
21024  return sync_folder_items(folder_id, sync_state, ignored_items,
21025  max_changes_returned);
21026  }
21027 
21029  sync_folder_items(const folder_id& folder_id, const std::string& sync_state,
21030  const std::vector<item_id>& ignored_items,
21031  int max_changes_returned = 512)
21032  {
21033  return sync_folder_items_impl(folder_id, sync_state, ignored_items,
21034  max_changes_returned);
21035  }
21036 
21038  folder get_folder(const folder_id& id)
21039  {
21040  return get_folder_impl(id, base_shape::all_properties);
21041  }
21042 
21044  folder get_folder(const folder_id& id,
21045  const std::vector<property_path>& additional_properties)
21046  {
21047  return get_folder_impl(id, base_shape::all_properties,
21048  additional_properties);
21049  }
21050 
21052  std::vector<folder> get_folders(const std::vector<folder_id>& ids)
21053  {
21054  return get_folders_impl(ids, base_shape::all_properties);
21055  }
21056 
21058  std::vector<folder>
21059  get_folders(const std::vector<folder_id>& ids,
21060  const std::vector<property_path>& additional_properties)
21061  {
21062  return get_folders(ids, base_shape::all_properties,
21063  additional_properties);
21064  }
21065 
21067  task get_task(const item_id& id, const item_shape& shape = item_shape())
21068  {
21069  return get_item_impl<task>(id, shape);
21070  }
21071 
21073  std::vector<task> get_tasks(const std::vector<item_id>& ids,
21074  const item_shape& shape = item_shape())
21075  {
21076  return get_item_impl<task>(ids, shape);
21077  }
21078 
21081  const item_shape& shape = item_shape())
21082  {
21083  return get_item_impl<contact>(id, shape);
21084  }
21085 
21087  std::vector<contact> get_contacts(const std::vector<item_id>& ids,
21088  const item_shape& shape = item_shape())
21089  {
21090  return get_item_impl<contact>(ids, shape);
21091  }
21092 
21095  const item_shape& shape = item_shape())
21096  {
21097  return get_item_impl<calendar_item>(id, shape);
21098  }
21099 
21101  std::vector<calendar_item>
21102  get_calendar_items(const std::vector<item_id>& ids,
21103  const item_shape& shape = item_shape())
21104  {
21105  return get_item_impl<calendar_item>(ids, shape);
21106  }
21107 
21110  const item_shape& shape = item_shape())
21111  {
21112  const std::string request_string = "<m:GetItem>" + shape.to_xml() +
21113  "<m:ItemIds>" + id.to_xml() +
21114  "</m:ItemIds>"
21115  "</m:GetItem>";
21116 
21117  auto response = request(request_string);
21118  const auto response_message =
21119  internal::get_item_response_message<calendar_item>::parse(
21120  std::move(response));
21121  if (!response_message.success())
21122  {
21123  throw exchange_error(response_message.result());
21124  }
21125  check(!response_message.items().empty(), "Expected at least one item");
21126  return response_message.items().front();
21127  }
21128 
21130  std::vector<calendar_item>
21131  get_calendar_items(const std::vector<occurrence_item_id>& ids,
21132  const item_shape& shape = item_shape())
21133  {
21134  check(!ids.empty(), "Expected at least one item in given vector");
21135 
21136  std::stringstream sstr;
21137  sstr << "<m:GetItem>";
21138  sstr << shape.to_xml();
21139  sstr << "<m:ItemIds>";
21140  for (const auto& id : ids)
21141  {
21142  sstr << id.to_xml();
21143  }
21144  sstr << "</m:ItemIds>"
21145  "</m:GetItem>";
21146 
21147  auto response = request(sstr.str());
21148  const auto response_messages =
21149  internal::item_response_messages<calendar_item>::parse(
21150  std::move(response));
21151  if (!response_messages.success())
21152  {
21153  throw exchange_error(response_messages.first_error_or_warning());
21154  }
21155  return response_messages.items();
21156  }
21157 
21160  const item_shape& shape = item_shape())
21161  {
21162  return get_item_impl<message>(id, shape);
21163  }
21164 
21166  std::vector<message> get_messages(const std::vector<item_id>& ids,
21167  const item_shape& shape = item_shape())
21168  {
21169  return get_item_impl<message>(ids, shape);
21170  }
21171 
21173  void delete_folder(const folder_id& id,
21175  {
21176  const std::string request_string = "<m:DeleteFolder "
21177  "DeleteType=\"" +
21178  internal::enum_to_str(del_type) +
21179  "\">"
21180  "<m:FolderIds>" +
21181  id.to_xml() +
21182  "</m:FolderIds>"
21183  "</m:DeleteFolder>";
21184 
21185  auto response = request(request_string);
21186  const auto response_message =
21187  internal::delete_folder_response_message::parse(
21188  std::move(response));
21189  if (!response_message.success())
21190  {
21191  throw exchange_error(response_message.result());
21192  }
21193  }
21194 
21196  void delete_item(const item_id& id,
21198  affected_task_occurrences affected =
21200  send_meeting_cancellations cancellations =
21202  {
21203  using internal::delete_item_response_message;
21204 
21205  const std::string request_string =
21206  "<m:DeleteItem "
21207  "DeleteType=\"" +
21208  internal::enum_to_str(del_type) +
21209  "\" "
21210  "SendMeetingCancellations=\"" +
21211  internal::enum_to_str(cancellations) +
21212  "\" "
21213  "AffectedTaskOccurrences=\"" +
21214  internal::enum_to_str(affected) +
21215  "\">"
21216  "<m:ItemIds>" +
21217  id.to_xml() +
21218  "</m:ItemIds>"
21219  "</m:DeleteItem>";
21220 
21221  auto response = request(request_string);
21222  const auto response_message =
21223  delete_item_response_message::parse(std::move(response));
21224  if (!response_message.success())
21225  {
21226  throw exchange_error(response_message.result());
21227  }
21228  }
21229 
21231  void delete_task(task&& the_task,
21233  affected_task_occurrences affected =
21235  {
21236  delete_item(the_task.get_item_id(), del_type, affected);
21237  the_task = task();
21238  }
21239 
21241  void delete_contact(contact&& the_contact)
21242  {
21243  delete_item(the_contact.get_item_id());
21244  the_contact = contact();
21245  }
21246 
21248  void delete_calendar_item(calendar_item&& the_calendar_item,
21250  send_meeting_cancellations cancellations =
21252  {
21253  delete_item(the_calendar_item.get_item_id(), del_type,
21255  the_calendar_item = calendar_item();
21256  }
21257 
21259  void delete_message(message&& the_message)
21260  {
21261  delete_item(the_message.get_item_id());
21262  the_message = message();
21263  }
21264 
21265  // Following items can be created in Exchange:
21266  //
21267  // - Calendar items
21268  // - E-mail messages
21269  // - Meeting requests
21270  // - Tasks
21271  // - Contacts
21272  //
21273  // Only purpose of this overload-set is to prevent exploding template
21274  // code in errors messages in caller's code.
21275 
21282  folder_id create_folder(const folder& new_folder,
21283  const folder_id& parent_folder)
21284  {
21285  return create_folder_impl(new_folder, parent_folder);
21286  }
21287 
21294  std::vector<folder_id> create_folder(const std::vector<folder>& new_folders,
21295  const folder_id& parent_folder)
21296  {
21297  return create_folder_impl(new_folders, parent_folder);
21298  }
21299 
21303  item_id create_item(const task& the_task)
21304  {
21305  return create_item_impl(the_task, folder_id());
21306  }
21307 
21315  item_id create_item(const task& the_task, const folder_id& folder)
21316  {
21317  return create_item_impl(the_task, folder);
21318  }
21319 
21323  std::vector<item_id> create_item(const std::vector<task>& tasks)
21324  {
21325  return create_item_impl(tasks, folder_id());
21326  }
21327 
21335  std::vector<item_id> create_item(const std::vector<task>& tasks,
21336  const folder_id& folder)
21337  {
21338  return create_item_impl(tasks, folder);
21339  }
21340 
21345  item_id create_item(const contact& the_contact)
21346  {
21347  return create_item_impl(the_contact, folder_id());
21348  }
21349 
21357  item_id create_item(const contact& the_contact, const folder_id& folder)
21358  {
21359  return create_item_impl(the_contact, folder);
21360  }
21361 
21366  std::vector<item_id> create_item(const std::vector<contact>& contacts)
21367  {
21368  return create_item_impl(contacts, folder_id());
21369  }
21370 
21378  std::vector<item_id> create_item(const std::vector<contact>& contacts,
21379  const folder_id& folder)
21380  {
21381  return create_item_impl(contacts, folder);
21382  }
21383 
21391  item_id create_item(const calendar_item& the_calendar_item,
21392  send_meeting_invitations send_invitations =
21394  {
21395  return create_item_impl(the_calendar_item, send_invitations,
21396  folder_id());
21397  }
21398 
21407  item_id create_item(const calendar_item& the_calendar_item,
21408  send_meeting_invitations send_invitations,
21409  const folder_id& folder)
21410  {
21411  return create_item_impl(the_calendar_item, send_invitations, folder);
21412  }
21413 
21421  std::vector<item_id>
21422  create_item(const std::vector<calendar_item>& calendar_items,
21423  send_meeting_invitations send_invitations =
21425  {
21426  return create_item_impl(calendar_items, send_invitations, folder_id());
21427  }
21428 
21437  std::vector<item_id>
21438  create_item(const std::vector<calendar_item>& calendar_items,
21439  send_meeting_invitations send_invitations,
21440  const folder_id& folder)
21441  {
21442  return create_item_impl(calendar_items, send_invitations, folder);
21443  }
21444 
21460  item_id create_item(const message& the_message,
21461  message_disposition disposition)
21462  {
21463  return create_item_impl(the_message, disposition, folder_id());
21464  }
21465 
21476  item_id create_item(const message& the_message,
21477  message_disposition disposition,
21478  const folder_id& folder)
21479  {
21480  return create_item_impl(the_message, disposition, folder);
21481  }
21482 
21498  std::vector<item_id> create_item(const std::vector<message>& messages,
21499  message_disposition disposition)
21500  {
21501  return create_item_impl(messages, disposition, folder_id());
21502  }
21503 
21514  std::vector<item_id> create_item(const std::vector<message>& messages,
21515  message_disposition disposition,
21516  const folder_id& folder)
21517  {
21518  return create_item_impl(messages, disposition, folder);
21519  }
21520 
21524  void send_item(const item_id& id) { send_item(id, folder_id()); }
21525 
21529  void send_item(const std::vector<item_id>& ids)
21530  {
21531  send_item(ids, folder_id());
21532  }
21533 
21539  void send_item(const item_id& id, const folder_id& folder)
21540  {
21541  std::stringstream sstr;
21542  sstr << "<m:SendItem SaveItemToFolder=\"" << std::boolalpha
21543  << folder.valid() << "\">"
21544  << "<m:ItemIds>" << id.to_xml() << "</m:ItemIds>";
21545  if (folder.valid())
21546  {
21547  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
21548  << "</m:SavedItemFolderId>";
21549  }
21550  sstr << "</m:SendItem>";
21551 
21552  auto response = request(sstr.str());
21553 
21554  const auto response_message =
21555  internal::send_item_response_message::parse(std::move(response));
21556  if (!response_message.success())
21557  {
21558  throw exchange_error(response_message.result());
21559  }
21560  }
21561 
21567  void send_item(const std::vector<item_id>& ids, const folder_id& folder)
21568  {
21569  std::stringstream sstr;
21570  sstr << "<m:SendItem SaveItemToFolder=\"" << std::boolalpha
21571  << folder.valid() << "\">";
21572  for (const auto& id : ids)
21573  {
21574  sstr << "<m:ItemIds>" << id.to_xml() << "</m:ItemIds>";
21575  }
21576  if (folder.valid())
21577  {
21578  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
21579  << "</m:SavedItemFolderId>";
21580  }
21581  sstr << "</m:SendItem>";
21582 
21583  auto response = request(sstr.str());
21584 
21585  const auto response_message =
21586  internal::send_item_response_message::parse(std::move(response));
21587  if (!response_message.success())
21588  {
21589  throw exchange_error(response_message.result());
21590  }
21591  }
21592 
21602  std::vector<folder_id> find_folder(const folder_id& parent_folder_id)
21603  {
21604  const std::string request_string =
21605  "<m:FindFolder Traversal=\"Shallow\">"
21606  "<m:FolderShape>"
21607  "<t:BaseShape>IdOnly</t:BaseShape>"
21608  "</m:FolderShape>"
21609  "<m:ParentFolderIds>" +
21610  parent_folder_id.to_xml() +
21611  "</m:ParentFolderIds>"
21612  "</m:FindFolder>";
21613 
21614  auto response = request(request_string);
21615  const auto response_message =
21616  internal::find_folder_response_message::parse(std::move(response));
21617  if (!response_message.success())
21618  {
21619  throw exchange_error(response_message.result());
21620  }
21621  return response_message.items();
21622  }
21623 
21624  std::vector<item_id> find_item(const folder_id& parent_folder_id,
21625  const paging_view& view)
21626  {
21627  const std::string request_string =
21628  "<m:FindItem Traversal=\"Shallow\">"
21629  "<m:ItemShape>"
21630  "<t:BaseShape>IdOnly</t:BaseShape>"
21631  "</m:ItemShape>" +
21632  view.to_xml() + "<m:ParentFolderIds>" + parent_folder_id.to_xml() +
21633  "</m:ParentFolderIds>"
21634  "</m:FindItem>";
21635 
21636  auto response = request(request_string);
21637  const auto response_message =
21638  internal::find_item_response_message::parse(std::move(response));
21639  if (!response_message.success())
21640  {
21641  throw exchange_error(response_message.result());
21642  }
21643  return response_message.items();
21644  }
21645 
21646  std::vector<item_id> find_item(const folder_id& parent_folder_id)
21647  {
21648  // TODO: add item_shape to function parameters
21649  const std::string request_string = "<m:FindItem Traversal=\"Shallow\">"
21650  "<m:ItemShape>"
21651  "<t:BaseShape>IdOnly</t:BaseShape>"
21652  "</m:ItemShape>"
21653  "<m:ParentFolderIds>" +
21654  parent_folder_id.to_xml() +
21655  "</m:ParentFolderIds>"
21656  "</m:FindItem>";
21657 
21658  auto response = request(request_string);
21659  const auto response_message =
21660  internal::find_item_response_message::parse(std::move(response));
21661  if (!response_message.success())
21662  {
21663  throw exchange_error(response_message.result());
21664  }
21665  return response_message.items();
21666  }
21667 
21673  std::vector<calendar_item> find_item(const calendar_view& view,
21674  const folder_id& parent_folder_id,
21675  const item_shape& shape = item_shape())
21676  {
21677  const std::string request_string =
21678  "<m:FindItem Traversal=\"Shallow\">" + shape.to_xml() +
21679  view.to_xml() + "<m:ParentFolderIds>" + parent_folder_id.to_xml() +
21680  "</m:ParentFolderIds>"
21681  "</m:FindItem>";
21682 
21683  auto response = request(request_string);
21684  const auto response_message =
21685  internal::find_calendar_item_response_message::parse(
21686  std::move(response));
21687  if (!response_message.success())
21688  {
21689  throw exchange_error(response_message.result());
21690  }
21691  return response_message.items();
21692  }
21693 
21705  std::vector<item_id> find_item(const folder_id& parent_folder_id,
21706  search_expression restriction)
21707  {
21708  // TODO: add item_shape to function parameters
21709  const std::string request_string = "<m:FindItem Traversal=\"Shallow\">"
21710  "<m:ItemShape>"
21711  "<t:BaseShape>IdOnly</t:BaseShape>"
21712  "</m:ItemShape>"
21713  "<m:Restriction>" +
21714  restriction.to_xml() +
21715  "</m:Restriction>"
21716  "<m:ParentFolderIds>" +
21717  parent_folder_id.to_xml() +
21718  "</m:ParentFolderIds>"
21719  "</m:FindItem>";
21720 
21721  auto response = request(request_string);
21722  const auto response_message =
21723  internal::find_item_response_message::parse(std::move(response));
21724  if (!response_message.success())
21725  {
21726  throw exchange_error(response_message.result());
21727  }
21728  return response_message.items();
21729  }
21730 
21746  item_id id, update change,
21748  send_meeting_invitations_or_cancellations invitations_or_cancellations =
21750  {
21751  return update_item_impl(std::move(id), std::move(change), resolution,
21752  invitations_or_cancellations, folder_id());
21753  }
21754 
21774  send_meeting_invitations_or_cancellations invitations_or_cancellations,
21775  const folder_id& folder)
21776  {
21777  return update_item_impl(std::move(id), std::move(change), resolution,
21778  invitations_or_cancellations, folder);
21779  }
21780 
21796  item_id id, const std::vector<update>& changes,
21798  send_meeting_invitations_or_cancellations invitations_or_cancellations =
21800  {
21801  return update_item_impl(std::move(id), changes, resolution,
21802  invitations_or_cancellations, folder_id());
21803  }
21804 
21823  item_id id, const std::vector<update>& changes,
21825  send_meeting_invitations_or_cancellations invitations_or_cancellations,
21826  const folder_id& folder)
21827  {
21828  return update_item_impl(std::move(id), changes, resolution,
21829  invitations_or_cancellations, folder);
21830  }
21831 
21841  folder_id update_folder(folder_id folder_id, update change)
21842  {
21843  return update_folder_impl(std::move(folder_id), std::move(change));
21844  }
21845 
21855  folder_id update_folder(folder_id folder_id,
21856  const std::vector<update>& changes)
21857  {
21858  return update_folder_impl(std::move(folder_id), changes);
21859  }
21860 
21867  item_id move_item(item_id item, const folder_id& folder)
21868  {
21869  return move_item_impl(std::move(item), folder);
21870  }
21871 
21878  std::vector<item_id> move_item(const std::vector<item_id>& items,
21879  const folder_id& folder)
21880  {
21881  return move_item_impl(items, folder);
21882  }
21883 
21890  folder_id move_folder(folder_id folder, const folder_id& target)
21891  {
21892  return move_folder_impl(std::move(folder), target);
21893  }
21894 
21901  std::vector<folder_id> move_folder(const std::vector<folder_id>& folders,
21902  const folder_id& target)
21903  {
21904  return move_folder_impl(folders, target);
21905  }
21906 
21908  std::vector<delegate_user>
21910  const std::vector<delegate_user>& delegates)
21911  {
21912  std::stringstream sstr;
21913  sstr << "<m:AddDelegate>";
21914  sstr << mailbox.to_xml("m");
21915  sstr << "<m:DelegateUsers>";
21916  for (const auto& delegate : delegates)
21917  {
21918  sstr << delegate.to_xml();
21919  }
21920  sstr << "</m:DelegateUsers>";
21921  sstr << "</m:AddDelegate>";
21922  auto response = request(sstr.str());
21923 
21924  const auto response_message =
21925  internal::add_delegate_response_message::parse(std::move(response));
21926  if (!response_message.success())
21927  {
21928  throw exchange_error(response_message.result());
21929  }
21930  return response_message.get_delegates();
21931  }
21932 
21935  std::vector<delegate_user> get_delegate(const mailbox& mailbox,
21936  bool include_permissions = false)
21937  {
21938  std::stringstream sstr;
21939  sstr << "<m:GetDelegate IncludePermissions=\""
21940  << (include_permissions ? "true" : "false") << "\">";
21941  sstr << mailbox.to_xml("m");
21942  sstr << "</m:GetDelegate>";
21943  auto response = request(sstr.str());
21944 
21945  const auto response_message =
21946  internal::get_delegate_response_message::parse(std::move(response));
21947  if (!response_message.success())
21948  {
21949  throw exchange_error(response_message.result());
21950  }
21951  return response_message.get_delegates();
21952  }
21953 
21954  void remove_delegate(const mailbox& mailbox,
21955  const std::vector<user_id>& delegates)
21956  {
21957  std::stringstream sstr;
21958  sstr << "<m:RemoveDelegate>";
21959  sstr << mailbox.to_xml("m");
21960  sstr << "<m:UserIds>";
21961  for (const auto& user : delegates)
21962  {
21963  sstr << user.to_xml();
21964  }
21965  sstr << "</m:UserIds>";
21966  sstr << "</m:RemoveDelegate>";
21967  auto response = request(sstr.str());
21968 
21969  const auto response_message =
21970  internal::remove_delegate_response_message::parse(
21971  std::move(response));
21972  if (!response_message.success())
21973  {
21974  throw exchange_error(response_message.result());
21975  }
21976  }
21977 
21985  const attachment& a)
21986  {
21987  auto response = request("<m:CreateAttachment>"
21988  "<m:ParentItemId Id=\"" +
21989  parent_item.id() + "\" ChangeKey=\"" +
21990  parent_item.change_key() +
21991  "\"/>"
21992  "<m:Attachments>" +
21993  a.to_xml() +
21994  "</m:Attachments>"
21995  "</m:CreateAttachment>");
21996 
21997  const auto response_message =
21998  internal::create_attachment_response_message::parse(
21999  std::move(response));
22000  if (!response_message.success())
22001  {
22002  throw exchange_error(response_message.result());
22003  }
22004  check(!response_message.attachment_ids().empty(),
22005  "Expected at least one attachment");
22006  return response_message.attachment_ids().front();
22007  }
22008 
22009 #if 0
22010  // TODO
22011 
22018  std::vector<attachment_id>
22019  create_attachments(const item& parent_item,
22020  const std::vector<attachment>& attachments)
22021  {
22022  (void)parent_item;
22023  (void)attachments;
22024  return std::vector<attachment_id>();
22025  }
22026 #endif // 0
22027 
22030  bool include_mime_content = false)
22031  {
22032  std::stringstream sstr;
22033  sstr << "<m:GetAttachment>"
22034  "<m:AttachmentShape>"
22035  "<t:IncludeMimeContent>"
22036  << (include_mime_content ? "true" : "false")
22037  << "</t:IncludeMimeContent>"
22038  "</m:AttachmentShape>"
22039  "<m:AttachmentIds>"
22040  << id.to_xml()
22041  << "</m:AttachmentIds>"
22042  "</m:GetAttachment>";
22043  auto response = request(sstr.str());
22044 
22045  const auto response_message =
22046  internal::get_attachment_response_message::parse(
22047  std::move(response));
22048  if (!response_message.success())
22049  {
22050  throw exchange_error(response_message.result());
22051  }
22052  check(!response_message.attachments().empty(),
22053  "Expected at least one attachment to be returned");
22054  return response_message.attachments().front();
22055  }
22056 
22063  {
22064  auto response = request("<m:DeleteAttachment>"
22065  "<m:AttachmentIds>" +
22066  id.to_xml() +
22067  "</m:AttachmentIds>"
22068  "</m:DeleteAttachment>");
22069  const auto response_message =
22070  internal::delete_attachment_response_message::parse(
22071  std::move(response));
22072  if (!response_message.success())
22073  {
22074  throw exchange_error(response_message.result());
22075  }
22076  return response_message.get_root_item_id();
22077  }
22078 
22089  resolution_set resolve_names(const std::string& unresolved_entry,
22090  search_scope scope)
22091  {
22092  std::vector<folder_id> v;
22093  return resolve_names_impl(unresolved_entry, v, scope);
22094  }
22095 
22108  resolve_names(const std::string& unresolved_entry, search_scope scope,
22109  const std::vector<folder_id>& parent_folder_ids)
22110  {
22111  return resolve_names_impl(unresolved_entry, parent_folder_ids, scope);
22112  }
22113 
22114 #ifdef EWS_HAS_VARIANT
22115  subscription_information
22124  subscribe(const std::vector<distinguished_folder_id>& ids,
22125  const std::vector<event_type>& types, int timeout)
22126  {
22127  return subscribe_impl(ids, types, timeout);
22128  }
22129 
22135  void unsubscribe(const std::string& subscription_id)
22136  {
22137  return unsubscribe_impl(subscription_id);
22138  }
22139 
22147  notification get_events(const std::string& subscription_id,
22148  const std::string& watermark)
22149  {
22150  return get_events_impl(subscription_id, watermark);
22151  }
22152 #endif
22153 private:
22154  RequestHandler request_handler_;
22155  debug_callback debug_callback_;
22156  std::string server_version_;
22157  std::string impersonation_;
22158  time_zone time_zone_;
22159 
22160  // Helper for doing requests. Adds the right headers, credentials, and
22161  // checks the response for faults.
22162  internal::http_response request(const std::string& request_string)
22163  {
22164  using internal::get_element_by_qname;
22165  using rapidxml::internal::compare;
22166 
22167  auto soap_headers = std::vector<std::string>();
22168  soap_headers.emplace_back("<t:RequestServerVersion Version=\"" +
22169  server_version_ + "\"/>");
22170  if (!impersonation_.empty())
22171  {
22172  soap_headers.emplace_back("<t:ExchangeImpersonation>" +
22173  impersonation_ +
22174  "</t:ExchangeImpersonation>");
22175  }
22176  if (time_zone_ != time_zone::none)
22177  {
22178  soap_headers.emplace_back("<t:TimeZoneContext>"
22179  "<t:TimeZoneDefinition Id=\"" +
22180  internal::enum_to_str(time_zone_) +
22181  "\"/></t:TimeZoneContext>");
22182  }
22183 
22184  auto response = internal::make_raw_soap_request(
22185  request_handler_, request_string, soap_headers);
22186 
22187  if (response.ok())
22188  {
22189  return response;
22190  }
22191  else if (response.is_soap_fault())
22192  {
22193  std::unique_ptr<rapidxml::xml_document<char>> doc;
22194 
22195  try
22196  {
22197  doc = parse_response(std::move(response));
22198  }
22199  catch (xml_parse_error&)
22200  {
22201  throw soap_fault("The request failed for unknown reason "
22202  "(could not parse response)");
22203  }
22204 
22205  auto elem = get_element_by_qname(
22206  *doc, "ResponseCode", internal::uri<>::microsoft::errors());
22207  if (!elem)
22208  {
22209  throw soap_fault("The request failed for unknown reason "
22210  "(unexpected XML in response)");
22211  }
22212 
22213  if (compare(elem->value(), elem->value_size(),
22214  "ErrorSchemaValidation", 21))
22215  {
22216  // Get some more helpful details
22217  elem = get_element_by_qname(
22218  *doc, "LineNumber", internal::uri<>::microsoft::types());
22219  check(elem, "Expected <LineNumber> element in response");
22220  const auto line_number =
22221  std::stoul(std::string(elem->value(), elem->value_size()));
22222 
22223  elem = get_element_by_qname(
22224  *doc, "LinePosition", internal::uri<>::microsoft::types());
22225  check(elem, "Expected <LinePosition> element in response");
22226  const auto line_position =
22227  std::stoul(std::string(elem->value(), elem->value_size()));
22228 
22229  elem = get_element_by_qname(
22230  *doc, "Violation", internal::uri<>::microsoft::types());
22231  check(elem, "Expected <Violation> element in response");
22233  line_number, line_position,
22234  std::string(elem->value(), elem->value_size()));
22235  }
22236  else
22237  {
22238  elem = get_element_by_qname(*doc, "faultstring", "");
22239  check(elem, "Expected <faultstring> element in response");
22240  throw soap_fault(elem->value());
22241  }
22242  }
22243  else
22244  {
22245  throw http_error(response.code());
22246  }
22247  }
22248 
22250  sync_folder_hierarchy_impl(const folder_id& folder_id,
22251  const std::string& sync_state)
22252  {
22253  std::stringstream sstr;
22254  sstr << "<m:SyncFolderHierarchy>"
22255  "<m:FolderShape>"
22256  "<t:BaseShape>"
22257  << internal::enum_to_str(base_shape::default_shape)
22258  << "</t:BaseShape>"
22259  "</m:FolderShape>"
22260  "<m:SyncFolderId>"
22261  << folder_id.to_xml() << "</m:SyncFolderId>";
22262  if (!sync_state.empty())
22263  {
22264  sstr << "<m:SyncState>" << sync_state << "</m:SyncState>";
22265  }
22266  sstr << "</m:SyncFolderHierarchy>";
22267 
22268  auto response = request(sstr.str());
22269  const auto response_message =
22270  sync_folder_hierarchy_result::parse(std::move(response));
22271  check(!response_message.get_sync_state().empty(),
22272  "Expected at least a sync state");
22273  return response_message;
22274  }
22275 
22276  sync_folder_items_result sync_folder_items_impl(
22277  const folder_id& folder_id, const std::string& sync_state,
22278  std::vector<item_id> ignored_items, int max_changes_returned = 512)
22279  {
22280  std::stringstream sstr;
22281  sstr << "<m:SyncFolderItems>"
22282  "<m:ItemShape>"
22283  "<t:BaseShape>"
22284  << internal::enum_to_str(base_shape::id_only)
22285  << "</t:BaseShape>"
22286  "</m:ItemShape>"
22287  "<m:SyncFolderId>"
22288  << folder_id.to_xml() << "</m:SyncFolderId>";
22289  if (!sync_state.empty())
22290  {
22291  sstr << "<m:SyncState>" << sync_state << "</m:SyncState>";
22292  }
22293  if (!ignored_items.empty())
22294  {
22295  sstr << "<m:Ignore>";
22296  for (const auto& i : ignored_items)
22297  {
22298  sstr << i.to_xml();
22299  }
22300  sstr << "</m:Ignore>";
22301  }
22302  sstr << "<m:MaxChangesReturned>" << max_changes_returned
22303  << "</m:MaxChangesReturned>"
22304  "</m:SyncFolderItems>";
22305 
22306  auto response = request(sstr.str());
22307  const auto response_message =
22308  sync_folder_items_result::parse(std::move(response));
22309  check(!response_message.get_sync_state().empty(),
22310  "Expected at least a sync state");
22311  return response_message;
22312  }
22313 
22314  folder get_folder_impl(const folder_id& id, base_shape shape)
22315  {
22316  const std::string request_string = "<m:GetFolder>"
22317  "<m:FolderShape>"
22318  "<t:BaseShape>" +
22319  internal::enum_to_str(shape) +
22320  "</t:BaseShape>"
22321  "</m:FolderShape>"
22322  "<m:FolderIds>" +
22323  id.to_xml() +
22324  "</m:FolderIds>"
22325  "</m:GetFolder>";
22326 
22327  auto response = request(request_string);
22328  const auto response_message =
22329  internal::get_folder_response_message::parse(std::move(response));
22330  if (!response_message.success())
22331  {
22332  throw exchange_error(response_message.result());
22333  }
22334  check(!response_message.items().empty(), "Expected at least one item");
22335  return response_message.items().front();
22336  }
22337 
22338  folder
22339  get_folder_impl(const folder_id& id, base_shape shape,
22340  const std::vector<property_path>& additional_properties)
22341  {
22342  check(!additional_properties.empty(),
22343  "Expected at least one element in additional_properties");
22344 
22345  std::stringstream sstr;
22346  sstr << "<m:GetFolder>"
22347  "<m:FolderShape>"
22348  "<t:BaseShape>"
22349  << internal::enum_to_str(shape)
22350  << "</t:BaseShape>"
22351  "<t:AdditionalProperties>";
22352  for (const auto& prop : additional_properties)
22353  {
22354  sstr << prop.to_xml();
22355  }
22356  sstr << "</t:AdditionalProperties>"
22357  "</m:FolderShape>"
22358  "<m:FolderIds>"
22359  << id.to_xml()
22360  << "</m:FolderIds>"
22361  "</m:GetFolder>";
22362 
22363  auto response = request(sstr.str());
22364  const auto response_message =
22365  internal::folder_response_message::parse(std::move(response));
22366  if (!response_message.success())
22367  {
22368  throw exchange_error(response_message.first_error_or_warning());
22369  }
22370  check(!response_message.items().empty(), "Expected at least one item");
22371  return response_message.items().front();
22372  }
22373 
22374  std::vector<folder> get_folders_impl(const std::vector<folder_id>& ids,
22375  base_shape shape)
22376  {
22377  check(!ids.empty(), "Expected at least one element in given vector");
22378 
22379  std::stringstream sstr;
22380  sstr << "<m:GetFolder>"
22381  "<m:FolderShape>"
22382  "<t:BaseShape>"
22383  << internal::enum_to_str(shape)
22384  << "</t:BaseShape>"
22385  "</m:FolderShape>"
22386  "<m:FolderIds>";
22387  for (const auto& id : ids)
22388  {
22389  sstr << id.to_xml();
22390  }
22391  sstr << "</m:FolderIds>"
22392  "</m:GetFolder>";
22393 
22394  auto response = request(sstr.str());
22395  const auto response_messages =
22396  internal::folder_response_message::parse(std::move(response));
22397  if (!response_messages.success())
22398  {
22399  throw exchange_error(response_messages.first_error_or_warning());
22400  }
22401  return response_messages.items();
22402  }
22403 
22404  std::vector<folder>
22405  get_folders_impl(const std::vector<folder_id>& ids, base_shape shape,
22406  const std::vector<property_path>& additional_properties)
22407  {
22408  check(!ids.empty(), "Expected at least one element in given vector");
22409  check(!additional_properties.empty(),
22410  "Expected at least one element in additional_properties");
22411 
22412  std::stringstream sstr;
22413  sstr << "<m:GetFolder>"
22414  "<m:FolderShape>"
22415  "<t:BaseShape>"
22416  << internal::enum_to_str(shape)
22417  << "</t:BaseShape>"
22418  "<t:AdditionalProperties>";
22419  for (const auto& prop : additional_properties)
22420  {
22421  sstr << prop.to_xml();
22422  }
22423  sstr << "</t:AdditionalProperties>"
22424  "</m:FolderShape>"
22425  "<m:FolderIds>";
22426  for (const auto& id : ids)
22427  {
22428  sstr << id.to_xml();
22429  }
22430  sstr << "</m:FolderIds>"
22431  "</m:GetFolder>";
22432 
22433  auto response = request(sstr.str());
22434  const auto response_messages =
22435  internal::folder_response_message::parse(std::move(response));
22436  if (!response_messages.success())
22437  {
22438  throw exchange_error(response_messages.first_error_or_warning());
22439  }
22440  return response_messages.items();
22441  }
22442 
22443  // Gets an item from the server
22444  template <typename ItemType>
22445  ItemType get_item_impl(const item_id& id, const item_shape& shape)
22446  {
22447  const std::string request_string = "<m:GetItem>" + shape.to_xml() +
22448  "<m:ItemIds>" + id.to_xml() +
22449  "</m:ItemIds>"
22450  "</m:GetItem>";
22451 
22452  auto response = request(request_string);
22453  const auto response_message =
22454  internal::get_item_response_message<ItemType>::parse(
22455  std::move(response));
22456  if (!response_message.success())
22457  {
22458  throw exchange_error(response_message.result());
22459  }
22460  check(!response_message.items().empty(), "Expected at least one item");
22461  return response_message.items().front();
22462  }
22463 
22464  // Gets a bunch of items from the server all at once
22465  template <typename ItemType>
22466  std::vector<ItemType> get_item_impl(const std::vector<item_id>& ids,
22467  const item_shape& shape)
22468  {
22469  check(!ids.empty(), "Expected at least one id in given vector");
22470 
22471  std::stringstream sstr;
22472  sstr << "<m:GetItem>";
22473  sstr << shape.to_xml();
22474  sstr << "<m:ItemIds>";
22475  for (const auto& id : ids)
22476  {
22477  sstr << id.to_xml();
22478  }
22479  sstr << "</m:ItemIds>"
22480  "</m:GetItem>";
22481 
22482  auto response = request(sstr.str());
22483  const auto response_messages =
22484  internal::item_response_messages<ItemType>::parse(
22485  std::move(response));
22486  if (!response_messages.success())
22487  {
22488  throw exchange_error(response_messages.first_error_or_warning());
22489  }
22490  return response_messages.items();
22491  }
22492 
22493  // Creates an item on the server and returns it's item_id.
22494  template <typename ItemType>
22495  item_id create_item_impl(const ItemType& the_item, const folder_id& folder)
22496  {
22497  std::stringstream sstr;
22498  sstr << "<m:CreateItem>";
22499 
22500  if (folder.valid())
22501  {
22502  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22503  << "</m:SavedItemFolderId>";
22504  }
22505 
22506  sstr << "<m:Items>";
22507  sstr << "<t:" << the_item.item_tag_name() << ">";
22508  sstr << the_item.xml().to_string();
22509  sstr << "</t:" << the_item.item_tag_name() << ">";
22510  sstr << "</m:Items>"
22511  "</m:CreateItem>";
22512 
22513  auto response = request(sstr.str());
22514  const auto response_message =
22515  internal::create_item_response_message::parse(std::move(response));
22516  if (!response_message.success())
22517  {
22518  throw exchange_error(response_message.result());
22519  }
22520  check(!response_message.items().empty(), "Expected at least one item");
22521  return response_message.items().front();
22522  }
22523 
22524  // Creates multiple items on the server and returns the item_ids.
22525  template <typename ItemType>
22526  std::vector<item_id> create_item_impl(const std::vector<ItemType>& items,
22527  const folder_id& folder)
22528  {
22529  std::stringstream sstr;
22530  sstr << "<m:CreateItem>";
22531 
22532  if (folder.valid())
22533  {
22534  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22535  << "</m:SavedItemFolderId>";
22536  }
22537 
22538  sstr << "<m:Items>";
22539  for (const auto& item : items)
22540  {
22541  sstr << "<t:" << item.item_tag_name() << ">";
22542  sstr << item.xml().to_string();
22543  sstr << "</t:" << item.item_tag_name() << ">";
22544  }
22545  sstr << "</m:Items>"
22546  "</m:CreateItem>";
22547 
22548  auto response = request(sstr.str());
22549  const auto response_messages =
22550  internal::item_response_messages<ItemType>::parse(
22551  std::move(response));
22552  if (!response_messages.success())
22553  {
22554  throw exchange_error(response_messages.first_error_or_warning());
22555  }
22556  check(!response_messages.items().empty(), "Expected at least one item");
22557 
22558  const std::vector<ItemType> res_items = response_messages.items();
22559  std::vector<item_id> res;
22560  res.reserve(res_items.size());
22561  std::transform(begin(res_items), end(res_items),
22562  std::back_inserter(res),
22563  [](const ItemType& elem) { return elem.get_item_id(); });
22564 
22565  return res;
22566  }
22567 
22568  item_id create_item_impl(const calendar_item& the_calendar_item,
22569  send_meeting_invitations send_invitations,
22570  const folder_id& folder)
22571  {
22572  using internal::create_item_response_message;
22573 
22574  std::stringstream sstr;
22575  sstr << "<m:CreateItem SendMeetingInvitations=\""
22576  << internal::enum_to_str(send_invitations) << "\">";
22577 
22578  if (folder.valid())
22579  {
22580  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22581  << "</m:SavedItemFolderId>";
22582  }
22583 
22584  sstr << "<m:Items>"
22585  "<t:CalendarItem>";
22586  sstr << the_calendar_item.xml().to_string();
22587  sstr << "</t:CalendarItem>"
22588  "</m:Items>"
22589  "</m:CreateItem>";
22590 
22591  auto response = request(sstr.str());
22592 
22593  const auto response_message =
22594  create_item_response_message::parse(std::move(response));
22595  if (!response_message.success())
22596  {
22597  throw exchange_error(response_message.result());
22598  }
22599  check(!response_message.items().empty(), "Expected a message item");
22600  return response_message.items().front();
22601  }
22602 
22603  std::vector<item_id>
22604  create_item_impl(const std::vector<calendar_item>& items,
22605  send_meeting_invitations send_invitations,
22606  const folder_id& folder)
22607  {
22608  std::stringstream sstr;
22609  sstr << "<m:CreateItem SendMeetingInvitations=\""
22610  << internal::enum_to_str(send_invitations) << "\">";
22611 
22612  if (folder.valid())
22613  {
22614  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22615  << "</m:SavedItemFolderId>";
22616  }
22617 
22618  sstr << "<m:Items>";
22619  for (const auto& item : items)
22620  {
22621  sstr << "<t:CalendarItem>";
22622  sstr << item.xml().to_string();
22623  sstr << "</t:CalendarItem>";
22624  }
22625  sstr << "</m:Items>"
22626  "</m:CreateItem>";
22627 
22628  auto response = request(sstr.str());
22629  const auto response_messages =
22630  internal::item_response_messages<calendar_item>::parse(
22631  std::move(response));
22632  if (!response_messages.success())
22633  {
22634  throw exchange_error(response_messages.first_error_or_warning());
22635  }
22636  check(!response_messages.items().empty(), "Expected at least one item");
22637 
22638  const std::vector<calendar_item> res_items = response_messages.items();
22639  std::vector<item_id> res;
22640  res.reserve(res_items.size());
22641  std::transform(
22642  begin(res_items), end(res_items), std::back_inserter(res),
22643  [](const calendar_item& elem) { return elem.get_item_id(); });
22644 
22645  return res;
22646  }
22647 
22648  folder_id create_folder_impl(const folder& new_folder,
22649  const folder_id& parent_folder)
22650  {
22651  check(parent_folder.valid(), "Given parent_folder is not valid");
22652 
22653  std::stringstream sstr;
22654  sstr << "<m:CreateFolder >"
22655  "<m:ParentFolderId>"
22656  << parent_folder.to_xml()
22657  << "</m:ParentFolderId>"
22658  "<m:Folders>"
22659  "<t:Folder>"
22660  << new_folder.xml().to_string()
22661  << "</t:Folder>"
22662  "</m:Folders>"
22663  "</m:CreateFolder>";
22664 
22665  auto response = request(sstr.str());
22666  const auto response_message =
22667  internal::create_folder_response_message::parse(
22668  std::move(response));
22669  if (!response_message.success())
22670  {
22671  throw exchange_error(response_message.result());
22672  }
22673  check(!response_message.items().empty(), "Expected at least one item");
22674  return response_message.items().front();
22675  }
22676 
22677  std::vector<folder_id>
22678  create_folder_impl(const std::vector<folder>& new_folders,
22679  const folder_id& parent_folder)
22680  {
22681  check(parent_folder.valid(), "Given parent_folder is not valid");
22682 
22683  std::stringstream sstr;
22684  sstr << "<m:CreateFolder >"
22685  "<m:ParentFolderId>"
22686  << parent_folder.to_xml()
22687  << "</m:ParentFolderId>"
22688  "<m:Folders>";
22689  for (const auto& folder : new_folders)
22690  {
22691  sstr << "<t:Folder>" << folder.xml().to_string() << "</t:Folder>";
22692  }
22693  sstr << "</m:Folders>"
22694  "</m:CreateFolder>";
22695 
22696  auto response = request(sstr.str());
22697  const auto response_messages =
22698  internal::folder_response_message::parse(std::move(response));
22699  if (!response_messages.success())
22700  {
22701  throw exchange_error(response_messages.first_error_or_warning());
22702  }
22703  check(!response_messages.items().empty(), "Expected at least one item");
22704 
22705  const std::vector<folder> items = response_messages.items();
22706  std::vector<folder_id> res;
22707  res.reserve(items.size());
22708  std::transform(begin(items), end(items), std::back_inserter(res),
22709  [](const folder& elem) { return elem.get_folder_id(); });
22710 
22711  return res;
22712  }
22713 
22714  item_id create_item_impl(const message& the_message,
22715  message_disposition disposition,
22716  const folder_id& folder)
22717  {
22718  std::stringstream sstr;
22719  sstr << "<m:CreateItem MessageDisposition=\""
22720  << internal::enum_to_str(disposition) << "\">";
22721 
22722  if (folder.valid())
22723  {
22724  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22725  << "</m:SavedItemFolderId>";
22726  }
22727 
22728  sstr << "<m:Items>"
22729  << "<t:Message>";
22730  sstr << the_message.xml().to_string();
22731  sstr << "</t:Message>"
22732  "</m:Items>"
22733  "</m:CreateItem>";
22734 
22735  auto response = request(sstr.str());
22736 
22737  const auto response_message =
22738  internal::create_item_response_message::parse(std::move(response));
22739  if (!response_message.success())
22740  {
22741  throw exchange_error(response_message.result());
22742  }
22743 
22744  if (disposition == message_disposition::save_only)
22745  {
22746  check(!response_message.items().empty(), "Expected a message item");
22747  return response_message.items().front();
22748  }
22749 
22750  return item_id();
22751  }
22752 
22753  std::vector<item_id> create_item_impl(const std::vector<message>& messages,
22754  ews::message_disposition disposition,
22755  const folder_id& folder)
22756  {
22757  std::stringstream sstr;
22758  sstr << "<m:CreateItem MessageDisposition=\""
22759  << internal::enum_to_str(disposition) << "\">";
22760 
22761  if (folder.valid())
22762  {
22763  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22764  << "</m:SavedItemFolderId>";
22765  }
22766 
22767  sstr << "<m:Items>";
22768  for (const auto& item : messages)
22769  {
22770  sstr << "<t:Message>";
22771  sstr << item.xml().to_string();
22772  sstr << "</t:Message>";
22773  }
22774  sstr << "</m:Items>"
22775  "</m:CreateItem>";
22776 
22777  auto response = request(sstr.str());
22778  const auto response_messages =
22779  internal::item_response_messages<message>::parse(
22780  std::move(response));
22781  if (!response_messages.success())
22782  {
22783  throw exchange_error(response_messages.first_error_or_warning());
22784  }
22785  if(disposition == message_disposition::save_only)
22786  {
22787  check(!response_messages.items().empty(), "Expected at least one item");
22788  }
22789 
22790  const std::vector<message> items = response_messages.items();
22791  std::vector<item_id> res;
22792  res.reserve(items.size());
22793  std::transform(begin(items), end(items), std::back_inserter(res),
22794  [](const message& elem) { return elem.get_item_id(); });
22795 
22796  return res;
22797  }
22798 
22799  item_id update_item_impl(
22801  send_meeting_invitations_or_cancellations invitations_or_cancellations,
22802  const folder_id& folder)
22803  {
22804  std::stringstream sstr;
22805  sstr << "<m:UpdateItem "
22806  "MessageDisposition=\"SaveOnly\" "
22807  "ConflictResolution=\""
22808  << internal::enum_to_str(resolution)
22809  << "\" SendMeetingInvitationsOrCancellations=\""
22810  << internal::enum_to_str(invitations_or_cancellations) + "\">";
22811 
22812  if (folder.valid())
22813  {
22814  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22815  << "</m:SavedItemFolderId>";
22816  }
22817 
22818  sstr << "<m:ItemChanges>"
22819  "<t:ItemChange>"
22820  << id.to_xml() << "<t:Updates>" << change.to_item_xml()
22821  << "</t:Updates>"
22822  "</t:ItemChange>"
22823  "</m:ItemChanges>"
22824  "</m:UpdateItem>";
22825 
22826  auto response = request(sstr.str());
22827  const auto response_message =
22828  internal::update_item_response_message::parse(std::move(response));
22829  if (!response_message.success())
22830  {
22831  throw exchange_error(response_message.result());
22832  }
22833  check(!response_message.items().empty(), "Expected at least one item");
22834  return response_message.items().front();
22835  }
22836 
22837  item_id
22838  update_item_impl(item_id id, const std::vector<update>& changes,
22839  conflict_resolution resolution,
22841  const folder_id& folder)
22842  {
22843  std::stringstream sstr;
22844  sstr << "<m:UpdateItem "
22845  "MessageDisposition=\"SaveOnly\" "
22846  "ConflictResolution=\""
22847  << internal::enum_to_str(resolution)
22848  << "\" SendMeetingInvitationsOrCancellations=\""
22849  << internal::enum_to_str(cancellations) + "\">";
22850 
22851  if (folder.valid())
22852  {
22853  sstr << "<m:SavedItemFolderId>" << folder.to_xml()
22854  << "</m:SavedItemFolderId>";
22855  }
22856 
22857  sstr << "<m:ItemChanges>";
22858  sstr << "<t:ItemChange>" << id.to_xml() << "<t:Updates>";
22859 
22860  for (const auto& change : changes)
22861  {
22862  sstr << change.to_item_xml();
22863  }
22864 
22865  sstr << "</t:Updates>"
22866  "</t:ItemChange>"
22867  "</m:ItemChanges>"
22868  "</m:UpdateItem>";
22869 
22870  auto response = request(sstr.str());
22871  const auto response_message =
22872  internal::update_item_response_message::parse(std::move(response));
22873  if (!response_message.success())
22874  {
22875  throw exchange_error(response_message.result());
22876  }
22877  check(!response_message.items().empty(), "Expected at least one item");
22878  return response_message.items().front();
22879  }
22880 
22881  folder_id update_folder_impl(folder_id id, update change)
22882  {
22883  std::stringstream sstr;
22884  sstr << "<m:UpdateFolder>"
22885  "<m:FolderChanges>"
22886  "<t:FolderChange>"
22887  << id.to_xml() << "<t:Updates>" << change.to_folder_xml()
22888  << "</t:Updates>"
22889  "</t:FolderChange>"
22890  "</m:FolderChanges>"
22891  "</m:UpdateFolder>";
22892 
22893  auto response = request(sstr.str());
22894  const auto response_message =
22895  internal::update_folder_response_message::parse(
22896  std::move(response));
22897  if (!response_message.success())
22898  {
22899  throw exchange_error(response_message.result());
22900  }
22901  check(!response_message.items().empty(),
22902  "Expected at least one folder");
22903  return response_message.items().front();
22904  }
22905 
22906  folder_id update_folder_impl(folder_id id,
22907  const std::vector<update>& changes)
22908  {
22909  std::stringstream sstr;
22910  sstr << "<m:UpdateFolder>"
22911  "<m:FolderChanges>"
22912  "<t:FolderChange>"
22913  << id.to_xml() << "<t:Updates>";
22914 
22915  for (const auto& change : changes)
22916  {
22917  sstr << change.to_folder_xml();
22918  }
22919 
22920  sstr << "</t:Updates>"
22921  "</t:FolderChange>"
22922  "</m:FolderChanges>"
22923  "</m:UpdateFolder>";
22924 
22925  auto response = request(sstr.str());
22926  const auto response_message =
22927  internal::update_folder_response_message::parse(
22928  std::move(response));
22929  if (!response_message.success())
22930  {
22931  throw exchange_error(response_message.result());
22932  }
22933  check(!response_message.items().empty(),
22934  "Expected at least one folder");
22935  return response_message.items().front();
22936  }
22937 
22938  item_id move_item_impl(item_id item, const folder_id& folder)
22939  {
22940  std::stringstream sstr;
22941  sstr << "<m:MoveItem>"
22942  "<m:ToFolderId>"
22943  << folder.to_xml()
22944  << "</m:ToFolderId>"
22945  "<m:ItemIds>"
22946  << item.to_xml()
22947  << "</m:ItemIds>"
22948  "</m:MoveItem>";
22949 
22950  auto response = request(sstr.str());
22951  const auto response_messages =
22952  internal::move_item_response_message::parse(std::move(response));
22953  if (!response_messages.success())
22954  {
22955  throw exchange_error(response_messages.first_error_or_warning());
22956  }
22957  check(!response_messages.items().empty(), "Expected at least one item");
22958  return response_messages.items().front();
22959  }
22960 
22961  std::vector<item_id> move_item_impl(const std::vector<item_id>& items,
22962  const folder_id& folder)
22963  {
22964  std::stringstream sstr;
22965  sstr << "<m:MoveItem>"
22966  "<m:ToFolderId>"
22967  << folder.to_xml()
22968  << "</m:ToFolderId>"
22969  "<m:ItemIds>";
22970 
22971  for (const auto& item : items)
22972  {
22973  sstr << item.to_xml();
22974  }
22975 
22976  sstr << "</m:ItemIds>"
22977  "</m:MoveItem>";
22978 
22979  auto response = request(sstr.str());
22980  const auto response_messages =
22981  internal::move_item_response_message::parse(std::move(response));
22982  if (!response_messages.success())
22983  {
22984  throw exchange_error(response_messages.first_error_or_warning());
22985  }
22986  check(!response_messages.items().empty(), "Expected at least one item");
22987 
22988  return response_messages.items();
22989  }
22990 
22991  folder_id move_folder_impl(folder_id folder, const folder_id& target)
22992  {
22993  std::stringstream sstr;
22994  sstr << "<m:MoveFolder>"
22995  "<m:ToFolderId>"
22996  << target.to_xml()
22997  << "</m:ToFolderId>"
22998  "<m:FolderIds>"
22999  << folder.to_xml()
23000  << "</m:FolderIds>"
23001  "</m:MoveFolder>";
23002 
23003  auto response = request(sstr.str());
23004  const auto response_messages =
23005  internal::move_folder_response_message::parse(std::move(response));
23006  if (!response_messages.success())
23007  {
23008  throw exchange_error(response_messages.first_error_or_warning());
23009  }
23010  check(!response_messages.items().empty(), "Expected at least one item");
23011  return response_messages.items().front();
23012  }
23013 
23014  std::vector<folder_id>
23015  move_folder_impl(const std::vector<folder_id>& folders,
23016  const folder_id& target)
23017  {
23018  std::stringstream sstr;
23019  sstr << "<m:MoveFolder>"
23020  "<m:ToFolderId>"
23021  << target.to_xml()
23022  << "</m:ToFolderId>"
23023  "<m:FolderIds>";
23024 
23025  for (const auto& folder : folders)
23026  {
23027  sstr << folder.to_xml();
23028  }
23029 
23030  sstr << "</m:FolderIds>"
23031  "</m:MoveFolder>";
23032 
23033  auto response = request(sstr.str());
23034  const auto response_messages =
23035  internal::move_folder_response_message::parse(std::move(response));
23036  if (!response_messages.success())
23037  {
23038  throw exchange_error(response_messages.first_error_or_warning());
23039  }
23040  check(!response_messages.items().empty(), "Expected at least one item");
23041 
23042  return response_messages.items();
23043  }
23044 
23046  resolve_names_impl(const std::string& name,
23047  const std::vector<folder_id>& parent_folder_ids,
23048  search_scope scope)
23049  {
23050  auto version = get_request_server_version();
23051  std::stringstream sstr;
23052  sstr << "<m:ResolveNames "
23053  << "ReturnFullContactData=\""
23054  << "true"
23055  << "\" "
23056  << "SearchScope=\"" << internal::enum_to_str(scope) << "\" ";
23057 
23058  if (version == server_version::exchange_2010_sp2 ||
23059  version == server_version::exchange_2013 ||
23061  {
23062  sstr << "ContactDataShape=\"IdOnly\"";
23063  }
23064  sstr << ">";
23065  if (parent_folder_ids.size() > 0)
23066  {
23067  sstr << "<ParentFolderIds>";
23068  for (const auto& id : parent_folder_ids)
23069  {
23070  sstr << id.to_xml();
23071  }
23072  sstr << "</ParentFolderIds>";
23073  }
23074  sstr << "<m:UnresolvedEntry>" << name << "</m:UnresolvedEntry>"
23075  << "</m:ResolveNames>";
23076  auto response = request(sstr.str());
23077  const auto response_message =
23078  internal::resolve_names_response_message::parse(
23079  std::move(response));
23080  if (response_message.result().code ==
23082  response_message.result().code ==
23084  {
23085  return resolution_set();
23086  }
23087  if (response_message.result().cls == response_class::error)
23088  {
23089  throw exchange_error(response_message.result());
23090  }
23091  return response_message.resolutions();
23092  }
23093 
23094 #ifdef EWS_HAS_VARIANT
23095  subscription_information
23096  subscribe_impl(const std::vector<distinguished_folder_id>& ids,
23097  const std::vector<event_type>& types, int timeout)
23098  {
23099  std::stringstream sstr;
23100  sstr << "<m:Subscribe>"
23101  << "<m:PullSubscriptionRequest>"
23102  << "<t:FolderIds>";
23103  for (const auto& id : ids)
23104  {
23105  sstr << "<t:DistinguishedFolderId Id=\"" << id.id() << "\"/>";
23106  }
23107  sstr << "</t:FolderIds>"
23108  << "<t:EventTypes>";
23109  for (const auto& type : types)
23110  {
23111  sstr << "<t:EventType>" << internal::enum_to_str(type)
23112  << "</t:EventType>";
23113  }
23114  sstr << "</t:EventTypes>"
23115  << "<t:Timeout>" << timeout << "</t:Timeout>"
23116  << "</m:PullSubscriptionRequest>"
23117  << "</m:Subscribe>";
23118  auto response = request(sstr.str());
23119  const auto response_message =
23120  internal::subscribe_response_message::parse(std::move(response));
23121  if (response_message.result().cls == response_class::error)
23122  {
23123  throw exchange_error(response_message.result());
23124  }
23125  return response_message.information();
23126  }
23127 
23128  void unsubscribe_impl(const std::string& id)
23129  {
23130  std::stringstream sstr;
23131  sstr << "<m:Unsubscribe>"
23132  << "<m:SubscriptionId>" << id << "</m:SubscriptionId>"
23133  << "</m:Unsubscribe>";
23134  auto response = request(sstr.str());
23135  const auto response_message =
23136  internal::unsubscribe_response_message::parse(std::move(response));
23137  if (response_message.result().cls != response_class::success)
23138  {
23139  throw exchange_error(response_message.result());
23140  }
23141  }
23142 
23143  notification get_events_impl(const std::string& id, const std::string& mark)
23144  {
23145  std::stringstream sstr;
23146  sstr << "<m:GetEvents>"
23147  << "<m:SubscriptionId>" << id << "</m:SubscriptionId>"
23148  << "<m:Watermark>" << mark << "</m:Watermark>"
23149  << "</m:GetEvents>";
23150  auto response = request(sstr.str());
23151  const auto response_message =
23152  internal::get_events_response_message::parse(std::move(response));
23153  if (response_message.result().cls != response_class::success)
23154  {
23155  throw exchange_error(response_message.result());
23156  }
23157  return response_message.get_notification();
23158  }
23159 #endif
23160 };
23161 typedef basic_service<> service;
23162 
23163 #if defined(EWS_HAS_NON_BUGGY_TYPE_TRAITS) && \
23164  defined(EWS_HAS_CXX17_STATIC_ASSERT)
23165 static_assert(!std::is_default_constructible<service>::value);
23166 static_assert(!std::is_copy_constructible<service>::value);
23167 static_assert(!std::is_copy_assignable<service>::value);
23168 static_assert(std::is_move_constructible<service>::value);
23169 static_assert(std::is_move_assignable<service>::value);
23170 #endif
23171 
23172 // Implementations
23173 
23174 inline void basic_credentials::certify(internal::http_request* request) const
23175 {
23176  check(request, "Expected request, got nullptr");
23177 
23178  std::string login = username_ + ":" + password_;
23179  request->set_option(CURLOPT_USERPWD, login.c_str());
23180  request->set_option(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
23181 }
23182 
23183 inline void ntlm_credentials::certify(internal::http_request* request) const
23184 {
23185  check(request, "Expected request, got nullptr");
23186 
23187  // CURLOPT_USERPWD: domain\username:password
23188  std::string login =
23189  (domain_.empty() ? "" : domain_ + "\\") + username_ + ":" + password_;
23190  request->set_option(CURLOPT_USERPWD, login.c_str());
23191  request->set_option(CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
23192 }
23193 
23194 inline void
23195 internal::oauth2_basic::certify(internal::http_request* request) const
23196 {
23197  check(request, "Expected request, got nullptr");
23198  // FIXME: we should test expiration here and get another token if the
23199  // previous one expired, but we can't change the credentials as they are
23200  // passed const here.
23201  if (access_token.empty() || expired())
23202  {
23203  authenticate(request);
23204  }
23205 
23206  request->set_authorization("Bearer " + access_token);
23207 }
23208 
23209 inline void
23210 internal::oauth2_basic::authenticate(internal::http_request* request) const
23211 {
23212  // Request with the same internal settings of the original one
23213  internal::http_request req(request->get_handle());
23214 
23215  // curl handle to url-encode the data
23216  CURL* c = req.get_handle().get();
23217 
23218  char* escaped_client_id =
23219  curl_easy_escape(c, client_id_.c_str(),
23220  internal::numeric_cast<int>(client_id_.length()));
23221 
23222  std::string url =
23223  "https://login.microsoftonline.com/" + tenant_ + "/oauth2/v2.0/token";
23224  std::string data;
23225 
23226  data.append("client_id=");
23227  data.append(escaped_client_id);
23228 
23229  curl_free(escaped_client_id);
23230 
23231  if (!scope_.empty())
23232  {
23233  char* escaped_scope = curl_easy_escape(
23234  c, scope_.c_str(), internal::numeric_cast<int>(scope_.length()));
23235  data.append("&scope=");
23236  data.append(escaped_scope);
23237  curl_free(escaped_scope);
23238  }
23239 
23240  append_url(c, data);
23241 
23242  // perform a request to get the authentication token
23243  req.set_option(CURLOPT_URL, url.c_str());
23244  req.set_option(CURLOPT_HTTPGET, 1L);
23245  internal::http_response res = req.send(data);
23246 
23247  std::vector<char> content_vector = res.content();
23248  std::string content(content_vector.begin(), content_vector.end());
23249 
23250  rapidjson::Document document;
23251  document.Parse(content.c_str());
23252 
23253  // test for expected JSON contents
23254  if (document.HasParseError())
23255  {
23256  throw exception("OAuth2 Error: JSON Parse Error");
23257  }
23258 
23259  if (!document.IsObject())
23260  {
23261  throw exception("OAuth2 Error: Response is not a JSON Object");
23262  }
23263 
23264  if (!document.HasMember("access_token") ||
23265  !document["access_token"].IsString())
23266  {
23267  throw exception("OAuth2 Error: no access_token in response\n"
23268  "Response: " +
23269  content);
23270  }
23271 
23272  if (!document.HasMember("expires_in") || !document["expires_in"].IsNumber())
23273  {
23274  throw exception("OAuth2 Error: no expiration time in response\n"
23275  "Response: " +
23276  content);
23277  }
23278 
23279  access_token = document["access_token"].GetString();
23280  expiration = std::chrono::steady_clock::time_point(
23281  std::chrono::seconds(document["expires_in"].GetUint64()));
23282 }
23283 
23284 inline void
23285 oauth2_resource_owner_password_credentials::append_url(CURL* c,
23286  std::string& data) const
23287 {
23288  char* escaped_client_secret =
23289  curl_easy_escape(c, client_secret_.c_str(),
23290  internal::numeric_cast<int>(client_secret_.length()));
23291  char* escaped_username = curl_easy_escape(
23292  c, username_.c_str(), internal::numeric_cast<int>(username_.length()));
23293  char* escaped_password = curl_easy_escape(
23294  c, password_.c_str(), internal::numeric_cast<int>(password_.length()));
23295 
23296  data.append("&client_secret=");
23297  data.append(escaped_client_secret);
23298  data.append("&username=");
23299  data.append(escaped_username);
23300  data.append("&password=");
23301  data.append(escaped_password);
23302  data.append("&grant_type=password");
23303 
23304  curl_free(escaped_client_secret);
23305  curl_free(escaped_username);
23306  curl_free(escaped_password);
23307 }
23308 
23309 inline void oauth2_client_credentials::append_url(CURL* c,
23310  std::string& data) const
23311 {
23312  char* escaped_client_secret =
23313  curl_easy_escape(c, client_secret_.c_str(),
23314  internal::numeric_cast<int>(client_secret_.length()));
23315  char* escaped_resource = curl_easy_escape(
23316  c, resource_.c_str(), internal::numeric_cast<int>(resource_.length()));
23317 
23318  data.append("&client_secret=");
23319  data.append(escaped_client_secret);
23320  data.append("&ressource=");
23321  data.append(escaped_resource);
23322  data.append("&grant_type=client_credentials");
23323 
23324  curl_free(escaped_resource);
23325  curl_free(escaped_client_secret);
23326 }
23327 
23328 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
23330 sync_folder_hierarchy_result::parse(internal::http_response&& response)
23331 {
23332  using rapidxml::internal::compare;
23333 
23334  const auto doc = parse_response(std::move(response));
23335  auto elem = internal::get_element_by_qname(
23336  *doc, "SyncFolderHierarchyResponseMessage",
23337  internal::uri<>::microsoft::messages());
23338 
23339  check(elem, "Expected <SyncFolderHierarchyResponseMessage>");
23340  auto result = internal::parse_response_class_and_code(*elem);
23341  if (result.cls == response_class::error)
23342  {
23343  throw exchange_error(result);
23344  }
23345 
23346  auto sync_state_elem = elem->first_node_ns(
23347  internal::uri<>::microsoft::messages(), "SyncState");
23348  check(sync_state_elem, "Expected <SyncState> element");
23349  auto sync_state =
23350  std::string(sync_state_elem->value(), sync_state_elem->value_size());
23351 
23352  auto includes_last_folder_in_range_elem = elem->first_node_ns(
23353  internal::uri<>::microsoft::messages(), "IncludesLastFolderInRange");
23354  check(includes_last_folder_in_range_elem,
23355  "Expected <IncludesLastFolderInRange> element");
23356  auto includes_last_folder_in_range = rapidxml::internal::compare(
23357  includes_last_folder_in_range_elem->value(),
23358  includes_last_folder_in_range_elem->value_size(), "true",
23359  strlen("true"));
23360 
23361  auto changes_elem =
23362  elem->first_node_ns(internal::uri<>::microsoft::messages(), "Changes");
23363  check(changes_elem, "Expected <Changes> element");
23364  std::vector<folder> created_folders;
23365  std::vector<folder> updated_folders;
23366  std::vector<folder_id> deleted_folder_ids;
23367  internal::for_each_child_node(
23368  *changes_elem,
23369  [&created_folders, &updated_folders,
23370  &deleted_folder_ids](const rapidxml::xml_node<>& item_elem) {
23371  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23372  "Create", strlen("Create")))
23373  {
23374  const auto folder_elem = item_elem.first_node();
23375  const auto folder = folder::from_xml_element(*folder_elem);
23376  created_folders.emplace_back(folder);
23377  }
23378 
23379  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23380  "Update", strlen("Update")))
23381  {
23382  const auto folder_elem = item_elem.first_node();
23383  const auto folder = folder::from_xml_element(*folder_elem);
23384  updated_folders.emplace_back(folder);
23385  }
23386 
23387  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23388  "Delete", strlen("Delete")))
23389  {
23390  const auto folder_id_elem = item_elem.first_node_ns(
23391  internal::uri<>::microsoft::types(), "FolderId");
23392  check(folder_id_elem, "Expected <Folder> element");
23393  const auto folder =
23394  folder_id::from_xml_element(*folder_id_elem);
23395  deleted_folder_ids.emplace_back(folder);
23396  }
23397  });
23398 
23399  sync_folder_hierarchy_result response_message(std::move(result));
23400  response_message.sync_state_ = std::move(sync_state);
23401  response_message.created_folders_ = std::move(created_folders);
23402  response_message.updated_folders_ = std::move(updated_folders);
23403  response_message.deleted_folder_ids_ = std::move(deleted_folder_ids);
23404  response_message.includes_last_folder_in_range_ =
23405  includes_last_folder_in_range;
23406 
23407  return response_message;
23408 }
23409 #endif
23410 
23411 #ifndef EWS_DOXYGEN_SHOULD_SKIP_THIS
23413 sync_folder_items_result::parse(internal::http_response&& response)
23414 {
23415  using rapidxml::internal::compare;
23416 
23417  const auto doc = parse_response(std::move(response));
23418  auto elem =
23419  internal::get_element_by_qname(*doc, "SyncFolderItemsResponseMessage",
23420  internal::uri<>::microsoft::messages());
23421 
23422  check(elem, "Expected <SyncFolderItemsResponseMessage>");
23423  auto result = internal::parse_response_class_and_code(*elem);
23424  if (result.cls == response_class::error)
23425  {
23426  throw exchange_error(result);
23427  }
23428 
23429  auto sync_state_elem = elem->first_node_ns(
23430  internal::uri<>::microsoft::messages(), "SyncState");
23431  check(sync_state_elem, "Expected <SyncState> element");
23432  auto sync_state =
23433  std::string(sync_state_elem->value(), sync_state_elem->value_size());
23434 
23435  auto includes_last_item_in_range_elem = elem->first_node_ns(
23436  internal::uri<>::microsoft::messages(), "IncludesLastItemInRange");
23437  check(includes_last_item_in_range_elem,
23438  "Expected <IncludesLastItemInRange> element");
23439  auto includes_last_item_in_range = rapidxml::internal::compare(
23440  includes_last_item_in_range_elem->value(),
23441  includes_last_item_in_range_elem->value_size(), "true", strlen("true"));
23442 
23443  auto changes_elem =
23444  elem->first_node_ns(internal::uri<>::microsoft::messages(), "Changes");
23445  check(changes_elem, "Expected <Changes> element");
23446  std::vector<item_id> created_items;
23447  std::vector<item_id> updated_items;
23448  std::vector<item_id> deleted_items;
23449  std::vector<std::pair<item_id, bool>> read_flag_changed;
23450  internal::for_each_child_node(
23451  *changes_elem,
23452  [&created_items, &updated_items, &deleted_items,
23453  &read_flag_changed](const rapidxml::xml_node<>& item_elem) {
23454  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23455  "Create", strlen("Create")))
23456  {
23457  const auto item_id_elem = item_elem.first_node()->first_node_ns(
23458  internal::uri<>::microsoft::types(), "ItemId");
23459  check(item_id_elem, "Expected <ItemId> element");
23460  const auto item_id = item_id::from_xml_element(*item_id_elem);
23461  created_items.emplace_back(item_id);
23462  }
23463 
23464  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23465  "Update", strlen("Update")))
23466  {
23467  const auto item_id_elem = item_elem.first_node()->first_node_ns(
23468  internal::uri<>::microsoft::types(), "ItemId");
23469  check(item_id_elem, "Expected <ItemId> element");
23470  const auto item_id = item_id::from_xml_element(*item_id_elem);
23471  updated_items.emplace_back(item_id);
23472  }
23473 
23474  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23475  "Delete", strlen("Delete")))
23476  {
23477  const auto item_id_elem = item_elem.first_node_ns(
23478  internal::uri<>::microsoft::types(), "ItemId");
23479  check(item_id_elem, "Expected <ItemId> element");
23480  const auto item_id = item_id::from_xml_element(*item_id_elem);
23481  deleted_items.emplace_back(item_id);
23482  }
23483 
23484  if (compare(item_elem.local_name(), item_elem.local_name_size(),
23485  "ReadFlagChange", strlen("ReadFlagChange")))
23486  {
23487  const auto item_id_elem = item_elem.first_node_ns(
23488  internal::uri<>::microsoft::types(), "ItemId");
23489  check(item_id_elem, "Expected <ItemId> element");
23490 
23491  const auto read_elem = item_elem.first_node_ns(
23492  internal::uri<>::microsoft::types(), "IsRead");
23493  check(read_elem, "Expected <IsRead> element");
23494 
23495  const auto item_id = item_id::from_xml_element(*item_id_elem);
23496 
23497  const bool read =
23498  compare(read_elem->value(), read_elem->value_size(), "true",
23499  strlen("true"));
23500 
23501  read_flag_changed.emplace_back(std::make_pair(item_id, read));
23502  }
23503  });
23504 
23505  sync_folder_items_result response_message(std::move(result));
23506  response_message.sync_state_ = std::move(sync_state);
23507  response_message.created_items_ = std::move(created_items);
23508  response_message.updated_items_ = std::move(updated_items);
23509  response_message.deleted_items_ = std::move(deleted_items);
23510  response_message.read_flag_changed_ = std::move(read_flag_changed);
23511  response_message.includes_last_item_in_range_ = includes_last_item_in_range;
23512 
23513  return response_message;
23514 }
23515 #endif
23516 
23517 namespace internal
23518 {
23519  inline create_folder_response_message
23520  create_folder_response_message::parse(http_response&& response)
23521  {
23522  const auto doc = parse_response(std::move(response));
23523  auto elem = get_element_by_qname(*doc, "CreateFolderResponseMessage",
23524  uri<>::microsoft::messages());
23525 
23526  check(elem, "Expected <CreateFolderResponseMessage>");
23527  auto result = parse_response_class_and_code(*elem);
23528  auto item_ids = std::vector<folder_id>();
23529  auto items_elem =
23530  elem->first_node_ns(uri<>::microsoft::messages(), "Folders");
23531  check(items_elem, "Expected <Folders> element");
23532 
23533  for_each_child_node(
23534  *items_elem, [&item_ids](const rapidxml::xml_node<>& item_elem) {
23535  auto item_id_elem = item_elem.first_node();
23536  check(item_id_elem, "Expected <FolderId> element");
23537  item_ids.emplace_back(
23538  folder_id::from_xml_element(*item_id_elem));
23539  });
23540  return create_folder_response_message(std::move(result),
23541  std::move(item_ids));
23542  }
23543 
23544  inline create_item_response_message
23545  create_item_response_message::parse(http_response&& response)
23546  {
23547  const auto doc = parse_response(std::move(response));
23548  auto elem = get_element_by_qname(*doc, "CreateItemResponseMessage",
23549  uri<>::microsoft::messages());
23550 
23551  check(elem, "Expected <CreateItemResponseMessage>");
23552  auto result = parse_response_class_and_code(*elem);
23553  auto item_ids = std::vector<item_id>();
23554  auto items_elem =
23555  elem->first_node_ns(uri<>::microsoft::messages(), "Items");
23556  check(items_elem, "Expected <Items> element");
23557 
23558  for_each_child_node(
23559  *items_elem, [&item_ids](const rapidxml::xml_node<>& item_elem) {
23560  auto item_id_elem = item_elem.first_node();
23561  check(item_id_elem, "Expected <ItemId> element");
23562  item_ids.emplace_back(item_id::from_xml_element(*item_id_elem));
23563  });
23564  return create_item_response_message(std::move(result),
23565  std::move(item_ids));
23566  }
23567 
23568  inline find_folder_response_message
23569  find_folder_response_message::parse(http_response&& response)
23570  {
23571  const auto doc = parse_response(std::move(response));
23572  auto elem = get_element_by_qname(*doc, "FindFolderResponseMessage",
23573  uri<>::microsoft::messages());
23574 
23575  check(elem, "Expected <FindFolderResponseMessage>");
23576  auto result = parse_response_class_and_code(*elem);
23577 
23578  auto root_folder =
23579  elem->first_node_ns(uri<>::microsoft::messages(), "RootFolder");
23580 
23581  auto items_elem =
23582  root_folder->first_node_ns(uri<>::microsoft::types(), "Folders");
23583  check(items_elem, "Expected <Folders> element");
23584 
23585  auto items = std::vector<folder_id>();
23586  for (auto item_elem = items_elem->first_node(); item_elem;
23587  item_elem = item_elem->next_sibling())
23588  {
23589  // TODO: Check that item is 'FolderId'
23590  check(item_elem, "Expected an element");
23591  auto item_id_elem = item_elem->first_node();
23592  check(item_id_elem, "Expected <FolderId> element");
23593  items.emplace_back(folder_id::from_xml_element(*item_id_elem));
23594  }
23595  return find_folder_response_message(std::move(result),
23596  std::move(items));
23597  }
23598 
23599  inline find_item_response_message
23600  find_item_response_message::parse(http_response&& response)
23601  {
23602  const auto doc = parse_response(std::move(response));
23603  auto elem = get_element_by_qname(*doc, "FindItemResponseMessage",
23604  uri<>::microsoft::messages());
23605 
23606  check(elem, "Expected <FindItemResponseMessage>");
23607  auto result = parse_response_class_and_code(*elem);
23608 
23609  auto root_folder =
23610  elem->first_node_ns(uri<>::microsoft::messages(), "RootFolder");
23611 
23612  auto items_elem =
23613  root_folder->first_node_ns(uri<>::microsoft::types(), "Items");
23614  check(items_elem, "Expected <Items> element");
23615 
23616  auto items = std::vector<item_id>();
23617  for (auto item_elem = items_elem->first_node(); item_elem;
23618  item_elem = item_elem->next_sibling())
23619  {
23620  check(item_elem, "Expected an element");
23621  auto item_id_elem = item_elem->first_node();
23622  check(item_id_elem, "Expected <ItemId> element");
23623  items.emplace_back(item_id::from_xml_element(*item_id_elem));
23624  }
23625  return find_item_response_message(std::move(result), std::move(items));
23626  }
23627 
23628  inline find_calendar_item_response_message
23629  find_calendar_item_response_message::parse(http_response&& response)
23630  {
23631  const auto doc = parse_response(std::move(response));
23632  auto elem = get_element_by_qname(*doc, "FindItemResponseMessage",
23633  uri<>::microsoft::messages());
23634 
23635  check(elem, "Expected <FindItemResponseMessage>");
23636  auto result = parse_response_class_and_code(*elem);
23637 
23638  check_response_message_for_error(*elem);
23639 
23640  auto root_folder =
23641  elem->first_node_ns(uri<>::microsoft::messages(), "RootFolder");
23642  check(root_folder, "Expected <RootFolder> element");
23643 
23644  auto items_elem =
23645  root_folder->first_node_ns(uri<>::microsoft::types(), "Items");
23646  check(items_elem, "Expected <Items> element");
23647 
23648  auto items = std::vector<calendar_item>();
23649  for_each_child_node(
23650  *items_elem, [&items](const rapidxml::xml_node<>& item_elem) {
23651  items.emplace_back(calendar_item::from_xml_element(item_elem));
23652  });
23653  return find_calendar_item_response_message(std::move(result),
23654  std::move(items));
23655  }
23656 
23657  inline update_item_response_message
23658  update_item_response_message::parse(http_response&& response)
23659  {
23660  const auto doc = parse_response(std::move(response));
23661  auto elem = get_element_by_qname(*doc, "UpdateItemResponseMessage",
23662  uri<>::microsoft::messages());
23663 
23664  check(elem, "Expected <UpdateItemResponseMessage>");
23665  auto result = parse_response_class_and_code(*elem);
23666 
23667  auto items_elem =
23668  elem->first_node_ns(uri<>::microsoft::messages(), "Items");
23669  check(items_elem, "Expected <Items> element");
23670 
23671  auto items = std::vector<item_id>();
23672  for (auto item_elem = items_elem->first_node(); item_elem;
23673  item_elem = item_elem->next_sibling())
23674  {
23675  check(item_elem, "Expected an element");
23676  auto item_id_elem = item_elem->first_node();
23677  check(item_id_elem, "Expected <ItemId> element");
23678  items.emplace_back(item_id::from_xml_element(*item_id_elem));
23679  }
23680  return update_item_response_message(std::move(result),
23681  std::move(items));
23682  }
23683 
23684  inline update_folder_response_message
23685  update_folder_response_message::parse(http_response&& response)
23686  {
23687  const auto doc = parse_response(std::move(response));
23688  auto elem = get_element_by_qname(*doc, "UpdateFolderResponseMessage",
23689  uri<>::microsoft::messages());
23690 
23691  check(elem, "Expected <UpdateFolderResponseMessage>");
23692  auto result = parse_response_class_and_code(*elem);
23693 
23694  auto folders_elem =
23695  elem->first_node_ns(uri<>::microsoft::messages(), "Folders");
23696  check(folders_elem, "Expected <Folders> element");
23697 
23698  auto folders = std::vector<folder_id>();
23699  for (auto folder_elem = folders_elem->first_node(); folder_elem;
23700  folder_elem = folder_elem->next_sibling())
23701  {
23702  check(folder_elem, "Expected an element");
23703  auto folder_id_elem = folder_elem->first_node();
23704  check(folder_id_elem, "Expected <FolderId> element");
23705  folders.emplace_back(folder_id::from_xml_element(*folder_id_elem));
23706  }
23707  return update_folder_response_message(std::move(result),
23708  std::move(folders));
23709  }
23710 
23711  inline get_folder_response_message
23712  get_folder_response_message::parse(http_response&& response)
23713  {
23714  const auto doc = parse_response(std::move(response));
23715  auto elem = get_element_by_qname(*doc, "GetFolderResponseMessage",
23716  uri<>::microsoft::messages());
23717  check(elem, "Expected <GetFolderResponseMessage>");
23718  auto result = parse_response_class_and_code(*elem);
23719  auto items_elem =
23720  elem->first_node_ns(uri<>::microsoft::messages(), "Folders");
23721  check(items_elem, "Expected <Folders> element");
23722  auto items = std::vector<folder>();
23723  for_each_child_node(
23724  *items_elem, [&items](const rapidxml::xml_node<>& item_elem) {
23725  items.emplace_back(folder::from_xml_element(item_elem));
23726  });
23727  return get_folder_response_message(std::move(result), std::move(items));
23728  }
23729 
23730  inline get_room_lists_response_message
23731  get_room_lists_response_message::parse(http_response&& response)
23732  {
23733  const auto doc = parse_response(std::move(response));
23734  auto elem = get_element_by_qname(*doc, "GetRoomListsResponse",
23735  uri<>::microsoft::messages());
23736  check(elem, "Expected <GetRoomListsResponse>");
23737 
23738  auto result = parse_response_class_and_code(*elem);
23739  if (result.cls == response_class::error)
23740  {
23741  throw exchange_error(result);
23742  }
23743 
23744  auto room_lists = std::vector<mailbox>();
23745  auto items_elem =
23746  elem->first_node_ns(uri<>::microsoft::messages(), "RoomLists");
23747  check(items_elem, "Expected <RoomLists> element");
23748 
23749  for_each_child_node(
23750  *items_elem, [&room_lists](const rapidxml::xml_node<>& item_elem) {
23751  room_lists.emplace_back(mailbox::from_xml_element(item_elem));
23752  });
23753  return get_room_lists_response_message(std::move(result),
23754  std::move(room_lists));
23755  }
23756 
23757  inline get_rooms_response_message
23758  get_rooms_response_message::parse(http_response&& response)
23759  {
23760  const auto doc = parse_response(std::move(response));
23761  auto elem = get_element_by_qname(*doc, "GetRoomsResponse",
23762  uri<>::microsoft::messages());
23763 
23764  check(elem, "Expected <GetRoomsResponse>");
23765  auto result = parse_response_class_and_code(*elem);
23766  auto rooms = std::vector<mailbox>();
23767  auto items_elem =
23768  elem->first_node_ns(uri<>::microsoft::messages(), "Rooms");
23769  if (!items_elem)
23770  {
23771  return get_rooms_response_message(std::move(result),
23772  std::move(rooms));
23773  }
23774 
23775  for_each_child_node(
23776  *items_elem, [&rooms](const rapidxml::xml_node<>& item_elem) {
23777  auto room_elem =
23778  item_elem.first_node_ns(uri<>::microsoft::types(), "Id");
23779  check(room_elem, "Expected <Id> element");
23780  rooms.emplace_back(mailbox::from_xml_element(*room_elem));
23781  });
23782  return get_rooms_response_message(std::move(result), std::move(rooms));
23783  }
23784 
23785  inline folder_response_message
23786  folder_response_message::parse(http_response&& response)
23787  {
23788  const auto doc = parse_response(std::move(response));
23789 
23790  auto response_messages = get_element_by_qname(
23791  *doc, "ResponseMessages", uri<>::microsoft::messages());
23792  check(response_messages, "Expected <ResponseMessages> node");
23793 
23794  std::vector<folder_response_message::response_message> messages;
23795  for_each_child_node(
23796  *response_messages, [&](const rapidxml::xml_node<>& node) {
23797  auto result = parse_response_class_and_code(node);
23798 
23799  auto items_elem =
23800  node.first_node_ns(uri<>::microsoft::messages(), "Folders");
23801  check(items_elem, "Expected <Folders> element");
23802 
23803  auto items = std::vector<folder>();
23804  for_each_child_node(
23805  *items_elem,
23806  [&items](const rapidxml::xml_node<>& item_elem) {
23807  items.emplace_back(folder::from_xml_element(item_elem));
23808  });
23809 
23810  messages.emplace_back(
23811  std::make_tuple(result.cls, result.code, std::move(items)));
23812  });
23813 
23814  return folder_response_message(std::move(messages));
23815  }
23816 
23817  template <typename ItemType>
23818  inline get_item_response_message<ItemType>
23819  get_item_response_message<ItemType>::parse(http_response&& response)
23820  {
23821  const auto doc = parse_response(std::move(response));
23822  auto elem = get_element_by_qname(*doc, "GetItemResponseMessage",
23823  uri<>::microsoft::messages());
23824  check(elem, "Expected <GetItemResponseMessage>");
23825  auto result = parse_response_class_and_code(*elem);
23826  auto items_elem =
23827  elem->first_node_ns(uri<>::microsoft::messages(), "Items");
23828  check(items_elem, "Expected <Items> element");
23829  auto items = std::vector<ItemType>();
23830  for_each_child_node(
23831  *items_elem, [&items](const rapidxml::xml_node<>& item_elem) {
23832  items.emplace_back(ItemType::from_xml_element(item_elem));
23833  });
23834  return get_item_response_message(std::move(result), std::move(items));
23835  }
23836 
23837  inline move_item_response_message
23838  move_item_response_message::parse(http_response&& response)
23839  {
23840  const auto doc = parse_response(std::move(response));
23841 
23842  auto response_messages = get_element_by_qname(
23843  *doc, "ResponseMessages", uri<>::microsoft::messages());
23844  check(response_messages, "Expected <ResponseMessages> node");
23845 
23846  using rapidxml::internal::compare;
23847 
23848  std::vector<response_message_with_ids::response_message> messages;
23849  for_each_child_node(
23850  *response_messages, [&](const rapidxml::xml_node<>& node) {
23851  check(compare(node.local_name(), node.local_name_size(),
23852  "MoveItemResponseMessage",
23853  strlen("MoveItemResponseMessage")),
23854  "Expected <MoveItemResponseMessage> element");
23855 
23856  auto result = parse_response_class_and_code(node);
23857 
23858  auto items_elem =
23859  node.first_node_ns(uri<>::microsoft::messages(), "Items");
23860  check(items_elem, "Expected <Items> element");
23861 
23862  auto items = std::vector<item_id>();
23863  for_each_child_node(
23864  *items_elem,
23865  [&items](const rapidxml::xml_node<>& item_elem) {
23866  auto item_id = item_elem.first_node_ns(
23867  uri<>::microsoft::types(), "ItemId");
23868  check(item_id, "Expected <ItemId> element");
23869  items.emplace_back(item_id::from_xml_element(*item_id));
23870  });
23871 
23872  messages.emplace_back(
23873  std::make_tuple(result.cls, result.code, std::move(items)));
23874  });
23875 
23876  return move_item_response_message(std::move(messages));
23877  }
23878 
23879  inline move_folder_response_message
23880  move_folder_response_message::parse(http_response&& response)
23881  {
23882  const auto doc = parse_response(std::move(response));
23883 
23884  auto response_messages = get_element_by_qname(
23885  *doc, "ResponseMessages", uri<>::microsoft::messages());
23886  check(response_messages, "Expected <ResponseMessages> node");
23887 
23888  using rapidxml::internal::compare;
23889 
23890  std::vector<response_message_with_ids::response_message> messages;
23891  for_each_child_node(
23892  *response_messages, [&](const rapidxml::xml_node<>& node) {
23893  check(compare(node.local_name(), node.local_name_size(),
23894  "MoveFolderResponseMessage",
23895  strlen("MoveFolderResponseMessage")),
23896  "Expected <MoveFolderResponseMessage> element");
23897 
23898  auto result = parse_response_class_and_code(node);
23899 
23900  auto folders_elem =
23901  node.first_node_ns(uri<>::microsoft::messages(), "Folders");
23902  check(folders_elem, "Expected <Folders> element");
23903 
23904  auto folders = std::vector<folder_id>();
23905  for_each_child_node(
23906  *folders_elem,
23907  [&folders](const rapidxml::xml_node<>& folder_elem) {
23908  auto folder_id = folder_elem.first_node_ns(
23909  uri<>::microsoft::types(), "FolderId");
23910  check(folder_id, "Expected <FolderId> element");
23911  folders.emplace_back(
23912  folder_id::from_xml_element(*folder_id));
23913  });
23914 
23915  messages.emplace_back(std::make_tuple(result.cls, result.code,
23916  std::move(folders)));
23917  });
23918 
23919  return move_folder_response_message(std::move(messages));
23920  }
23921 
23922  template <typename ItemType>
23923  inline item_response_messages<ItemType>
23924  item_response_messages<ItemType>::parse(http_response&& response)
23925  {
23926  const auto doc = parse_response(std::move(response));
23927 
23928  auto response_messages = get_element_by_qname(
23929  *doc, "ResponseMessages", uri<>::microsoft::messages());
23930  check(response_messages, "Expected <ResponseMessages> node");
23931 
23932  std::vector<item_response_messages::response_message> messages;
23933  for_each_child_node(
23934  *response_messages, [&](const rapidxml::xml_node<>& node) {
23935  auto result = parse_response_class_and_code(node);
23936 
23937  auto items_elem =
23938  node.first_node_ns(uri<>::microsoft::messages(), "Items");
23939  check(items_elem, "Expected <Items> element");
23940 
23941  auto items = std::vector<ItemType>();
23942  for_each_child_node(
23943  *items_elem,
23944  [&items](const rapidxml::xml_node<>& item_elem) {
23945  items.emplace_back(
23946  ItemType::from_xml_element(item_elem));
23947  });
23948 
23949  messages.emplace_back(
23950  std::make_tuple(result.cls, result.code, std::move(items)));
23951  });
23952 
23953  return item_response_messages(std::move(messages));
23954  }
23955 
23956  inline std::vector<delegate_user> delegate_response_message::parse_users(
23957  const rapidxml::xml_node<>& response_element)
23958  {
23959  using rapidxml::internal::compare;
23960 
23961  std::vector<delegate_user> delegate_users;
23962  for_each_child_node(
23963  response_element, [&](const rapidxml::xml_node<>& node) {
23964  if (compare(node.local_name(), node.local_name_size(),
23965  "ResponseMessages", strlen("ResponseMessages")))
23966  {
23967  for_each_child_node(
23968  node, [&](const rapidxml::xml_node<>& msg) {
23969  for_each_child_node(
23970  msg,
23971  [&](const rapidxml::xml_node<>& msg_content) {
23972  if (compare(msg_content.local_name(),
23973  msg_content.local_name_size(),
23974  "DelegateUser",
23975  strlen("DelegateUser")))
23976  {
23977  delegate_users.emplace_back(
23978  delegate_user::from_xml_element(
23979  msg_content));
23980  }
23981  });
23982  });
23983  }
23984  });
23985  return delegate_users;
23986  }
23987 
23988  inline add_delegate_response_message
23989  add_delegate_response_message::parse(http_response&& response)
23990  {
23991  const auto doc = parse_response(std::move(response));
23992  auto response_elem = get_element_by_qname(*doc, "AddDelegateResponse",
23993  uri<>::microsoft::messages());
23994  check(response_elem, "Expected <AddDelegateResponse>");
23995  auto result = parse_response_class_and_code(*response_elem);
23996 
23997  std::vector<delegate_user> delegates;
23998  if (result.code == response_code::no_error)
23999  {
24000  delegates = delegate_response_message::parse_users(*response_elem);
24001  }
24002  return add_delegate_response_message(std::move(result),
24003  std::move(delegates));
24004  }
24005 
24006  inline get_delegate_response_message
24007  get_delegate_response_message::parse(http_response&& response)
24008  {
24009  const auto doc = parse_response(std::move(response));
24010  auto response_elem = get_element_by_qname(*doc, "GetDelegateResponse",
24011  uri<>::microsoft::messages());
24012  check(response_elem, "Expected <GetDelegateResponse>");
24013  auto result = parse_response_class_and_code(*response_elem);
24014 
24015  std::vector<delegate_user> delegates;
24016  if (result.code == response_code::no_error)
24017  {
24018  delegates = delegate_response_message::parse_users(*response_elem);
24019  }
24020  return get_delegate_response_message(std::move(result),
24021  std::move(delegates));
24022  }
24023 
24024  inline remove_delegate_response_message
24025  remove_delegate_response_message::parse(http_response&& response)
24026  {
24027  const auto doc = parse_response(std::move(response));
24028  auto resp = get_element_by_qname(*doc, "RemoveDelegateResponse",
24029  uri<>::microsoft::messages());
24030  check(resp, "Expected <RemoveDelegateResponse>");
24031 
24032  auto result = parse_response_class_and_code(*resp);
24033  if (result.code == response_code::no_error)
24034  {
24035  // We still need to check each individual element in
24036  // <ResponseMessages> for errors ¯\_(⊙︿⊙)_/¯
24037 
24038  using rapidxml::internal::compare;
24039 
24040  for_each_child_node(*resp, [](const rapidxml::xml_node<>& elem) {
24041  if (compare(elem.local_name(), elem.local_name_size(),
24042  "ResponseMessages", strlen("ResponseMessages")))
24043  {
24044  for_each_child_node(
24045  elem, [](const rapidxml::xml_node<>& msg) {
24046  auto response_class_attr =
24047  msg.first_attribute("ResponseClass");
24048  if (compare(response_class_attr->value(),
24049  response_class_attr->value_size(),
24050  "Error", 5))
24051  {
24052  // Okay, we got an error. Additional
24053  // context about the error might be
24054  // available in <m:MessageText>. Throw
24055  // directly from here.
24056 
24057  auto code = response_code::no_error;
24058 
24059  auto rcode_elem = msg.first_node_ns(
24060  uri<>::microsoft::messages(),
24061  "ResponseCode");
24062  check(rcode_elem,
24063  "Expected <ResponseCode> element");
24064  code =
24065  str_to_response_code(rcode_elem->value());
24066 
24067  auto message_text = msg.first_node_ns(
24068  uri<>::microsoft::messages(),
24069  "MessageText");
24070 
24071  if (message_text)
24072  {
24073  throw exchange_error(
24074  code, std::string(
24075  message_text->value(),
24076  message_text->value_size()));
24077  }
24078 
24079  throw exchange_error(code);
24080  }
24081  });
24082  }
24083  });
24084  }
24085 
24086  return remove_delegate_response_message(std::move(result));
24087  }
24088 
24089  inline resolve_names_response_message
24090  resolve_names_response_message::parse(http_response&& response)
24091  {
24092  using rapidxml::internal::compare;
24093  const auto doc = parse_response(std::move(response));
24094  auto response_elem = get_element_by_qname(
24095  *doc, "ResolveNamesResponseMessage", uri<>::microsoft::messages());
24096  check(response_elem, "Expected <ResolveNamesResponseMessage>");
24097  auto result = parse_response_class_and_code(*response_elem);
24098 
24099  resolution_set resolutions;
24100  if (result.code == response_code::no_error ||
24101  result.code ==
24103  {
24104  auto resolution_set_element = response_elem->first_node_ns(
24105  uri<>::microsoft::messages(), "ResolutionSet");
24106  check(resolution_set_element, "Expected <ResolutionSet> element");
24107 
24108  for (auto attr = resolution_set_element->first_attribute();
24109  attr != nullptr; attr = attr->next_attribute())
24110  {
24111  if (compare("IndexedPagingOffset",
24112  strlen("IndexedPagingOffset"), attr->local_name(),
24113  attr->local_name_size()))
24114  {
24115  resolutions.indexed_paging_offset =
24116  std::stoi(resolution_set_element
24117  ->first_attribute("IndexedPagingOffset")
24118  ->value());
24119  }
24120  if (compare("NumeratorOffset", strlen("NumeratorOffset"),
24121  attr->local_name(), attr->local_name_size()))
24122  {
24123  resolutions.numerator_offset =
24124  std::stoi(resolution_set_element
24125  ->first_attribute("NumeratorOffset")
24126  ->value());
24127  }
24128  if (compare("AbsoluteDenominator",
24129  strlen("AbsoluteDenominator"), attr->local_name(),
24130  attr->local_name_size()))
24131  {
24132  resolutions.absolute_denominator =
24133  std::stoi(resolution_set_element
24134  ->first_attribute("AbsoluteDenominator")
24135  ->value());
24136  }
24137  if (compare("IncludesLastItemInRange",
24138  strlen("IncludesLastItemInRange"),
24139  attr->local_name(), attr->local_name_size()))
24140  {
24141  auto includes =
24142  resolution_set_element
24143  ->first_attribute("IncludesLastItemInRange")
24144  ->value();
24145  if (includes)
24146  {
24147  resolutions.includes_last_item_in_range = true;
24148  }
24149  else
24150  {
24151  resolutions.includes_last_item_in_range = false;
24152  }
24153  }
24154  if (compare("TotalItemsInView", strlen("TotalItemsInView"),
24155  attr->local_name(), attr->local_name_size()))
24156  {
24157  resolutions.total_items_in_view =
24158  std::stoi(resolution_set_element
24159  ->first_attribute("TotalItemsInView")
24160  ->value());
24161  }
24162  }
24163 
24164  for (auto res = resolution_set_element->first_node_ns(
24165  uri<>::microsoft::types(), "Resolution");
24166  res; res = res->next_sibling())
24167  {
24168  check(res, "Expected <Resolution> element");
24169  resolution r;
24170 
24171  if (compare("Mailbox", strlen("Mailbox"),
24172  res->first_node()->local_name(),
24173  res->first_node()->local_name_size()))
24174  {
24175  auto mailbox_elem = res->first_node("t:Mailbox");
24176  r.mailbox = mailbox::from_xml_element(*mailbox_elem);
24177  }
24178  if (compare("Contact", strlen("Contact"),
24179  res->last_node()->local_name(),
24180  res->last_node()->local_name_size()))
24181  {
24182  auto contact_elem = res->last_node("t:Contact");
24183  auto directory_id_elem = contact_elem->first_node_ns(
24184  internal::uri<>::microsoft::types(), "DirectoryId");
24185 
24186  if (directory_id_elem)
24187  {
24188  directory_id id(directory_id_elem->value());
24189  r.directory_id = id;
24190  }
24191 
24192  r.contact = std::make_shared<ews::contact>(
24194  *contact_elem));
24195  }
24196 
24197  resolutions.resolutions.emplace_back(r);
24198  }
24199  }
24200  return resolve_names_response_message(std::move(result),
24201  std::move(resolutions));
24202  }
24203 
24204 #ifdef EWS_HAS_VARIANT
24205  inline subscribe_response_message
24206  subscribe_response_message::parse(http_response&& response)
24207  {
24208  using rapidxml::internal::compare;
24209  const auto doc = parse_response(std::move(response));
24210  auto response_elem = get_element_by_qname(
24211  *doc, "SubscribeResponseMessage", uri<>::microsoft::messages());
24212  check(response_elem, "Expected <SubscribeResponseMessage>");
24213  auto result = parse_response_class_and_code(*response_elem);
24214 
24215  std::string id;
24216  std::string mark;
24217  if (result.code == response_code::no_error)
24218  {
24219 
24220  id = response_elem
24221  ->first_node_ns(uri<>::microsoft::messages(),
24222  "SubscriptionId")
24223  ->value();
24224 
24225  mark =
24226  response_elem
24227  ->first_node_ns(uri<>::microsoft::messages(), "Watermark")
24228  ->value();
24229  }
24230  return subscribe_response_message(std::move(result),
24231  subscription_information(id, mark));
24232  }
24233 
24234  inline unsubscribe_response_message
24235  unsubscribe_response_message::parse(http_response&& response)
24236  {
24237  using rapidxml::internal::compare;
24238  const auto doc = parse_response(std::move(response));
24239  auto response_elem = get_element_by_qname(
24240  *doc, "UnsubscribeResponseMessage", uri<>::microsoft::messages());
24241  check(response_elem, "Expected <UnsubscribeResponseMessage>");
24242  auto result = parse_response_class_and_code(*response_elem);
24243 
24244  return unsubscribe_response_message(std::move(result));
24245  }
24246 
24247  inline get_events_response_message
24248  get_events_response_message::parse(http_response&& response)
24249  {
24250  using rapidxml::internal::compare;
24251  const auto doc = parse_response(std::move(response));
24252  auto response_elem = get_element_by_qname(
24253  *doc, "GetEventsResponseMessage", uri<>::microsoft::messages());
24254  check(response_elem, "Expected <GetEventsResponseMessage>");
24255  auto result = parse_response_class_and_code(*response_elem);
24256 
24257  notification n;
24258  if (result.code == response_code::no_error)
24259  {
24260  auto notification_element = response_elem->first_node_ns(
24261  uri<>::microsoft::messages(), "Notification");
24262  check(notification_element, "Expected <Notification> element");
24263 
24264  n.subscription_id =
24265  notification_element
24266  ->first_node_ns(uri<>::microsoft::types(), "SubscriptionId")
24267  ->value();
24268 
24269  n.previous_watermark =
24270  notification_element
24271  ->first_node_ns(uri<>::microsoft::types(),
24272  "PreviousWatermark")
24273  ->value();
24274 
24275  n.more_events =
24276  notification_element
24277  ->first_node_ns(uri<>::microsoft::types(), "MoreEvents")
24278  ->value();
24279 
24280  if (notification_element->first_node_ns(uri<>::microsoft::types(),
24281  "StatusEvent") != nullptr)
24282  {
24283  auto e = notification_element->first_node_ns(
24284  uri<>::microsoft::types(), "StatusEvent");
24285  status_event s = status_event::from_xml_element(*e);
24286  n.events.emplace_back(s);
24287  }
24288  else
24289  {
24290  for (auto res = notification_element->first_node_ns(
24291  uri<>::microsoft::types(), "CopiedEvent");
24292  res; res = res->next_sibling())
24293  {
24294  copied_event c = copied_event::from_xml_element(*res);
24295  n.events.emplace_back(c);
24296  }
24297  for (auto res = notification_element->first_node_ns(
24298  uri<>::microsoft::types(), "CreatedEvent");
24299  res; res = res->next_sibling())
24300  {
24301  created_event c = created_event::from_xml_element(*res);
24302  n.events.emplace_back(c);
24303  }
24304  for (auto res = notification_element->first_node_ns(
24305  uri<>::microsoft::types(), "DeletedEvent");
24306  res; res = res->next_sibling())
24307  {
24308  deleted_event d = deleted_event::from_xml_element(*res);
24309  n.events.emplace_back(d);
24310  }
24311  for (auto res = notification_element->first_node_ns(
24312  uri<>::microsoft::types(), "ModifiedEvent");
24313  res; res = res->next_sibling())
24314  {
24315  modified_event d = modified_event::from_xml_element(*res);
24316  n.events.emplace_back(d);
24317  }
24318  for (auto res = notification_element->first_node_ns(
24319  uri<>::microsoft::types(), "MovedEvent");
24320  res; res = res->next_sibling())
24321  {
24322  moved_event m = moved_event::from_xml_element(*res);
24323  n.events.emplace_back(m);
24324  }
24325  for (auto res = notification_element->first_node_ns(
24326  uri<>::microsoft::types(), "NewMailEvent");
24327  res; res = res->next_sibling())
24328  {
24329  new_mail_event m = new_mail_event::from_xml_element(*res);
24330  n.events.emplace_back(m);
24331  }
24332  for (auto res = notification_element->first_node_ns(
24333  uri<>::microsoft::types(), "FreeBusyChangedEvent");
24334  res; res = res->next_sibling())
24335  {
24336  free_busy_changed_event f =
24337  free_busy_changed_event::from_xml_element(*res);
24338  n.events.emplace_back(f);
24339  }
24340  }
24341  }
24342  return get_events_response_message(std::move(result), std::move(n));
24343  }
24344 #endif
24345 } // namespace internal
24346 
24351 inline attachment attachment::from_item(const item& the_item,
24352  const std::string& name)
24353 {
24354  // Creating a new <ItemAttachment> with the <CreateAttachment>
24355  // method is pretty similar to a <CreateItem> method call. However,
24356  // most of the times we do not want to create item attachments out
24357  // of thin air but attach an _existing_ item.
24358  //
24359  // If we want create an attachment from an existing item, we need
24360  // to first call <GetItem> before we call <CreateItem> and put the
24361  // complete item from the response into the <CreateAttachment>
24362  // call.
24363  //
24364  // There is a shortcut for Calendar, E-mail message items, and Posting
24365  // notes: use <BaseShape>IdOnly</BaseShape> and <AdditionalProperties>
24366  // with item::MimeContent in <GetItem> call, remove <ItemId> from the
24367  // response and pass that to <CreateAttachment>.
24368 
24369 #if 0
24370  const auto item_class = the_item.get_item_class();
24371  if ( item_class == "" // Calendar items
24372  || item_class == "IPM.Note" // E-mail messages
24373  || item_class == "IPM.Post" // Posting notes in a folder
24374  )
24375  {
24376  auto mime_content_node = props.get_node("MimeContent");
24377  }
24378 #endif
24379 
24380  auto& props = the_item.xml();
24381 
24382 // Filter out read-only property paths
24383 #ifdef EWS_HAS_INITIALIZER_LISTS
24384  for (const auto& property_name :
24385  // item
24386  {"ItemId", "ParentFolderId", "DateTimeReceived", "Size", "IsSubmitted",
24387  "IsDraft", "IsFromMe", "IsResend", "IsUnmodified", "DateTimeSent",
24388  "DateTimeCreated", "ResponseObjects", "DisplayCc", "DisplayTo",
24389  "HasAttachments", "EffectiveRights", "LastModifiedName",
24390  "LastModifiedTime", "IsAssociated", "WebClientReadFormQueryString",
24391  "WebClientEditFormQueryString", "ConversationId", "InstanceKey",
24392 
24393  // message
24394  "ConversationIndex", "ConversationTopic"})
24395 #else
24396  std::vector<std::string> properties;
24397 
24398  // item
24399  properties.push_back("ItemId");
24400  properties.push_back("ParentFolderId");
24401  properties.push_back("DateTimeReceived");
24402  properties.push_back("Size");
24403  properties.push_back("IsSubmitted");
24404  properties.push_back("IsDraft");
24405  properties.push_back("IsFromMe");
24406  properties.push_back("IsResend");
24407  properties.push_back("IsUnmodified");
24408  properties.push_back("DateTimeSent");
24409  properties.push_back("DateTimeCreated");
24410  properties.push_back("ResponseObjects");
24411  properties.push_back("DisplayCc");
24412  properties.push_back("DisplayTo");
24413  properties.push_back("HasAttachments");
24414  properties.push_back("EffectiveRights");
24415  properties.push_back("LastModifiedName");
24416  properties.push_back("LastModifiedTime");
24417  properties.push_back("IsAssociated");
24418  properties.push_back("WebClientReadFormQueryString");
24419  properties.push_back("WebClientEditFormQueryString");
24420  properties.push_back("ConversationId");
24421  properties.push_back("InstanceKey");
24422 
24423  // message
24424  properties.push_back("ConversationIndex");
24425  properties.push_back("ConversationTopic");
24426 
24427  for (const auto& property_name : properties)
24428 #endif
24429  {
24430  auto node = props.get_node(property_name);
24431  if (node)
24432  {
24433  auto parent = node->parent();
24434  check(parent, "Expected node to have a parent node");
24435  parent->remove_node(node);
24436  }
24437  }
24438 
24439  auto obj = attachment();
24440  obj.type_ = type::item;
24441 
24442  using internal::create_node;
24443  auto& attachment_node =
24444  create_node(*obj.xml_.document(), "t:ItemAttachment");
24445  create_node(attachment_node, "t:Name", name);
24446  props.append_to(attachment_node);
24447 
24448  return obj;
24449 }
24450 
24451 inline std::string delegate_user::delegate_permissions::to_xml() const
24452 {
24453  std::stringstream sstr;
24454  sstr << "<t:DelegatePermissions>";
24455  sstr << "<t:CalendarFolderPermissionLevel>"
24456  << internal::enum_to_str(calendar_folder)
24457  << "</t:CalendarFolderPermissionLevel>";
24458 
24459  sstr << "<t:TasksFolderPermissionLevel>"
24460  << internal::enum_to_str(tasks_folder)
24461  << "</t:TasksFolderPermissionLevel>";
24462 
24463  sstr << "<t:InboxFolderPermissionLevel>"
24464  << internal::enum_to_str(inbox_folder)
24465  << "</t:InboxFolderPermissionLevel>";
24466 
24467  sstr << "<t:ContactsFolderPermissionLevel>"
24468  << internal::enum_to_str(contacts_folder)
24469  << "</t:ContactsFolderPermissionLevel>";
24470 
24471  sstr << "<t:NotesFolderPermissionLevel>"
24472  << internal::enum_to_str(notes_folder)
24473  << "</t:NotesFolderPermissionLevel>";
24474 
24475  sstr << "<t:JournalFolderPermissionLevel>"
24476  << internal::enum_to_str(journal_folder)
24477  << "</t:JournalFolderPermissionLevel>";
24478  sstr << "</t:DelegatePermissions>";
24479  return sstr.str();
24480 }
24481 
24483 delegate_user::delegate_permissions::from_xml_element(
24484  const rapidxml::xml_node<char>& elem)
24485 {
24486  using rapidxml::internal::compare;
24487 
24488  delegate_permissions perms;
24489  for (auto node = elem.first_node(); node; node = node->next_sibling())
24490  {
24491  if (compare(node->local_name(), node->local_name_size(),
24492  "CalendarFolderPermissionLevel",
24493  strlen("CalendarFolderPermissionLevel")))
24494  {
24495  perms.calendar_folder = internal::str_to_permission_level(
24496  std::string(node->value(), node->value_size()));
24497  }
24498  else if (compare(node->local_name(), node->local_name_size(),
24499  "TasksFolderPermissionLevel",
24500  strlen("TasksFolderPermissionLevel")))
24501  {
24502  perms.tasks_folder = internal::str_to_permission_level(
24503  std::string(node->value(), node->value_size()));
24504  }
24505  else if (compare(node->local_name(), node->local_name_size(),
24506  "InboxFolderPermissionLevel",
24507  strlen("InboxFolderPermissionLevel")))
24508  {
24509  perms.inbox_folder = internal::str_to_permission_level(
24510  std::string(node->value(), node->value_size()));
24511  }
24512  else if (compare(node->local_name(), node->local_name_size(),
24513  "ContactsFolderPermissionLevel",
24514  strlen("ContactsFolderPermissionLevel")))
24515  {
24516  perms.contacts_folder = internal::str_to_permission_level(
24517  std::string(node->value(), node->value_size()));
24518  }
24519  else if (compare(node->local_name(), node->local_name_size(),
24520  "NotesFolderPermissionLevel",
24521  strlen("NotesFolderPermissionLevel")))
24522  {
24523  perms.notes_folder = internal::str_to_permission_level(
24524  std::string(node->value(), node->value_size()));
24525  }
24526  else if (compare(node->local_name(), node->local_name_size(),
24527  "JournalFolderPermissionLevel",
24528  strlen("JournalFolderPermissionLevel")))
24529  {
24530  perms.journal_folder = internal::str_to_permission_level(
24531  std::string(node->value(), node->value_size()));
24532  }
24533  else
24534  {
24535  throw exception(
24536  "Unexpected child element in <DelegatePermissions>");
24537  }
24538  }
24539  return perms;
24540 }
24541 
24542 inline std::unique_ptr<recurrence_pattern>
24543 recurrence_pattern::from_xml_element(const rapidxml::xml_node<>& elem)
24544 {
24545  using rapidxml::internal::compare;
24546  using namespace internal;
24547 
24548  check(compare(elem.local_name(), elem.local_name_size(), "Recurrence",
24549  strlen("Recurrence")),
24550  "Expected a <Recurrence> element");
24551 
24552  auto node = elem.first_node_ns(uri<>::microsoft::types(),
24553  "AbsoluteYearlyRecurrence");
24554  if (node)
24555  {
24556  auto mon = month::jan;
24557  uint32_t day_of_month = 0U;
24558 
24559  for (auto child = node->first_node(); child;
24560  child = child->next_sibling())
24561  {
24562  if (compare(child->local_name(), child->local_name_size(), "Month",
24563  strlen("Month")))
24564  {
24565  mon = str_to_month(
24566  std::string(child->value(), child->value_size()));
24567  }
24568  else if (compare(child->local_name(), child->local_name_size(),
24569  "DayOfMonth", strlen("DayOfMonth")))
24570  {
24571  day_of_month = std::stoul(
24572  std::string(child->value(), child->value_size()));
24573  }
24574  }
24575 
24576 #ifdef EWS_HAS_MAKE_UNIQUE
24577  return std::make_unique<absolute_yearly_recurrence>(
24578  std::move(day_of_month), std::move(mon));
24579 #else
24580  return std::unique_ptr<absolute_yearly_recurrence>(
24581  new absolute_yearly_recurrence(std::move(day_of_month),
24582  std::move(mon)));
24583 #endif
24584  }
24585 
24586  node = elem.first_node_ns(uri<>::microsoft::types(),
24587  "RelativeYearlyRecurrence");
24588  if (node)
24589  {
24590  auto mon = month::jan;
24591  auto index = day_of_week_index::first;
24592  auto days_of_week = day_of_week::sun;
24593 
24594  for (auto child = node->first_node(); child;
24595  child = child->next_sibling())
24596  {
24597  if (compare(child->local_name(), child->local_name_size(), "Month",
24598  strlen("Month")))
24599  {
24600  mon = str_to_month(
24601  std::string(child->value(), child->value_size()));
24602  }
24603  else if (compare(child->local_name(), child->local_name_size(),
24604  "DayOfWeekIndex", strlen("DayOfWeekIndex")))
24605  {
24606  index = str_to_day_of_week_index(
24607  std::string(child->value(), child->value_size()));
24608  }
24609  else if (compare(child->local_name(), child->local_name_size(),
24610  "DaysOfWeek", strlen("DaysOfWeek")))
24611  {
24612  days_of_week = str_to_day_of_week(
24613  std::string(child->value(), child->value_size()));
24614  }
24615  }
24616 
24617 #ifdef EWS_HAS_MAKE_UNIQUE
24618  return std::make_unique<relative_yearly_recurrence>(
24619  std::move(days_of_week), std::move(index), std::move(mon));
24620 #else
24621  return std::unique_ptr<relative_yearly_recurrence>(
24622  new relative_yearly_recurrence(std::move(days_of_week),
24623  std::move(index), std::move(mon)));
24624 #endif
24625  }
24626 
24627  node = elem.first_node_ns(uri<>::microsoft::types(),
24628  "AbsoluteMonthlyRecurrence");
24629  if (node)
24630  {
24631  uint32_t interval = 0U;
24632  uint32_t day_of_month = 0U;
24633 
24634  for (auto child = node->first_node(); child;
24635  child = child->next_sibling())
24636  {
24637  if (compare(child->local_name(), child->local_name_size(),
24638  "Interval", strlen("Interval")))
24639  {
24640  interval = std::stoul(
24641  std::string(child->value(), child->value_size()));
24642  }
24643  else if (compare(child->local_name(), child->local_name_size(),
24644  "DayOfMonth", strlen("DayOfMonth")))
24645  {
24646  day_of_month = std::stoul(
24647  std::string(child->value(), child->value_size()));
24648  }
24649  }
24650 
24651 #ifdef EWS_HAS_MAKE_UNIQUE
24652  return std::make_unique<absolute_monthly_recurrence>(
24653  std::move(interval), std::move(day_of_month));
24654 #else
24655  return std::unique_ptr<absolute_monthly_recurrence>(
24656  new absolute_monthly_recurrence(std::move(interval),
24657  std::move(day_of_month)));
24658 #endif
24659  }
24660 
24661  node = elem.first_node_ns(uri<>::microsoft::types(),
24662  "RelativeMonthlyRecurrence");
24663  if (node)
24664  {
24665  uint32_t interval = 0U;
24666  auto days_of_week = day_of_week::sun;
24667  auto index = day_of_week_index::first;
24668 
24669  for (auto child = node->first_node(); child;
24670  child = child->next_sibling())
24671  {
24672  if (compare(child->local_name(), child->local_name_size(),
24673  "Interval", strlen("Interval")))
24674  {
24675  interval = std::stoul(
24676  std::string(child->value(), child->value_size()));
24677  }
24678  else if (compare(child->local_name(), child->local_name_size(),
24679  "DaysOfWeek", strlen("DaysOfWeek")))
24680  {
24681  days_of_week = str_to_day_of_week(
24682  std::string(child->value(), child->value_size()));
24683  }
24684  else if (compare(child->local_name(), child->local_name_size(),
24685  "DayOfWeekIndex", strlen("DayOfWeekIndex")))
24686  {
24687  index = str_to_day_of_week_index(
24688  std::string(child->value(), child->value_size()));
24689  }
24690  }
24691 
24692 #ifdef EWS_HAS_MAKE_UNIQUE
24693  return std::make_unique<relative_monthly_recurrence>(
24694  std::move(interval), std::move(days_of_week), std::move(index));
24695 #else
24696  return std::unique_ptr<relative_monthly_recurrence>(
24697  new relative_monthly_recurrence(std::move(interval),
24698  std::move(days_of_week),
24699  std::move(index)));
24700 #endif
24701  }
24702 
24703  node = elem.first_node_ns(uri<>::microsoft::types(), "WeeklyRecurrence");
24704  if (node)
24705  {
24706  uint32_t interval = 0U;
24707  auto days_of_week = std::vector<day_of_week>();
24708  auto first_day_of_week = day_of_week::mon;
24709 
24710  for (auto child = node->first_node(); child;
24711  child = child->next_sibling())
24712  {
24713  if (compare(child->local_name(), child->local_name_size(),
24714  "Interval", strlen("Interval")))
24715  {
24716  interval = std::stoul(
24717  std::string(child->value(), child->value_size()));
24718  }
24719  else if (compare(child->local_name(), child->local_name_size(),
24720  "DaysOfWeek", strlen("DaysOfWeek")))
24721  {
24722  const auto list =
24723  std::string(child->value(), child->value_size());
24724  std::stringstream sstr(list);
24725  std::string temp;
24726  while (std::getline(sstr, temp, ' '))
24727  {
24728  days_of_week.emplace_back(str_to_day_of_week(temp));
24729  }
24730  }
24731  else if (compare(child->local_name(), child->local_name_size(),
24732  "FirstDayOfWeek", strlen("FirstDayOfWeek")))
24733  {
24734  first_day_of_week = str_to_day_of_week(
24735  std::string(child->value(), child->value_size()));
24736  }
24737  }
24738 
24739 #ifdef EWS_HAS_MAKE_UNIQUE
24740  return std::make_unique<weekly_recurrence>(
24741  std::move(interval), std::move(days_of_week),
24742  std::move(first_day_of_week));
24743 #else
24744  return std::unique_ptr<weekly_recurrence>(
24745  new weekly_recurrence(std::move(interval), std::move(days_of_week),
24746  std::move(first_day_of_week)));
24747 #endif
24748  }
24749 
24750  node = elem.first_node_ns(uri<>::microsoft::types(), "DailyRecurrence");
24751  if (node)
24752  {
24753  uint32_t interval = 0U;
24754 
24755  for (auto child = node->first_node(); child;
24756  child = child->next_sibling())
24757  {
24758  if (compare(child->local_name(), child->local_name_size(),
24759  "Interval", strlen("Interval")))
24760  {
24761  interval = std::stoul(
24762  std::string(child->value(), child->value_size()));
24763  }
24764  }
24765 
24766 #ifdef EWS_HAS_MAKE_UNIQUE
24767  return std::make_unique<daily_recurrence>(std::move(interval));
24768 #else
24769  return std::unique_ptr<daily_recurrence>(
24770  new daily_recurrence(std::move(interval)));
24771 #endif
24772  }
24773 
24774  check(false, "Expected one of "
24775  "<AbsoluteYearlyRecurrence>, <RelativeYearlyRecurrence>, "
24776  "<AbsoluteMonthlyRecurrence>, <RelativeMonthlyRecurrence>, "
24777  "<WeeklyRecurrence>, <DailyRecurrence>");
24778  return std::unique_ptr<recurrence_pattern>();
24779 }
24780 
24781 inline std::unique_ptr<recurrence_range>
24782 recurrence_range::from_xml_element(const rapidxml::xml_node<>& elem)
24783 {
24784  using rapidxml::internal::compare;
24785 
24786  check(compare(elem.local_name(), elem.local_name_size(), "Recurrence",
24787  strlen("Recurrence")),
24788  "Expected a <Recurrence> element");
24789 
24790  auto node = elem.first_node_ns(internal::uri<>::microsoft::types(),
24791  "NoEndRecurrence");
24792  if (node)
24793  {
24794  date_time start_date;
24795 
24796  for (auto child = node->first_node(); child;
24797  child = child->next_sibling())
24798  {
24799  if (compare(child->local_name(), child->local_name_size(),
24800  "StartDate", strlen("StartDate")))
24801  {
24802  start_date =
24803  date_time(std::string(child->value(), child->value_size()));
24804  }
24805  }
24806 
24807 #ifdef EWS_HAS_MAKE_UNIQUE
24808  return std::make_unique<no_end_recurrence_range>(std::move(start_date));
24809 #else
24810  return std::unique_ptr<no_end_recurrence_range>(
24811  new no_end_recurrence_range(std::move(start_date)));
24812 #endif
24813  }
24814 
24815  node = elem.first_node_ns(internal::uri<>::microsoft::types(),
24816  "EndDateRecurrence");
24817  if (node)
24818  {
24819  date_time start_date;
24820  date_time end_date;
24821 
24822  for (auto child = node->first_node(); child;
24823  child = child->next_sibling())
24824  {
24825  if (compare(child->local_name(), child->local_name_size(),
24826  "StartDate", strlen("StartDate")))
24827  {
24828  start_date =
24829  date_time(std::string(child->value(), child->value_size()));
24830  }
24831  else if (compare(child->local_name(), child->local_name_size(),
24832  "EndDate", strlen("EndDate")))
24833  {
24834  end_date =
24835  date_time(std::string(child->value(), child->value_size()));
24836  }
24837  }
24838 
24839 #ifdef EWS_HAS_MAKE_UNIQUE
24840  return std::make_unique<end_date_recurrence_range>(
24841  std::move(start_date), std::move(end_date));
24842 #else
24843  return std::unique_ptr<end_date_recurrence_range>(
24844  new end_date_recurrence_range(std::move(start_date),
24845  std::move(end_date)));
24846 #endif
24847  }
24848 
24849  node = elem.first_node_ns(internal::uri<>::microsoft::types(),
24850  "NumberedRecurrence");
24851  if (node)
24852  {
24853  date_time start_date;
24854  uint32_t no_of_occurrences = 0U;
24855 
24856  for (auto child = node->first_node(); child;
24857  child = child->next_sibling())
24858  {
24859  if (compare(child->local_name(), child->local_name_size(),
24860  "StartDate", strlen("StartDate")))
24861  {
24862  start_date =
24863  date_time(std::string(child->value(), child->value_size()));
24864  }
24865  else if (compare(child->local_name(), child->local_name_size(),
24866  "NumberOfOccurrences",
24867  strlen("NumberOfOccurrences")))
24868  {
24869  no_of_occurrences = std::stoul(
24870  std::string(child->value(), child->value_size()));
24871  }
24872  }
24873 
24874 #ifdef EWS_HAS_MAKE_UNIQUE
24875  return std::make_unique<numbered_recurrence_range>(
24876  std::move(start_date), std::move(no_of_occurrences));
24877 #else
24878  return std::unique_ptr<numbered_recurrence_range>(
24879  new numbered_recurrence_range(std::move(start_date),
24880  std::move(no_of_occurrences)));
24881 #endif
24882  }
24883 
24884  check(false,
24885  "Expected one of "
24886  "<NoEndRecurrence>, <EndDateRecurrence>, <NumberedRecurrence>");
24887  return std::unique_ptr<recurrence_range>();
24888 }
24889 } // namespace ews
Indicates that the mailbox hold was not found.
std::vector< item_id > create_item(const std::vector< message > &messages, message_disposition disposition, const folder_id &folder)
Creates new messages in the specified folder.
Definition: ews.hpp:21514
A paged view of items in a folder.
Definition: ews.hpp:20332
This class allows HTTP basic authentication.
Definition: ews.hpp:8210
Represents the admin audit logs folder.
This error is intended for internal use only.
void set_categories(const std::vector< std::string > &categories)
Sets this item&#39;s categories.
Definition: ews.hpp:13758
Negates the boolean value of the search expression it contains.
Definition: ews.hpp:20178
Abstract base class for all recurrence ranges.
Definition: ews.hpp:17602
void set_sensitivity(sensitivity s)
Sets the sensitivity level of this item.
Definition: ews.hpp:13624
std::vector< calendar_item > get_calendar_items(const std::vector< item_id > &ids, const item_shape &shape=item_shape())
Gets a bunch of calendar items from the Exchange store at once.
Definition: ews.hpp:21102
std::string get_time_zone() const
Returns the display name for the time zone associated with this calendar item.
Definition: ews.hpp:18129
permission_level
Specifies the delegate permission-level settings for a user.
Definition: ews.hpp:14343
This error occurs when attempts to save the item or folder fail.
calendar_item_type
The CalendarItemType class represents an Exchange calendar item.
Definition: ews.hpp:6975
This error occurs when the mailbox quota is exceeded.
This error occurs when an invalid SID is passed in a request.
date_time get_date_time_created() const
Returns the date/time this item was created.
Definition: ews.hpp:13897
Specifies that the client was disconnected.
This error Indicates that a calendar item has been canceled.
Compare a property with a constant or another property.
Definition: ews.hpp:19922
item_id update_item(item_id id, update change, conflict_resolution resolution, send_meeting_invitations_or_cancellations invitations_or_cancellations, const folder_id &folder)
Update an existing item&#39;s property in the specified folder.
Definition: ews.hpp:21772
std::string get_net_show_url() const
Returns a URL for Microsoft NetShow online meeting.
Definition: ews.hpp:18422
static attachment from_item(const item &the_item, const std::string &name)
Creates a new <ItemAttachment> from a given item.
Definition: ews.hpp:24351
std::vector< item_id > create_item(const std::vector< contact > &contacts)
Creates new contacts from the given vector in the Exchange store.
Definition: ews.hpp:21366
Identifies individual members of a dictionary property by an URI and index.
Definition: ews.hpp:18880
int get_appointment_sequence_number() const
Returns the sequence number of this meetings version.
Definition: ews.hpp:18146
autodiscover_result get_exchange_web_services_url(const std::string &user_smtp_address, const basic_credentials &credentials)
Returns the EWS URL by querying the Autodiscover service.
Definition: ews.hpp:9142
The response will return the richest available content.
This error occurs if the offset for indexed paging is negative.
std::string to_xml() const
Serializes this item_id to an XML string.
Definition: ews.hpp:9216
void set_given_name(const std::string &given_name)
Definition: ews.hpp:16281
Meeting is accepted.
Should not be used.
const date_time & get_last_response_time() const EWS_NOEXCEPT
Returns the date and time of the latest response that was received.
Definition: ews.hpp:12758
std::string get_mileage() const
Returns the distance to the reference point.
Definition: ews.hpp:16771
void set_internet_message_id(const std::string &value)
Sets the Message-ID: header field of this email message.
Definition: ews.hpp:18645
std::string to_folder_xml() const
Serializes this update instance to an XML string for folder operations.
Definition: ews.hpp:20522
calendar_item(item_id id)
Creates a <CalendarItem> with given id.
Definition: ews.hpp:17829
Compare a property with a constant or another property.
Definition: ews.hpp:19961
task(item_id id)
Constructs a new task with the given item_id.
Definition: ews.hpp:14986
const date_time & get_proposed_end() const EWS_NOEXCEPT
Returns the date and time that was proposed as the end by the attendee.
Definition: ews.hpp:12779
Represents recurrence range with no end date.
Definition: ews.hpp:17659
std::string get_location() const
Returns the location where a meeting or event is supposed to take place.
Definition: ews.hpp:17923
This error must be returned when the server cannot empty a folder.
ssl_options
Definition: ews.hpp:20619
void set_net_show_url(const std::string &url)
Sets the URL for Microsoft NetShow online meeting.
Definition: ews.hpp:18432
search_scope
Identifies the order and scope for a ResolveNames search.
Definition: ews.hpp:7350
basic_service(const std::string &server_uri, const internal::credentials &creds, const std::string &cainfo, const std::string &capath, const std::string &proxy_uri, const bool is_http_proxy_tunneling, const debug_callback &callback, const ssl_options ssl_opts=ssl_options::none)
Constructs a new service with given credentials to a server specified by server_uri.
Definition: ews.hpp:20751
void set_subject(const std::string &subject)
Sets this item&#39;s subject. Limited to 255 characters.
Definition: ews.hpp:13604
This error occurs if the ReferenceItemId is missing.
This error occurs when the account in question has been disabled.
std::vector< std::string > get_companies() const
Returns the companies associated with this task.
Definition: ews.hpp:15060
Renders a <DistinguishedFolderId> element.
Definition: ews.hpp:9879
Represents the Favorites folder.
Allows you to express a boolean And operation between two search expressions.
Definition: ews.hpp:20121
The third occurrence of a day within a month.
bool none() const EWS_NOEXCEPT
True if this occurrence_info is undefined.
Definition: ews.hpp:17042
date_time get_complete_date() const
Returns the time the task was completed.
Definition: ews.hpp:15075
The Search Folders folder, also known as the Finder folder.
Represents a ConnectingSID element.
Definition: ews.hpp:20555
rapidxml::xml_node & to_xml_element(rapidxml::xml_node<> &parent) const
Creates a new XML element for this recurrence pattern and appends it to given parent node...
Definition: ews.hpp:17142
const std::string & field_uri() const EWS_NOEXCEPT
Returns the value of the <FieldURI> element.
Definition: ews.hpp:18772
void set_bcc_recipients(const std::vector< mailbox > &recipients)
Sets the recipients that will receive a blind carbon copy of the message to recipients.
Definition: ews.hpp:18592
The item has a normal sensitivity.
std::vector< mailbox > get_rooms(const mailbox &room_list)
Gets all rooms from a room list in the Exchange store.
Definition: ews.hpp:20977
date_time get_reminder_due_by() const
Returns the due date of this item.
Definition: ews.hpp:13917
Represents the IM contact list folder.
void set_middle_name(const std::string &middle_name)
Set the middle name for the contact.
Definition: ews.hpp:16305
static calendar_item from_xml_element(const rapidxml::xml_node<> &elem)
Makes a calendar item instance from a <CalendarItem> XML element.
Definition: ews.hpp:18438
mailbox get_from() const
Returns the From: header field of this message.
Definition: ews.hpp:18603
void set_end(const date_time &datetime)
Sets the ending date and time for this calendar item.
Definition: ews.hpp:17857
importance
This enumeration indicates the importance of an item.
Definition: ews.hpp:7281
This error indicates that the ID and/or change key is malformed.
response_class
The ResponseClass attribute of a ResponseMessage.
Definition: ews.hpp:415
time_zone get_start_time_zone()
Returns the time zone for the starting date and time.
Definition: ews.hpp:18281
Represents a generic <Item> in the Exchange store.
Definition: ews.hpp:13550
The Contacts folder.
Base-class for all exceptions thrown by this library.
Definition: ews.hpp:428
Represents a generic <Folder> in the Exchange store.
Definition: ews.hpp:13438
send_meeting_cancellations
Describes how a meeting will be canceled.
Definition: ews.hpp:6813
Raised when a response from a server could not be parsed.
Definition: ews.hpp:444
void set_time_zone(const time_zone time_zone)
Sets the time zone ID used in the header of the request made by this service.
Definition: ews.hpp:20810
This error occurs when the SavedItemFolderId is not found.
The Outbox folder.
Contains all classes, functions, and enumerations of this library.
Definition: ews.hpp:83
void send_item(const std::vector< item_id > &ids)
Definition: ews.hpp:21529
The Deleted Items folder.
void set_reply_to(const std::vector< mailbox > &recipients)
Sets the addresses to which replies to this message should be sent.
Definition: ews.hpp:18679
This error occurs when a contact in your mailbox is corrupt.
void set_profession(const std::string &profession)
Sets the occupation or discipline of the contact.
Definition: ews.hpp:16793
The task is new and the request has been sent, but the delegate has no yet responded to the task...
void set_body(const body &b)
Sets the body of this item.
Definition: ews.hpp:13630
The comparison is between the string prefix and the constant.
This error indicates that the sharing message is not supported.
void set_resources(const std::vector< attendee > &resources) const
Sets the scheduled resources of this meeting.
Definition: ews.hpp:18073
item_id create_item(const contact &the_contact, const folder_id &folder)
Creates a new contact from the given object in the specified folder.
Definition: ews.hpp:21357
Should not be used.
void set_surname(const std::string &surname)
Definition: ews.hpp:16818
The item is personal.
occurrence_item_id(const item_id &item_id, int instance_index)
Constructs an <OccurrenceItemId> from a given item_id instance.
Definition: ews.hpp:9278
paging_base_point
Defines the base point for paged searches with <FindItem> and <FindFolder>.
Definition: ews.hpp:5577
std::string get_meeting_workspace_url() const
Returns the URL for a meeting workspace.
Definition: ews.hpp:18406
This error indicates that a calendar item has been canceled.
void set_new_time_proposal_allowed(bool allowed)
If set to true, allows attendees to respond to the organizer with new time suggestions.
Definition: ews.hpp:18384
item_id update_item(item_id id, update change, conflict_resolution resolution=conflict_resolution::auto_resolve, send_meeting_invitations_or_cancellations invitations_or_cancellations=send_meeting_invitations_or_cancellations::send_to_none)
Update an existing item&#39;s property.
Definition: ews.hpp:21745
A weekly recurrence.
Definition: ews.hpp:17469
body_type
Specifies the type of a <Body> element.
Definition: ews.hpp:12573
The response type is unknown.
bool is_submitted() const
True if this item has been submitted for delivery.
Definition: ews.hpp:13820
void set_http_proxy_tunnel(const bool value)
Activate or deactivates HTTP proxy tunneling.
Definition: ews.hpp:20836
December.
void set_start_time_zone(time_zone tz)
Sets the time zone for the starting date and time.
Definition: ews.hpp:18271
void delete_contact(contact &&the_contact)
Delete a contact from the Exchange store.
Definition: ews.hpp:21241
static user_id from_primary_smtp_address(std::string primary_smtp_address)
Creates a user_id from a given SMTP address.
Definition: ews.hpp:14202
occurrence_item_id(const item_id &item_id)
Constructs an <OccurrenceItemId> from a given item_id instance.
Definition: ews.hpp:9270
The item is private.
Specifies a time interval.
Definition: ews.hpp:12535
std::vector< mailbox > get_bcc_recipients() const
Returns the Bcc: recipients of this message.
Definition: ews.hpp:18582
This error occurs if you try to move a distinguished folder.
This error indicates that the destination folder does not exist.
The second occurrence of a day within a month.
The user doesn&#39;t have a valid license.
Compare a property with a constant or another property.
Definition: ews.hpp:20080
item_id move_item(item_id item, const folder_id &folder)
Moves one item to a folder.
Definition: ews.hpp:21867
void set_company_name(const std::string &company_name)
Sets the company that the contact is affiliated with.
Definition: ews.hpp:16340
date_time get_due_date() const
Returns the date that the task is due.
Definition: ews.hpp:15142
std::vector< item_id > create_item(const std::vector< calendar_item > &calendar_items, send_meeting_invitations send_invitations=send_meeting_invitations::send_to_none)
Creates new calendar items from the given vector in the Exchange store.
Definition: ews.hpp:21422
void set_location(const std::string &location)
Sets the location where a meeting or event is supposed to take place.
Definition: ews.hpp:17930
void set_start(const date_time &datetime)
Sets the starting date and time for this calendar item.
Definition: ews.hpp:17845
std::string content_id() const
Returns the attachement&#39;s content ID.
Definition: ews.hpp:11028
std::vector< folder > get_folders(const std::vector< folder_id > &ids)
Gets a list of folders from the Exchange store.
Definition: ews.hpp:21052
const item_id & root_item_id() const EWS_NOEXCEPT
Returns the item_id of the parent or root item.
Definition: ews.hpp:9388
std::string get_manager() const
Returns the name of the contact&#39;s manager.
Definition: ews.hpp:16758
This error indicates that there is a time zone error.
item_id create_item(const message &the_message, message_disposition disposition)
Creates a new message in the Exchange store.
Definition: ews.hpp:21460
extended_property(extended_field_uri ext_field_uri, std::vector< std::string > values)
Constructor to initialize an <ExtendedProperty> with the necessary values.
Definition: ews.hpp:13348
The Voicemail folder.
Target the schema files for Exchange 2010 Service Pack 1 (SP1)
std::vector< delegate_user > add_delegate(const mailbox &mailbox, const std::vector< delegate_user > &delegates)
Add new delegates to given mailbox.
Definition: ews.hpp:21909
folder_id create_folder(const folder &new_folder, const folder_id &parent_folder)
Create a new folder in the Exchange store.
Definition: ews.hpp:21282
bool valid() const EWS_NOEXCEPT
Whether this item_id is expected to be valid.
Definition: ews.hpp:9213
date_time get_date_time_received() const
Date/Time an item was received.
Definition: ews.hpp:13736
date_time get_date_time_sent() const
Returns the date/time this item was sent.
Definition: ews.hpp:13889
Describes a daily recurring event.
Definition: ews.hpp:17557
bool empty() const EWS_NOEXCEPT
Whether the resolution_set has no elements.
Definition: ews.hpp:9735
bool none() const EWS_NOEXCEPT
True if this mailbox is undefined.
Definition: ews.hpp:9484
std::vector< item_id > create_item(const std::vector< contact > &contacts, const folder_id &folder)
Creates new contacts from the given vector in the specified folder.
Definition: ews.hpp:21378
Specifies that there are duplicate SOAP headers.
This error occurs when the request stream is larger than 400 KB.
Definition: ews.hpp:7216
void set_display_name(const std::string &display_name)
Sets this folders display name.
Definition: ews.hpp:13467
std::string get_spouse_name() const
Get name of the contact&#39;s significant other.
Definition: ews.hpp:16811
Check if a text property contains a sub-string.
Definition: ews.hpp:20296
High importance.
int get_percent_complete() const
Returns the percentage of the task that has been completed.
Definition: ews.hpp:15212
std::vector< item_id > create_item(const std::vector< task > &tasks, const folder_id &folder)
Creates new tasks from the given vector in the the specified folder.
Definition: ews.hpp:21335
This error MUST be returned when event notifications are missed.
containment_comparison
This enumeration determines how case and non-spacing characters are considered when evaluating a text...
Definition: ews.hpp:20257
void set_culture(const std::string &culture)
Sets the culture name associated with the body of this item.
Definition: ews.hpp:14048
This response code is not used.
void set_meeting_time_zone(time_zone tz)
Sets the time zone for the meeting date and time.
Definition: ews.hpp:18323
This error occurs when the SMTP address cannot be parsed.
occurrence_info get_first_occurrence() const
Returns the first occurrence.
Definition: ews.hpp:18211
bool meeting_request_was_sent() const
True if a meeting request for this calendar item has been sent to all attendees.
Definition: ews.hpp:17975
This response code is not used.
delete_type
Describes how items are deleted from the Exchange store.
Definition: ews.hpp:6712
Exception for libcurl related runtime errors.
Definition: ews.hpp:7710
A message item in the Exchange store.
Definition: ews.hpp:18506
std::string get_mime_content() const
Returns the attachment&#39;s mime content.
Definition: ews.hpp:10964
Compare a property with a constant or another property.
Definition: ews.hpp:20000
Represents a numbered recurrence range.
Definition: ews.hpp:17760
int get_conference_type() const
Returns the type of conferencing that is performed with this calendar item.
Definition: ews.hpp:18356
occurrence_info get_last_occurrence() const
Returns the last occurrence.
Definition: ews.hpp:18222
bool is_recurring() const
True if the task is recurring.
Definition: ews.hpp:15172
void set_companies(const std::vector< std::string > &companies)
A collection of companies a contact is associated with.
Definition: ews.hpp:16632
conflict_resolution
The type of conflict resolution to try during an UpdateItem method call.
Definition: ews.hpp:6852
bool get_receive_copies_of_meeting_messages() const EWS_NOEXCEPT
Returns whether this delegate receives copies of meeting-related messages that are addressed to the o...
Definition: ews.hpp:14411
std::vector< mailbox > get_to_recipients() const
Returns the recipients of this message.
Definition: ews.hpp:18551
std::string to_xml() const
Serializes this occurrence_item_id to an XML string.
Definition: ews.hpp:9306
void set_cainfo(const std::string &path)
Sets the path to file holding certificates.
Definition: ews.hpp:20858
void set_office_location(const std::string &office_location)
Sets the location of the contact&#39;s office.
Definition: ews.hpp:16777
std::string get_subject() const
Returns this item&#39;s subject.
Definition: ews.hpp:13610
static task from_xml_element(const rapidxml::xml_node<> &elem)
Makes a task instance from a <Task> XML element.
Definition: ews.hpp:15316
This response code is not used.
std::vector< email_address > get_email_addresses() const
A collection of email addresses for the contact.
Definition: ews.hpp:16352
resolution_set resolve_names(const std::string &unresolved_entry, search_scope scope, const std::vector< folder_id > &parent_folder_ids)
The ResolveNames operation resolves ambiguous email addresses and display names.
Definition: ews.hpp:22108
Indicates that the item was invalid for an ArchiveItem operation.
This error is intended for internal use only.
Compare a property with a constant or another property.
Definition: ews.hpp:19878
Represents the directory folder.
const std::string & error_details() const EWS_NOEXCEPT
More detailed information about the error.
Definition: ews.hpp:7724
std::vector< std::string > get_contacts() const
Returns a list of contacts associated with this task.
Definition: ews.hpp:15081
operation
Definition: ews.hpp:20459
Identifies frequently referenced properties by an URI.
Definition: ews.hpp:18750
const std::string & routing_type() const EWS_NOEXCEPT
Returns the routing type.
Definition: ews.hpp:9500
void set_when(const std::string &desc)
Sets a description of when this calendar item occurs.
Definition: ews.hpp:17939
const std::string & id() const EWS_NOEXCEPT
Definition: ews.hpp:9378
Represents a concrete task in the Exchange store.
Definition: ews.hpp:14976
std::vector< std::string > get_categories() const
Returns the categories associated with this item.
Definition: ews.hpp:13776
The Journal folder.
const char * bytes() const EWS_NOEXCEPT
Note: the pointer to the data is not 0-terminated.
Definition: ews.hpp:12696
calendar_item_type get_calendar_item_type() const
Returns the type of this calendar item.
Definition: ews.hpp:17991
free_busy_status
Gets the free/busy status that is associated with the event.
Definition: ews.hpp:6923
This error indicates that mail tips are disabled.
std::string get_display_to() const
Returns a nice string containing all To: recipients of this item.
Definition: ews.hpp:13968
An error has occurred.
std::vector< folder_id > move_folder(const std::vector< folder_id > &folders, const folder_id &target)
Moves one or more folders to a target folder.
Definition: ews.hpp:21901
folder_id move_folder(folder_id folder, const folder_id &target)
Moves one folder to a folder.
Definition: ews.hpp:21890
void set_mileage(const std::string &mileage)
Definition: ews.hpp:16765
This error occurs when a list with added delegates cannot be saved.
The Tasks folder.
Abstract base class for all recurrence patterns.
Definition: ews.hpp:17117
The task is completed.
std::vector< item_id > find_item(const folder_id &parent_folder_id, search_expression restriction)
Sends a <FindItem/> operation to the server.
Definition: ews.hpp:21705
void set_timeout(std::chrono::seconds d)
Sets maximum time the request is allowed to take.
Definition: ews.hpp:20823
static item_id from_xml_element(const rapidxml::xml_node<> &elem)
Makes an item_id instance from an <ItemId> XML element.
Definition: ews.hpp:9223
time_zone get_meeting_time_zone()
Returns the time zone for the meeting date and time.
Definition: ews.hpp:18333
This error indicates that a calendar item has been canceled.
std::vector< mailbox > get_reply_to() const
Returns the Reply-To: address list of this message.
Definition: ews.hpp:18669
Only the Active Directory directory service is searched.
The message per folder receive quota has been exceeded.
void set_optional_attendees(const std::vector< attendee > &attendees) const
Sets the attendees not required to attend this meeting.
Definition: ews.hpp:18061
This response code is not used.
std::vector< folder > get_folders(const std::vector< folder_id > &ids, const std::vector< property_path > &additional_properties)
Gets a list of folders from Exchange store.
Definition: ews.hpp:21059
std::string get_contact_source() const
Indicates whether this is a directory or a store contact.
Definition: ews.hpp:16645
The comparison is between a prefix on individual words in the string and the constant.
std::string get_internet_message_id() const
Returns the Message-ID: header field of this email message.
Definition: ews.hpp:18631
folder get_folder(const folder_id &id, const std::vector< property_path > &additional_properties)
Gets a folder from the Exchange store.
Definition: ews.hpp:21044
void set_reminder_due_by(const date_time &due_by)
Sets the due date of this item.
Definition: ews.hpp:13909
This error is intended for internal use only.
time_zone get_end_time_zone()
Returns the time zone for the ending date and time.
Definition: ews.hpp:18307
distinguished_folder_id(standard_folder folder, mailbox owner)
Constructor for EWS delegate access.
Definition: ews.hpp:9915
The quick contacts folder.
message_disposition
<CreateItem> and <UpdateItem> methods use this attribute. Only applicable to email messages ...
Definition: ews.hpp:6890
std::vector< delegate_user > get_delegate(const mailbox &mailbox, bool include_permissions=false)
Retrieves the delegate users and settings for the specified mailbox.
Definition: ews.hpp:21935
void set_debug_callback(const debug_callback &callback)
Sets the callback for debug messages.
Definition: ews.hpp:20876
Raised when an assertion fails.
Definition: ews.hpp:436
base_shape
Specifies the set of properties that a GetItem or GetFolder method call will return.
Definition: ews.hpp:6675
contact get_contact(const item_id &id, const item_shape &shape=item_shape())
Gets a contact from the Exchange store.
Definition: ews.hpp:21080
bool is_meeting() const
Indicates whether this calendar item is a meeting.
Definition: ews.hpp:17947
static attachment from_base64(const std::string &content, std::string content_type, std::string name)
Creates a new <FileAttachment> from a given base64 string.
Definition: ews.hpp:11112
std::string get_generation() const
Returns the generation of the contact.
Definition: ews.hpp:16670
The Inbox folder.
Represents a single delegate.
Definition: ews.hpp:14339
std::string get_department() const
Return the department name of the contact.
Definition: ews.hpp:16657
This error is intended for internal use only.
Exception thrown when a HTTP request was not successful.
Definition: ews.hpp:7650
bool is_response_requested() const
Indicates whether a response to a calendar item is needed.
Definition: ews.hpp:17983
body(std::string content, body_type type=body_type::plain_text)
Creates a new body element with given content and type.
Definition: ews.hpp:12618
bool has_attachments() const
True if this item has non-hidden attachments.
Definition: ews.hpp:13976
sync_folder_hierarchy_result sync_folder_hierarchy(const folder_id &folder_id)
Synchronizes the folder hierarchy in the Exchange store.
Definition: ews.hpp:21000
month
Describes the month when a yearly recurring item occurs.
Definition: ews.hpp:14653
const std::string & change_key() const EWS_NOEXCEPT
Returns the change key.
Definition: ews.hpp:9210
date_time get_start_date() const
Returns the date that work on the task should start.
Definition: ews.hpp:15244
std::string content() const
Returns the attachment&#39;s contents.
Definition: ews.hpp:11002
The item is removed immediately from the user&#39;s mailbox.
response_code
Response code enum describes status information about a request.
Definition: ews.hpp:548
std::vector< task > get_tasks(const std::vector< item_id > &ids, const item_shape &shape=item_shape())
Gets multiple tasks from the Exchange store.
Definition: ews.hpp:21073
void set_start_date(const date_time &start_date)
Set the date that work on the task should start.
Definition: ews.hpp:15238
This response code is not used.
void set_ssl_options(const ssl_options value)
Sets the SSL options.
Definition: ews.hpp:20870
Represents a <FileAttachment> or an <ItemAttachment>
Definition: ews.hpp:10925
attachment get_attachment(const attachment_id &id, bool include_mime_content=false)
Retrieves an attachment from the Exchange store.
Definition: ews.hpp:22029
static date_time from_epoch(time_t epoch)
Definition: ews.hpp:12427
const std::string & change_key() const EWS_NOEXCEPT
Returns the change key.
Definition: ews.hpp:9297
The unique identifier and change key of an item in the Exchange store.
Definition: ews.hpp:9186
free_busy_status get_legacy_free_busy_status() const
Returns the free/busy status of this calendar item.
Definition: ews.hpp:17883
std::string get_business_homepage() const
Returns the URL of the contact.
Definition: ews.hpp:16615
item_id create_item(const calendar_item &the_calendar_item, send_meeting_invitations send_invitations=send_meeting_invitations::send_to_none)
Creates a new calendar item from the given object in the Exchange store.
Definition: ews.hpp:21391
void set_generation(const std::string &generation)
Definition: ews.hpp:16664
Definition: ews.hpp:14138
Allows you to express a logical Or operation between two search expressions.
Definition: ews.hpp:20150
This error is for internal use only. This error is not returned.
Indicates an organizer response type.
bool is_resend() const
True if this item a re-send.
Definition: ews.hpp:13844
Represents the actual content of a message.
Definition: ews.hpp:12611
std::string get_assistant_name() const
Returns the contact&#39;s assistant&#39;s name.
Definition: ews.hpp:16585
This error occurs if the object type changed.
This error is intended for internal use only.
std::string name() const
Returns the attachment&#39;s name.
Definition: ews.hpp:10952
std::vector< folder_id > find_folder(const folder_id &parent_folder_id)
Sends a <FindFolder/> operation to the server.
Definition: ews.hpp:21602
Indicates that the extension was not found.
Non-spacing characters will be ignored during comparison.
Target the schema files for Exchange 2010.
std::vector< item_id > create_item(const std::vector< message > &messages, message_disposition disposition)
Creates new messages in the Exchange store.
Definition: ews.hpp:21498
calendar_item get_calendar_item(const item_id &id, const item_shape &shape=item_shape())
Gets a calendar item from the Exchange store.
Definition: ews.hpp:21094
The item is confidential.
The task was declined by the delegate.
This error indicates that a calendar item has been canceled.
distinguished_folder_id(standard_folder folder, std::string change_key)
Creates a <DistinguishedFolderId> element for a given well-known folder and change key...
Definition: ews.hpp:9897
static extended_field_uri from_xml_element(const rapidxml::xml_node<> &elem)
Converts an xml string into a extended_field_uri property.
Definition: ews.hpp:13139
The conversation history folder.
item_id create_item(const message &the_message, message_disposition disposition, const folder_id &folder)
Creates a new message in the specified folder.
Definition: ews.hpp:21476
int get_appointment_state() const
Returns the status of this meeting.
Definition: ews.hpp:18165
This error indicates that the given domain cannot be found.
response_type get_my_response_type() const
Returns the response of this calendar item&#39;s owner to the meeting.
Definition: ews.hpp:18018
bool valid() const EWS_NOEXCEPT
Whether this attachment_id is valid.
Definition: ews.hpp:9391
message()
Constructs a new message object.
Definition: ews.hpp:18513
The root of the mailbox.
int instance_index() const EWS_NOEXCEPT
Returns the instance index.
Definition: ews.hpp:9300
This error is for internal use only. This error is not returned.
Compare a property with a constant or another property.
Definition: ews.hpp:20041
void set_children(const std::vector< std::string > &children)
A collection of children&#39;s names associated with the contact.
Definition: ews.hpp:16621
The todo search folder.
Target the schema files for Exchange 2013 Service Pack 1 (SP1)
The root of the folder hierarchy in the archive mailbox.
Identifies a folder.
Definition: ews.hpp:9800
Return only the item or folder ID.
std::string get_given_name() const
Returns the person&#39;s first name.
Definition: ews.hpp:16287
void set_assistant_name(const std::string &assistant_name)
Sets the name of the contact&#39;s assistant.
Definition: ews.hpp:16579
bool is_complete() const
True if the task is marked as complete.
Definition: ews.hpp:15166
std::vector< folder_id > create_folder(const std::vector< folder > &new_folders, const folder_id &parent_folder)
Create a new folder in the Exchange store.
Definition: ews.hpp:21294
void delete_message(message &&the_message)
Delete a message item from the Exchange store.
Definition: ews.hpp:21259
This error occurs when the MIME content is invalid.
An event that occurs annually relative to a month, week, and day.
Definition: ews.hpp:17393
This class allows NTLM authentication.
Definition: ews.hpp:8235
const mailbox & get_mailbox() const EWS_NOEXCEPT
Returns this attendee&#39;s email address.
Definition: ews.hpp:12743
This error occurs when the server is busy.
std::vector< mailbox > get_cc_recipients() const
Returns the Cc: recipients of this message.
Definition: ews.hpp:18566
void set_up() EWS_NOEXCEPT
Definition: ews.hpp:9121
item()
Constructs a new item.
Definition: ews.hpp:13557
day_of_week
Describes working days.
Definition: ews.hpp:14787
void delete_task(task &&the_task, delete_type del_type=delete_type::hard_delete, affected_task_occurrences affected=affected_task_occurrences::all_occurrences)
Delete a task item from the Exchange store.
Definition: ews.hpp:21231
standard_folder
Well known folder names enumeration. Usually rendered to XML as <DistinguishedFolderId> element...
Definition: ews.hpp:7068
const std::string & value() const EWS_NOEXCEPT
Returns the email address.
Definition: ews.hpp:9490
bool is_team_task() const
True if the task is a team task.
Definition: ews.hpp:15180
void set_capath(const std::string &path)
Sets the path to the certificates directory.
Definition: ews.hpp:20864
std::string to_item_xml() const
Serializes this update instance to an XML string for item operations.
Definition: ews.hpp:20503
std::string get_profession() const
Returns the occupation of the contact.
Definition: ews.hpp:16799
mime_content(std::string charset, const char *const ptr, size_t len)
Copies len bytes from ptr into an internal buffer.
Definition: ews.hpp:12687
bool is_inline() const
Returns true if the attachment is inlined.
Definition: ews.hpp:11035
Exception thrown when a request was not successful.
Definition: ews.hpp:7508
void set_importance(importance i)
Sets the importance of the item.
Definition: ews.hpp:13795
size_t get_size() const
Size in bytes of an item.
Definition: ews.hpp:13745
The Junk E-mail folder.
static contact from_xml_element_without_item_id(const rapidxml::xml_node<> &elem)
Definition: ews.hpp:16897
Apply an operation only to the specified occurrence.
This response code is not used.
The item is an occurrence of a recurring calendar item.
void set_last_response_time(const date_time &time)
Sets the date and time fo the latest response that was received.
Definition: ews.hpp:12764
Base-class for all search expressions.
Definition: ews.hpp:19762
void tear_down() EWS_NOEXCEPT
Definition: ews.hpp:9129
void send_item(const item_id &id)
Definition: ews.hpp:21524
delegation_state
Describes the state of a delegated task.
Definition: ews.hpp:14564
folder get_folder(const folder_id &id)
Gets a folder from the Exchange store.
Definition: ews.hpp:21038
std::string get_culture() const
Returns the culture name associated with the body of this item.
Definition: ews.hpp:14054
std::vector< internet_message_header > get_internet_message_headers() const
Returns a collection of Internet message headers associated with this item.
Definition: ews.hpp:13863
date_time get_end() const
Returns the ending date and time for this calendar item.
Definition: ews.hpp:17851
static std::string well_known_name(standard_folder enumeration)
Returns the well-known name for given standard_folder as string.
Definition: ews.hpp:10092
std::vector< attendee > get_required_attendees() const
Returns all attendees required to attend this meeting.
Definition: ews.hpp:18043
std::vector< occurrence_info > get_modified_occurrences() const
Returns the modified occurrences.
Definition: ews.hpp:18233
The task is waiting on other.
std::string get_middle_name() const
Returns the middle name of the contact.
Definition: ews.hpp:16311
A SOAP fault occurred due to a bad request.
Definition: ews.hpp:7667
const std::string & mailbox_type() const EWS_NOEXCEPT
Returns the mailbox type.
Definition: ews.hpp:9508
send_meeting_invitations_or_cancellations
Describes how attendees will be updated when a meeting changes.
Definition: ews.hpp:6764
bool is_online_meeting() const
Returns whether this meeting is held online.
Definition: ews.hpp:18390
The task is deferred.
Represents a calendar item in the Exchange store.
Definition: ews.hpp:17819
exchange_error(response_code code)
Constructs an exchange_error from a <ResponseCode>.
Definition: ews.hpp:7512
bool is_unmodified() const
True if this item is unmodified.
Definition: ews.hpp:13852
Definition: ews.hpp:9685
static std::unique_ptr< recurrence_range > from_xml_element(const rapidxml::xml_node<> &elem)
Makes a recurrence_range instance from a <Recurrence> XML element.
Definition: ews.hpp:24782
static attachment from_file(const std::string &file_path, std::string content_type, std::string name)
Creates a new <FileAttachment> from a given file.
Definition: ews.hpp:11144
folder_id update_folder(folder_id folder_id, update change)
Update an existing folder&#39;s property.
Definition: ews.hpp:21841
Return (nearly) all properties.
const std::string & name() const EWS_NOEXCEPT
Returns the name of the mailbox user.
Definition: ews.hpp:9495
Represents the people connect folder.
Target the schema files for Exchange 2013.
rapidxml::xml_node & to_xml_element(rapidxml::xml_node<> &parent) const
Creates a new XML element for this recurrence range and appends it to given parent node...
Definition: ews.hpp:17626
std::vector< calendar_item > find_item(const calendar_view &view, const folder_id &parent_folder_id, const item_shape &shape=item_shape())
Returns all calendar items in given calendar view.
Definition: ews.hpp:21673
void set_file_as_mapping(internal::file_as_mapping maptype)
Definition: ews.hpp:16256
Contains the unique identifier of an attachment.
Definition: ews.hpp:9358
A thin wrapper around xs:dateTime formatted strings.
Definition: ews.hpp:12290
std::pair< std::unique_ptr< recurrence_pattern >, std::unique_ptr< recurrence_range > > get_recurrence() const
Returns the recurrence pattern for calendar items and meeting requests.
Definition: ews.hpp:18178
Return the default set of properties.
mailbox get_sender() const
Returns the Sender: header field of this message.
Definition: ews.hpp:18527
void set_end_time_zone(time_zone tz)
Sets the time zone of the ending date and time.
Definition: ews.hpp:18297
bool is_draft() const
True if this item is a draft.
Definition: ews.hpp:13828
The response will return an item body as HTML.
body()
Creates an empty body element; body_type is plain-text.
Definition: ews.hpp:12615
std::string get_surname() const
Definition: ews.hpp:16825
The OccurrenceItemId element identifies a single occurrence of a recurring item.
Definition: ews.hpp:9252
void set_contacts(const std::vector< std::string > &contacts)
Sets the contacts associated with this task to contacts.
Definition: ews.hpp:15087
Renders an <ItemShape> element.
Definition: ews.hpp:19579
The recipient cache folder.
std::string get_initials() const
Returns the person&#39;s initials.
Definition: ews.hpp:16299
November.
Indicates that the archive mailbox was not enabled.
static attachment from_xml_element(const rapidxml::xml_node<> &elem)
Constructs an attachment from a given XML element elem.
Definition: ews.hpp:11086
mime_content get_mime_content() const
Base64-encoded contents of the MIME stream of this item.
Definition: ews.hpp:13573
std::vector< attendee > get_optional_attendees() const
Returns all attendees not required to attend this meeting.
Definition: ews.hpp:18055
The comparison is case-insensitive.
void set_birthday(const std::string &birthday)
The contact&#39;s birthday.
Definition: ews.hpp:16598
February.
item_id update_item(item_id id, const std::vector< update > &changes, conflict_resolution resolution=conflict_resolution::auto_resolve, send_meeting_invitations_or_cancellations invitations_or_cancellations=send_meeting_invitations_or_cancellations::send_to_none)
Update multiple properties of an existing item.
Definition: ews.hpp:21795
A range view of appointments in a calendar.
Definition: ews.hpp:20396
std::string get_delegator() const
Returns the name of the user that delegated the task.
Definition: ews.hpp:15130
bool is_reminder_enabled() const
True if a reminder has been enabled on this item.
Definition: ews.hpp:13929
item_id(std::string id)
Constructs an <ItemId> from given id string.
Definition: ews.hpp:9197
basic_service(const std::string &server_uri, const internal::credentials &creds)
Constructs a new service with given credentials to a server specified by server_uri.
Definition: ews.hpp:20739
std::vector< item_id > move_item(const std::vector< item_id > &items, const folder_id &folder)
Moves one or more items to a folder.
Definition: ews.hpp:21878
void set_response_type(response_type type)
Sets the atteendee&#39;s response.
Definition: ews.hpp:12755
static contact from_xml_element(const rapidxml::xml_node<> &elem)
Makes a contact instance from a <Contact> XML element.
Definition: ews.hpp:16885
int get_adjacent_meeting_count() const
Returns the number of meetings that are adjacent to this meeting.
Definition: ews.hpp:18098
const std::string & get_value() const EWS_NOEXCEPT
Returns the value of the header field.
Definition: ews.hpp:12952
static occurrence_item_id from_xml_element(const rapidxml::xml_node<> &elem)
Definition: ews.hpp:9317
const std::string & change_key() const EWS_NOEXCEPT
Returns a string identifying a version of a folder.
Definition: ews.hpp:9825
void set_cc_recipients(const std::vector< mailbox > &recipients)
Sets the recipients that will receive a carbon copy of the message to recipients. ...
Definition: ews.hpp:18576
Definition: ews.hpp:15896
attachment_id create_attachment(const item_id &parent_item, const attachment &a)
Lets you attach a file (or another item) to an existing item.
Definition: ews.hpp:21984
folder_id get_parent_folder_id() const
Returns a unique identifier for the folder that contains this item.
Definition: ews.hpp:13590
static attendee from_xml_element(const rapidxml::xml_node<> &elem)
Makes a attendee instance from an <Attendee> XML element.
Definition: ews.hpp:12853
date_time date
A xs:date formatted string.
Definition: ews.hpp:12517
const std::string & get_name() const EWS_NOEXCEPT
Returns the name of the header field.
Definition: ews.hpp:12949
occurrence_item_id(std::string id, std::string change_key, int instance_index)
Constructs an <OccurrenceItemId> from given identifier and change key.
Definition: ews.hpp:9286
void set_actual_work(int actual_work)
Sets the actual amount of work expended on the task.
Definition: ews.hpp:15011
type
Describes whether an attachment contains a file or another item.
Definition: ews.hpp:10933
The fourth occurrence of a day within a month.
void set_nickname(const std::string &nickname)
Sets another name by which the contact is known.
Definition: ews.hpp:16317
std::string get_item_class() const
Returns the PR_MESSAGE_CLASS MAPI property (the message class) for an item.
Definition: ews.hpp:13598
void set_mileage(const std::string &mileage)
Sets the mileage associated with the task.
Definition: ews.hpp:15194
std::string get_display_name() const
Returns this folders display name.
Definition: ews.hpp:13461
sensitivity
This enumeration indicates the sensitivity of an item.
Definition: ews.hpp:7222
Access to items is prohibited.
A SOAP fault that is raised when we sent invalid XML.
Definition: ews.hpp:7683
body get_body() const
Returns the body of this item.
Definition: ews.hpp:13659
std::string get_status_description() const
Returns the status description.
Definition: ews.hpp:15289
std::string to_xml(const char *xmlns="t") const
Returns the XML serialized string of this mailbox.
Definition: ews.hpp:9522
int get_actual_work() const
Returns the actual amount of work expended on the task.
Definition: ews.hpp:14998
A yearly recurrence pattern, e.g., a birthday.
Definition: ews.hpp:17248
Allows you to perform operations on an Exchange server.
Definition: ews.hpp:20712
An attendee of a meeting or a meeting room.
Definition: ews.hpp:12727
void set_initials(const std::string &initials)
Set the Initials for the contact.
Definition: ews.hpp:16293
Represents the My Contacts folder.
void delete_folder(const folder_id &id, delete_type del_type=delete_type::hard_delete)
Delete a folder from the Exchange store.
Definition: ews.hpp:21173
bool valid() const EWS_NOEXCEPT
Whether this item_id is expected to be valid.
Definition: ews.hpp:9303
sensitivity get_sensitivity() const
Returns the sensitivity level of this item.
Definition: ews.hpp:13616
int get_total_work() const
Returns the total amount of work for this task.
Definition: ews.hpp:15295
static attachment_id from_xml_element(const rapidxml::xml_node<> &elem)
Makes an attachment_id instance from an <AttachmentId> element.
Definition: ews.hpp:9408
This response code is not used.
status
Specifies the status of a task item.
Definition: ews.hpp:14612
const std::string & id() const EWS_NOEXCEPT
Returns the identifier.
Definition: ews.hpp:9294
std::string get_display_cc() const
Returns a nice string containing all Cc: recipients of this item.
Definition: ews.hpp:13957
Definition: ews.hpp:15561
This error is caused by an invalid watermark.
This error MUST be returned if any rule does not validate.
Following are folders containing recoverable items:
date_time get_start() const
Returns the starting date and time for this calendar item.
Definition: ews.hpp:17839
static folder_id from_xml_element(const rapidxml::xml_node<> &elem)
Makes a folder_id instance from given XML element.
Definition: ews.hpp:9831
void set_due_date(const date_time &due_date)
Sets the date that the task is due.
Definition: ews.hpp:15136
void set_to_recipients(const std::vector< mailbox > &recipients)
Sets the recipients of this message to recipients.
Definition: ews.hpp:18560
std::string get_office_location() const
Returns the location of the contact&#39;s office.
Definition: ews.hpp:16783
uint32_t get_reminder_minutes_before_start() const
Returns the number of minutes before due date that a reminder should be shown to the user...
Definition: ews.hpp:13944
void set_companies(const std::vector< std::string > &companies)
Sets the companies associated with this task.
Definition: ews.hpp:15069
server_version
Defines the different values for the <RequestServerVersion> element.
Definition: ews.hpp:6583
This error is intended for internal use only.
This response code is not used.
const std::string & to_xml() const EWS_NOEXCEPT
Serializes this ConnectingSID instance to an XML string.
Definition: ews.hpp:20574
int get_conflicting_meeting_count() const
Returns the number of meetings that are in conflict with this meeting.
Definition: ews.hpp:18085
Definition: ews.hpp:16001
std::vector< mailbox > get_room_lists()
Gets all room lists in the Exchange store.
Definition: ews.hpp:20962
This error indicates that the requester is not enabled.
void set_manager(const std::string &manager)
Sets the name of the contact&#39;s manager.
Definition: ews.hpp:16752
No error occurred for the request.
void set_all_day_event_enabled(bool enabled)
Makes this calendar item an all day event or not.
Definition: ews.hpp:17877
distinguished_folder_id(standard_folder folder)
Creates a <DistinguishedFolderId> element for a given well-known folder.
Definition: ews.hpp:9890
The Notes folder.
std::vector< calendar_item > get_calendar_items(const std::vector< occurrence_item_id > &ids, const item_shape &shape=item_shape())
Gets a bunch of calendar items from the Exchange store at once.
Definition: ews.hpp:21131
bool is_all_day_event() const
True if this calendar item is lasting all day.
Definition: ews.hpp:17871
folder()
Constructs a new folder.
Definition: ews.hpp:13445
bool is_new_time_proposal_allowed() const
Returns true if attendees are allowed to respond to the organizer with new time suggestions.
Definition: ews.hpp:18373
bool get_view_private_items() const EWS_NOEXCEPT
Returns whether this delegate is allowed to view private items in the owner&#39;s mailbox.
Definition: ews.hpp:14418
void set_business_homepage(const std::string &business_homepage)
Sets the web page for the contact&#39;s business; typically a URL.
Definition: ews.hpp:16609
static standard_folder str_to_standard_folder(const std::string &name)
Returns the standard_folder enum for given string.
Definition: ews.hpp:9921
void delete_calendar_item(calendar_item &&the_calendar_item, delete_type del_type=delete_type::hard_delete, send_meeting_cancellations cancellations=send_meeting_cancellations::send_to_none)
Delete a calendar item from the Exchange store.
Definition: ews.hpp:21248
attachment_id id() const
Returns this attachment&#39;s attachment_id.
Definition: ews.hpp:10945
const std::string & violation() const EWS_NOEXCEPT
A more detailed explanation of what went wrong.
Definition: ews.hpp:7701
complete_name get_complete_name() const
A combination of several name fields in one convenient place.
Definition: ews.hpp:16329
item_id create_item(const task &the_task, const folder_id &folder)
Creates a new task from the given object in the the specified folder.
Definition: ews.hpp:21315
The root of the message folder hierarchy in the archive mailbox.
std::vector< contact > get_contacts(const std::vector< item_id > &ids, const item_shape &shape=item_shape())
Gets multiple contacts from the Exchange store.
Definition: ews.hpp:21087
The Deleted Items folder in the archive mailbox.
rapidxml::xml_node & to_xml_element(rapidxml::xml_node<> &parent) const
Creates a new <Mailbox> XML element and appends it to given parent node.
Definition: ews.hpp:9559
sync_folder_items_result sync_folder_items(const folder_id &folder_id, int max_changes_returned=512)
Synchronizes a folder in the Exchange store.
Definition: ews.hpp:21013
std::string to_xml() const
Returns this attachment serialized to XML.
Definition: ews.hpp:11083
Definition: ews.hpp:15450
std::string get_in_reply_to() const
Returns the identifier of the item to which this item is a reply.
Definition: ews.hpp:13812
The Sync Issues folder.
Indicates an error in archive folder path creation.
item_id create_item(const calendar_item &the_calendar_item, send_meeting_invitations send_invitations, const folder_id &folder)
Creates a new calendar item from the given object in the specified folder.
Definition: ews.hpp:21407
std::vector< attachment > get_attachments() const
Returns the items or files that are attached to this item.
Definition: ews.hpp:13714
void set_conference_type(int value)
Sets the type of conferencing that is performed with this calendar item.
Definition: ews.hpp:18366
bool is_read() const
Returns whether this message has been read.
Definition: ews.hpp:18651
int get_total_count() const
Returns the total number of items in this folder.
Definition: ews.hpp:13473
The task was accepted by the delegate.
void delete_item(const item_id &id, delete_type del_type=delete_type::hard_delete, affected_task_occurrences affected=affected_task_occurrences::all_occurrences, send_meeting_cancellations cancellations=send_meeting_cancellations::send_to_none)
Delete an arbitrary item from the Exchange store.
Definition: ews.hpp:21196
std::string get_nickname() const
Returns the nickname of the contact.
Definition: ews.hpp:16323
The task is not a delegated task, or the task request has been created but not sent.
The last occurrence of a day within a month.
int get_change_count() const
Returns the change count of this task.
Definition: ews.hpp:15044
void set_proposed_start(const date_time &start)
Sets the start date and time that was proposed by the attendee.
Definition: ews.hpp:12776
Definition: ews.hpp:9725
size_t write_content_to_file(const std::string &file_path) const
Write contents to a file.
Definition: ews.hpp:11055
std::string to_xml()
Returns a string representation of this extended_field_uri.
Definition: ews.hpp:13104
bool is_recurring() const
True if a calendar item is part of a recurring series.
Definition: ews.hpp:17966
static user_id from_sid(std::string sid)
Creates a user_id from a given SID.
Definition: ews.hpp:14209
std::vector< resolution >::iterator end()
Range-based for loop support.
Definition: ews.hpp:9741
std::string get_billing_information() const
Returns the billing information associated with this task.
Definition: ews.hpp:15027
std::vector< occurrence_info > get_deleted_occurrences() const
Returns the deleted occurrences.
Definition: ews.hpp:18252
Holds a subset of properties from an existing calendar item.
Definition: ews.hpp:17025
affected_task_occurrences
Indicates which occurrences of a recurring series should be deleted.
Definition: ews.hpp:6738
int get_child_folder_count() const
Returns the number of child folders in this folder.
Definition: ews.hpp:13479
folder_id get_parent_folder_id() const
Returns the id of the parent folder.
Definition: ews.hpp:13485
The comparison is between a sub-string of the string and the constant.
Apply an operation to all occurrences in the series.
The Conflicts folder.
std::vector< physical_address > get_physical_addresses() const
A collection of mailing addresses for the contact.
Definition: ews.hpp:16415
time_zone
Represents the unique identifiers of the time zones. These IDs are specific to windows and differ fro...
Definition: ews.hpp:5606
Represents recurrence range with end date.
Definition: ews.hpp:17707
Definition: ews.hpp:7210
date_time get_assigned_time() const
Returns the time this task was assigned to the current owner.
Definition: ews.hpp:15021
duration get_duration() const
Returns the duration of this meeting.
Definition: ews.hpp:18111
The first occurrence of a day within a month.
September.
response_type get_response_type() const EWS_NOEXCEPT
Returns this attendee&#39;s response.
Definition: ews.hpp:12749
void set_billing_information(const std::string &billing_info)
Sets the billing information associated with this task.
Definition: ews.hpp:15033
const std::vector< std::string > & get_values() const EWS_NOEXCEPT
Returns the values of the extended_property as a vector even it is just one.
Definition: ews.hpp:13368
void set_department(const std::string &department)
Set the department name that the contact is in.
Definition: ews.hpp:16651
The item is master for a set of recurring calendar items.
time_t to_epoch() const
Definition: ews.hpp:12314
std::string get_mileage() const
Returns the mileage associated with the task.
Definition: ews.hpp:15188
void set_proxy(const std::string &url)
Sets the URL of the proxy which should be used for connecting to the EWS service. ...
Definition: ews.hpp:20830
std::vector< item_id > create_item(const std::vector< calendar_item > &calendar_items, send_meeting_invitations send_invitations, const folder_id &folder)
Creates new calendar items from the given vector in the specified folder.
Definition: ews.hpp:21438
static occurrence_info from_xml_element(const rapidxml::xml_node<> &elem)
Makes a occurrence_info instance from a <FirstOccurrence>, <LastOccurrence>, or <Occurrence> XML elem...
Definition: ews.hpp:17057
containment_mode
Specifies which parts of a text value are compared to a supplied constant value.
Definition: ews.hpp:20208
Represents a SMTP mailbox.
Definition: ews.hpp:9455
item_id create_item(const contact &the_contact)
Creates a new contact from the given object in the Exchange store.
Definition: ews.hpp:21345
void set_proposed_end(const date_time &end)
Sets the end date and time that was proposed by the attendee.
Definition: ews.hpp:12785
The time slot is potentially filled.
folder_id update_folder(folder_id folder_id, const std::vector< update > &changes)
Update multiple properties of an existing folder.
Definition: ews.hpp:21855
Something strange but not fatal happened.
void set_recurrence(const recurrence_pattern &pattern, const recurrence_range &range)
Sets the recurrence pattern for calendar items and meeting requests.
Definition: ews.hpp:18193
Indicates that no response is received.
const date_time & get_proposed_start() const EWS_NOEXCEPT
Returns the date and time that was proposed as the start by the attendee.
Definition: ews.hpp:12770
calendar_item get_calendar_item(const occurrence_item_id &id, const item_shape &shape=item_shape())
Gets a calendar item from the Exchange store.
Definition: ews.hpp:21109
void set_request_server_version(server_version vers)
Sets the schema version that will be used in requests made by this service.
Definition: ews.hpp:20803
The Local Failures folder.
std::vector< resolution >::iterator begin()
Range-based for loop support.
Definition: ews.hpp:9738
The calendar item is updated but updates are not sent to attendee.
bool none() const EWS_NOEXCEPT
Definition: ews.hpp:12705
The Sent Items folder.
This error occurs when an invalid SID is passed in a request.
unsigned long line_position() const EWS_NOEXCEPT
Column number in request string where the error was found.
Definition: ews.hpp:7698
const std::string & id() const EWS_NOEXCEPT
Returns the identifier.
Definition: ews.hpp:9207
Low importance.
status get_status() const
Returns the status of the task.
Definition: ews.hpp:15250
The task is not started.
Can read, create, and modify items.
This error indicates that the user could not be found.
bool is_cancelled() const
Indicates whether this calendar item has been cancelled by the organizer.
Definition: ews.hpp:17956
std::string to_xml() const
Returns the XML serialized version of this attendee instance.
Definition: ews.hpp:12788
The item is moved to a dedicated "Trash" folder.
std::vector< item_id > create_item(const std::vector< task > &tasks)
Creates new tasks from the given vector in the Exchange store.
Definition: ews.hpp:21323
Represents an <InternetMessageHeader> property.
Definition: ews.hpp:12931
task get_task(const item_id &id, const item_shape &shape=item_shape())
Gets a task from the Exchange store.
Definition: ews.hpp:21067
size_t content_size() const
Returns the attachment&#39;s size in bytes.
Definition: ews.hpp:11012
message get_message(const item_id &id, const item_shape &shape=item_shape())
Gets a message item from the Exchange store.
Definition: ews.hpp:21159
Definition: ews.hpp:12188
void set_extended_property(const extended_property &extended_prop)
Sets an extended property of an item.
Definition: ews.hpp:14006
Represents an <ExtendedProperty>.
Definition: ews.hpp:13334
item_id(std::string id, std::string change_key)
Constructs an <ItemId> from given identifier and change key.
Definition: ews.hpp:9201
This error occurs if the restriction contains more than 255 nodes.
The response will return an item body as plain-text.
An update to a single property of an item.
Definition: ews.hpp:20456
importance get_importance() const
Returns the importance of this item.
Definition: ews.hpp:13801
void send_item(const item_id &id, const folder_id &folder)
Sends a message that is already in the Exchange store.
Definition: ews.hpp:21539
void set_file_as(const std::string &fileas)
How the name should be filed for display/sorting purposes.
Definition: ews.hpp:16243
This error occurs if there is no Calendar folder for the mailbox.
The time slot is open for other events.
void set_total_work(int total_work)
Sets the total amount of work for this task.
Definition: ews.hpp:15306
time_zone get_time_zone()
Returns the time zone ID currently used for the header of the request made by this service...
Definition: ews.hpp:20814
message(item_id id)
Constructs a new message object with the given id.
Definition: ews.hpp:18517
static folder from_xml_element(const rapidxml::xml_node<> &elem)
Makes a message instance from a <Message> XML element.
Definition: ews.hpp:13499
Definition: ews.hpp:12129
Represents an item&#39;s <MimeContent CharacterSet="" /> element.
Definition: ews.hpp:12677
void set_from(const ews::mailbox &m)
Sets the From: header field of this message.
Definition: ews.hpp:18614
Everything went fine.
void send_item(const std::vector< item_id > &ids, const folder_id &folder)
Sends messages that are already in the Exchange store.
Definition: ews.hpp:21567
const item_id & get_item_id() const EWS_NOEXCEPT
Returns the id of an item.
Definition: ews.hpp:13570
std::string get_company_name() const
Returns the comany of the contact.
Definition: ews.hpp:16346
std::string get_display_name() const
Returns the displayed name of the contact.
Definition: ews.hpp:16274
The item is an exception to a recurring calendar item.
std::string get_when() const
Returns a description of when this calendar item occurs.
Definition: ews.hpp:17936
connecting_sid(type, const std::string &)
Constructs a new ConnectingSID element.
Definition: ews.hpp:20609
The task is started and in progress.
This error is intended for internal use only.
item_id create_item(const task &the_task)
Creates a new task from the given object in the Exchange store.
Definition: ews.hpp:21303
This error indicates that a user&#39;s dial plan is not available.
void set_reminder_enabled(bool enabled)
Set a reminder on this item.
Definition: ews.hpp:13923
void set_status(status s)
Sets the status of the task to s.
Definition: ews.hpp:15280
This class allows OAuth2 authentification using the Ressource Owner Password Credentials grant...
Definition: ews.hpp:8280
int get_unread_count() const
Returns the number of unread items in this folder.
Definition: ews.hpp:13493
void set_im_address(const im_address &im_address)
A collection of instant messaging addresses for the contact.
Definition: ews.hpp:16677
The paged view starts at the end of the found conversation or item set.
void set_wedding_anniversary(const std::string &anniversary)
Date that the contact was married.
Definition: ews.hpp:16831
std::function< void(const std::string &)> debug_callback
Callback for debug messages.
Definition: ews.hpp:20716
The Calendar folder.
void set_sender(const ews::mailbox &m)
Sets the Sender: header field of this message.
Definition: ews.hpp:18538
void set_is_read(bool value)
Sets whether this message has been read.
Definition: ews.hpp:18660
This error indicates that a valid VoIP gateway is not available.
This class allows OAuth2 authentification using the client credentials grant type.
Definition: ews.hpp:8257
This error indicates that the specified delegate user ID is invalid.
occurrence_item_id(std::string id)
Constructs an <OccurrenceItemId> from given id string.
Definition: ews.hpp:9263
Represents the Server Failures folder.
void set_display_name(const std::string &display_name)
Sets the name to display for a contact.
Definition: ews.hpp:16268
date_time get_original_start() const
The original start time of a calendar item.
Definition: ews.hpp:17865
property(indexed_property_path path)
Definition: ews.hpp:19413
resolution_set resolve_names(const std::string &unresolved_entry, search_scope scope)
The ResolveNames operation resolves ambiguous email addresses and display names.
Definition: ews.hpp:22089
day_of_week_index
This element describes which week in a month is used in a relative recurrence pattern.
Definition: ews.hpp:14907
type get_type() const EWS_NOEXCEPT
Returns either type::file or type::item.
Definition: ews.hpp:11048
date_time get_appointment_reply_time() const
Returns the date and time when when this meeting was responded to.
Definition: ews.hpp:18138
bool is_from_me() const
True if this item is from you.
Definition: ews.hpp:13836
std::vector< message > get_messages(const std::vector< item_id > &ids, const item_shape &shape=item_shape())
Gets multiple message items from the Exchange store.
Definition: ews.hpp:21166
Indicates that the retention tag GUID was invalid.
void set_legacy_free_busy_status(free_busy_status status)
Sets the free/busy status of this calendar item.
Definition: ews.hpp:17915
The comparison is between an exact phrase in the string and the constant.
This error indicates that the caller identifier is not valid.
basic_service(const std::string &server_uri, const std::string &domain, const std::string &username, const std::string &password)
Constructs a new service with given credentials to a server specified by server_uri.
Definition: ews.hpp:20726
const std::string & character_set() const EWS_NOEXCEPT
Returns how the string is encoded, e.g., "UTF-8".
Definition: ews.hpp:12693
std::string get_job_title() const
Returns the job title for the contact.
Definition: ews.hpp:16746
exchange_error(response_code code, const std::string &message_text)
Constructs an exchange_error from a <ResponseCode> and additional error message, e.g., from an <MessageText> element.
Definition: ews.hpp:7519
An event that occurs on the same day each month or monthly interval.
Definition: ews.hpp:17319
This response code is not used.
void set_spouse_name(const std::string &spouse_name)
Set name of the contact&#39;s significant other.
Definition: ews.hpp:16805
Send the message and do not save a copy in the sender&#39;s mailbox.
std::vector< extended_property > get_extended_properties() const
Definition: ews.hpp:13983
static mailbox from_xml_element(const rapidxml::xml_node<> &elem)
Makes a mailbox instance from a <Mailbox> XML element.
Definition: ews.hpp:9608
const extended_field_uri & get_extended_field_uri() const EWS_NOEXCEPT
Definition: ews.hpp:13361
The strings must exactly be the same.
property(property_path path)
Use this constructor if you want to delete a property from an item.
Definition: ews.hpp:19409
This error occurs when the folder ID is corrupt.
Meeting is declined.
An event that occurs annually relative to a month, week, and day.
Definition: ews.hpp:17180
item_id delete_attachment(const attachment_id &id)
Deletes given attachment from the Exchange store.
Definition: ews.hpp:22062
const std::string & id() const EWS_NOEXCEPT
Returns a string identifying a folder in the Exchange store.
Definition: ews.hpp:9822
The Drafts folder.
response_type
The ResponseType element represents the type of recipient response that is received for a meeting...
Definition: ews.hpp:6994
void set_job_title(const std::string &title)
Sets this contact&#39;s job title.
Definition: ews.hpp:16740
server_version get_request_server_version() const
Returns the schema version that is used in requests by this service.
Definition: ews.hpp:20944
Represents a single property.
Definition: ews.hpp:19403
Indicates that the source folder path could not be retrieved.
std::vector< attendee > get_resources() const
Returns all scheduled resources of this meeting.
Definition: ews.hpp:18067
unsigned long line_number() const EWS_NOEXCEPT
Line number in request string where the error was found.
Definition: ews.hpp:7695
void set_meeting_workspace_url(const std::string &url)
Sets the URL for a meeting workspace.
Definition: ews.hpp:18416
bool valid() const EWS_NOEXCEPT
Whether this folder_id is valid.
Definition: ews.hpp:9828
This error occurs when the specified recurrence cannot be created.
void set_reminder_minutes_before_start(uint32_t minutes)
Sets the minutes before due date that a reminder should be shown to the user.
Definition: ews.hpp:13936
This error occurs when an invalid time zone is encountered.
Definition: ews.hpp:15344
The root of the message folder hierarchy.
mailbox get_organizer() const
Returns the organizer of this calendar item.
Definition: ews.hpp:18032
static std::unique_ptr< recurrence_pattern > from_xml_element(const rapidxml::xml_node<> &elem)
Makes a recurrence_pattern instance from a <Recurrence> XML element.
Definition: ews.hpp:24543
A contact item in the Exchange store.
Definition: ews.hpp:16224
std::string content_type() const
Returns the attachment&#39;s content type.
Definition: ews.hpp:10991
item_id update_item(item_id id, const std::vector< update > &changes, conflict_resolution resolution, send_meeting_invitations_or_cancellations invitations_or_cancellations, const folder_id &folder)
Update multiple properties of an existing item in the specified folder.
Definition: ews.hpp:21822
rapidxml::xml_node & to_xml_element(rapidxml::xml_node<> &parent) const
Creates a new <Attendee> XML element and appends it to given parent node.
Definition: ews.hpp:12815
This error occurs when the folder is corrupted and cannot be saved.
const folder_id & get_folder_id() const EWS_NOEXCEPT
Returns the id of a folder.
Definition: ews.hpp:13458
The ExtendedFieldURI element identifies an extended MAPI property.
Definition: ews.hpp:13009
Definition: ews.hpp:9709
static message from_xml_element(const rapidxml::xml_node<> &elem)
Makes a message instance from a <Message> XML element.
Definition: ews.hpp:18685
void set_required_attendees(const std::vector< attendee > &attendees) const
Sets the attendees required to attend this meeting.
Definition: ews.hpp:18049
The comparison is between the full string and the constant.
void set_online_meeting_enabled(bool enabled)
If set to true, this meeting is supposed to be held online.
Definition: ews.hpp:18400
delegation_state get_delegation_state() const
Returns the delegation state of this task.
Definition: ews.hpp:15095
void set_percent_complete(int value)
Sets the percentage of the task that has been completed.
Definition: ews.hpp:15229