Objects.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * Copyright (c) 2021, Kyle Pereira <hey@xylepereira.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Format.h>
  8. #include <AK/Function.h>
  9. #include <AK/Tuple.h>
  10. #include <AK/Variant.h>
  11. #include <LibCore/DateTime.h>
  12. #include <LibCore/EventLoop.h>
  13. #include <LibCore/Object.h>
  14. #include <utility>
  15. namespace IMAP {
  16. enum class CommandType {
  17. Capability,
  18. List,
  19. Login,
  20. Logout,
  21. Noop,
  22. Select,
  23. };
  24. enum class MailboxFlag : unsigned {
  25. All = 1u << 0,
  26. Drafts = 1u << 1,
  27. Flagged = 1u << 2,
  28. HasChildren = 1u << 3,
  29. HasNoChildren = 1u << 4,
  30. Important = 1u << 5,
  31. Junk = 1u << 6,
  32. Marked = 1u << 7,
  33. NoInferiors = 1u << 8,
  34. NoSelect = 1u << 9,
  35. Sent = 1u << 10,
  36. Trash = 1u << 11,
  37. Unmarked = 1u << 12,
  38. Unknown = 1u << 13,
  39. };
  40. enum class ResponseType : unsigned {
  41. Capability = 1u << 0,
  42. List = 1u << 1,
  43. Exists = 1u << 2,
  44. Recent = 1u << 3,
  45. Flags = 1u << 4,
  46. UIDNext = 1u << 5,
  47. UIDValidity = 1u << 6,
  48. Unseen = 1u << 7,
  49. PermanentFlags = 1u << 8,
  50. Bye = 1u << 13,
  51. };
  52. class Parser;
  53. struct Command {
  54. public:
  55. CommandType type;
  56. int tag;
  57. Vector<String> args;
  58. };
  59. enum class ResponseStatus {
  60. Bad,
  61. No,
  62. OK,
  63. };
  64. struct ListItem {
  65. unsigned flags;
  66. String reference;
  67. String name;
  68. };
  69. class ResponseData {
  70. public:
  71. [[nodiscard]] unsigned response_type() const
  72. {
  73. return m_response_type;
  74. }
  75. ResponseData()
  76. : m_response_type(0)
  77. {
  78. }
  79. ResponseData(ResponseData&) = delete;
  80. ResponseData(ResponseData&&) = default;
  81. ResponseData& operator=(const ResponseData&) = delete;
  82. ResponseData& operator=(ResponseData&&) = default;
  83. [[nodiscard]] bool contains_response_type(ResponseType response_type) const
  84. {
  85. return (static_cast<unsigned>(response_type) & m_response_type) != 0;
  86. }
  87. void add_response_type(ResponseType response_type)
  88. {
  89. m_response_type = m_response_type | static_cast<unsigned>(response_type);
  90. }
  91. void add_capabilities(Vector<String>&& capabilities)
  92. {
  93. m_capabilities = move(capabilities);
  94. add_response_type(ResponseType::Capability);
  95. }
  96. Vector<String>& capabilities()
  97. {
  98. VERIFY(contains_response_type(ResponseType::Capability));
  99. return m_capabilities;
  100. }
  101. void add_list_item(ListItem&& item)
  102. {
  103. add_response_type(ResponseType::List);
  104. m_list_items.append(move(item));
  105. }
  106. Vector<ListItem>& list_items()
  107. {
  108. VERIFY(contains_response_type(ResponseType::List));
  109. return m_list_items;
  110. }
  111. void set_exists(unsigned exists)
  112. {
  113. add_response_type(ResponseType::Exists);
  114. m_exists = exists;
  115. }
  116. [[nodiscard]] unsigned exists() const
  117. {
  118. VERIFY(contains_response_type(ResponseType::Exists));
  119. return m_exists;
  120. }
  121. void set_recent(unsigned recent)
  122. {
  123. add_response_type(ResponseType::Recent);
  124. m_recent = recent;
  125. }
  126. [[nodiscard]] unsigned recent() const
  127. {
  128. VERIFY(contains_response_type(ResponseType::Recent));
  129. return m_recent;
  130. }
  131. void set_uid_next(unsigned uid_next)
  132. {
  133. add_response_type(ResponseType::UIDNext);
  134. m_uid_next = uid_next;
  135. }
  136. [[nodiscard]] unsigned uid_next() const
  137. {
  138. VERIFY(contains_response_type(ResponseType::UIDNext));
  139. return m_uid_next;
  140. }
  141. void set_uid_validity(unsigned uid_validity)
  142. {
  143. add_response_type(ResponseType::UIDValidity);
  144. m_uid_validity = uid_validity;
  145. }
  146. [[nodiscard]] unsigned uid_validity() const
  147. {
  148. VERIFY(contains_response_type(ResponseType::UIDValidity));
  149. return m_uid_validity;
  150. }
  151. void set_unseen(unsigned unseen)
  152. {
  153. add_response_type(ResponseType::Unseen);
  154. m_unseen = unseen;
  155. }
  156. [[nodiscard]] unsigned unseen() const
  157. {
  158. VERIFY(contains_response_type(ResponseType::Unseen));
  159. return m_unseen;
  160. }
  161. void set_flags(Vector<String>&& flags)
  162. {
  163. m_response_type |= static_cast<unsigned>(ResponseType::Flags);
  164. m_flags = move(flags);
  165. }
  166. Vector<String>& flags()
  167. {
  168. VERIFY(contains_response_type(ResponseType::Flags));
  169. return m_flags;
  170. }
  171. void set_permanent_flags(Vector<String>&& flags)
  172. {
  173. add_response_type(ResponseType::PermanentFlags);
  174. m_permanent_flags = move(flags);
  175. }
  176. Vector<String>& permanent_flags()
  177. {
  178. VERIFY(contains_response_type(ResponseType::PermanentFlags));
  179. return m_permanent_flags;
  180. }
  181. void set_bye(Optional<String> message)
  182. {
  183. add_response_type(ResponseType::Bye);
  184. m_bye_message = move(message);
  185. }
  186. Optional<String>& bye_message()
  187. {
  188. VERIFY(contains_response_type(ResponseType::Bye));
  189. return m_bye_message;
  190. }
  191. private:
  192. unsigned m_response_type;
  193. Vector<String> m_capabilities;
  194. Vector<ListItem> m_list_items;
  195. unsigned m_recent {};
  196. unsigned m_exists {};
  197. unsigned m_uid_next {};
  198. unsigned m_uid_validity {};
  199. unsigned m_unseen {};
  200. Vector<String> m_permanent_flags;
  201. Vector<String> m_flags;
  202. Optional<String> m_bye_message;
  203. };
  204. class SolidResponse {
  205. // Parser is allowed to set up fields
  206. friend class Parser;
  207. public:
  208. ResponseStatus status() { return m_status; }
  209. int tag() const { return m_tag; }
  210. ResponseData& data() { return m_data; }
  211. String response_text() { return m_response_text; };
  212. SolidResponse()
  213. : SolidResponse(ResponseStatus::Bad, -1)
  214. {
  215. }
  216. SolidResponse(ResponseStatus status, int tag)
  217. : m_status(status)
  218. , m_tag(tag)
  219. , m_data(ResponseData())
  220. {
  221. }
  222. private:
  223. ResponseStatus m_status;
  224. String m_response_text;
  225. unsigned m_tag;
  226. ResponseData m_data;
  227. };
  228. struct ContinueRequest {
  229. String data;
  230. };
  231. template<typename Result>
  232. class Promise : public Core::Object {
  233. C_OBJECT(Promise);
  234. private:
  235. Optional<Result> m_pending;
  236. public:
  237. Function<void(Result&)> on_resolved;
  238. void resolve(Result&& result)
  239. {
  240. m_pending = move(result);
  241. if (on_resolved)
  242. on_resolved(m_pending.value());
  243. }
  244. bool is_resolved()
  245. {
  246. return m_pending.has_value();
  247. };
  248. Result await()
  249. {
  250. while (!is_resolved()) {
  251. Core::EventLoop::current().pump();
  252. }
  253. return m_pending.release_value();
  254. }
  255. // Converts a Promise<A> to a Promise<B> using a function func: A -> B
  256. template<typename T>
  257. RefPtr<Promise<T>> map(T func(Result&))
  258. {
  259. RefPtr<Promise<T>> new_promise = Promise<T>::construct();
  260. on_resolved = [new_promise, func](Result& result) mutable {
  261. auto t = func(result);
  262. new_promise->resolve(move(t));
  263. };
  264. return new_promise;
  265. }
  266. };
  267. using Response = Variant<SolidResponse, ContinueRequest>;
  268. }
  269. // An RFC 2822 message
  270. // https://datatracker.ietf.org/doc/html/rfc2822
  271. struct Message {
  272. String data;
  273. };