Objects.h 6.6 KB

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