tdiary 5.4.0 → 5.5.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (641) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +25 -2
  3. data/Gemfile.lock +211 -61
  4. data/README.md +4 -4
  5. data/doc/HOWTO-make-plugin.md +1 -1
  6. data/doc/HOWTO-testing-tDiary.md +2 -2
  7. data/doc/INSTALL-cgi.md +7 -0
  8. data/doc/INSTALL-paas.md +11 -11
  9. data/doc/INSTALL.md +2 -2
  10. data/doc/README.en.md +1 -1
  11. data/doc/README.md +1 -1
  12. data/lib/aws/pa_api.rb +6 -2
  13. data/lib/tdiary/admin.rb +6 -4
  14. data/lib/tdiary/application.rb +17 -17
  15. data/lib/tdiary/author_only_base.rb +6 -13
  16. data/lib/tdiary/base.rb +52 -16
  17. data/lib/tdiary/cgi_adapter.rb +86 -0
  18. data/lib/tdiary/cgi_compat.rb +189 -0
  19. data/lib/tdiary/configuration.rb +1 -1
  20. data/lib/tdiary/core_ext.rb +4 -53
  21. data/lib/tdiary/diary_container.rb +23 -11
  22. data/lib/tdiary/dispatcher/index_main.rb +16 -16
  23. data/lib/tdiary/dispatcher/update_main.rb +16 -16
  24. data/lib/tdiary/dispatcher.rb +4 -28
  25. data/lib/tdiary/environment.rb +12 -0
  26. data/lib/tdiary/filter.rb +5 -2
  27. data/lib/tdiary/io/pstore.rb +6 -3
  28. data/lib/tdiary/plugin/00default.rb +10 -14
  29. data/lib/tdiary/plugin/05referer.rb +6 -6
  30. data/lib/tdiary/plugin/60sf.rb +1 -1
  31. data/lib/tdiary/plugin.rb +76 -16
  32. data/lib/tdiary/request.rb +11 -353
  33. data/lib/tdiary/tasks/db.rake +17 -4
  34. data/lib/tdiary/tasks/heroku.rake +9 -0
  35. data/lib/tdiary/tasks/release.rake +126 -146
  36. data/lib/tdiary/version.rb +1 -1
  37. data/lib/tdiary/view.rb +3 -3
  38. data/lib/tdiary.rb +3 -1
  39. data/misc/convert2.rb +3 -0
  40. data/misc/migrate.rb +3 -0
  41. data/misc/plugin/a.rb +1 -6
  42. data/misc/plugin/amazon.rb +5 -4
  43. data/misc/plugin/calendar2.rb +1 -1
  44. data/misc/plugin/en/disp_referrer.rb +1 -1
  45. data/misc/plugin/ja/disp_referrer.rb +1 -1
  46. data/misc/plugin/kw.rb +2 -21
  47. data/misc/plugin/makelirs.rb +1 -4
  48. data/tdiary.conf.sample +8 -0
  49. data/theme/base.css +15 -0
  50. data/vendor/bundle/ruby/3.4.0/bin/emot +29 -0
  51. data/vendor/bundle/ruby/3.4.0/bin/hikidoc +29 -0
  52. data/vendor/bundle/ruby/3.4.0/bin/rackup +29 -0
  53. data/vendor/bundle/ruby/3.4.0/bin/rake +29 -0
  54. data/vendor/bundle/ruby/3.4.0/bin/thor +29 -0
  55. data/vendor/bundle/ruby/3.4.0/cache/base64-0.3.0.gem +0 -0
  56. data/vendor/bundle/ruby/3.4.0/cache/cgi-0.5.2.gem +0 -0
  57. data/vendor/bundle/ruby/3.4.0/cache/date-3.5.1.gem +0 -0
  58. data/vendor/bundle/ruby/3.4.0/cache/emot-0.0.4.gem +0 -0
  59. data/vendor/bundle/ruby/3.4.0/cache/fastimage-2.4.1.gem +0 -0
  60. data/vendor/bundle/ruby/3.4.0/cache/hikidoc-0.1.1.gem +0 -0
  61. data/vendor/bundle/ruby/3.4.0/cache/logger-1.7.0.gem +0 -0
  62. data/vendor/bundle/ruby/3.4.0/cache/mail-2.9.1.gem +0 -0
  63. data/vendor/bundle/ruby/3.4.0/cache/mini_mime-1.1.5.gem +0 -0
  64. data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.5.15.gem +0 -0
  65. data/vendor/bundle/ruby/3.4.0/cache/net-pop-0.1.2.gem +0 -0
  66. data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.2.2.gem +0 -0
  67. data/vendor/bundle/ruby/3.4.0/cache/net-smtp-0.5.1.gem +0 -0
  68. data/vendor/bundle/ruby/3.4.0/cache/pstore-0.2.1.gem +0 -0
  69. data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.6.gem +0 -0
  70. data/vendor/bundle/ruby/3.4.0/cache/rack-session-2.1.2.gem +0 -0
  71. data/vendor/bundle/ruby/3.4.0/cache/rackup-2.3.1.gem +0 -0
  72. data/vendor/bundle/ruby/3.4.0/cache/rake-13.4.2.gem +0 -0
  73. data/vendor/bundle/ruby/3.4.0/cache/thor-1.5.0.gem +0 -0
  74. data/vendor/bundle/ruby/3.4.0/cache/timeout-0.6.1.gem +0 -0
  75. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/cgi/escape.so +0 -0
  76. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem.build_complete +0 -0
  77. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem_make.out +18 -0
  78. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/date_core.so +0 -0
  79. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem.build_complete +0 -0
  80. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem_make.out +24 -0
  81. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/mkmf.log +93 -0
  82. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/BSDL +22 -0
  83. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/COPYING +56 -0
  84. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/LEGAL +60 -0
  85. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/README.md +48 -0
  86. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/lib/base64.rb +381 -0
  87. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/sig/base64.rbs +355 -0
  88. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/BSDL +22 -0
  89. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/COPYING +56 -0
  90. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/README.md +98 -0
  91. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/Makefile +275 -0
  92. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/depend +2 -0
  93. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/escape.c +487 -0
  94. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/extconf.rb +7 -0
  95. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/cookie.rb +212 -0
  96. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/core.rb +1273 -0
  97. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/escape.rb +227 -0
  98. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/escape.so +0 -0
  99. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/html.rb +1040 -0
  100. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/session/pstore.rb +91 -0
  101. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/session.rb +574 -0
  102. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/util.rb +48 -0
  103. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi.rb +310 -0
  104. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/BSDL +22 -0
  105. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/COPYING +56 -0
  106. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/README.md +102 -0
  107. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/Makefile +273 -0
  108. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_core.c +10065 -0
  109. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_parse.c +3086 -0
  110. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_strftime.c +638 -0
  111. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_strptime.c +704 -0
  112. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_tmx.h +56 -0
  113. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/extconf.rb +13 -0
  114. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/prereq.mk +19 -0
  115. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/zonetab.h +1564 -0
  116. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/zonetab.list +330 -0
  117. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/lib/date.rb +70 -0
  118. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/lib/date_core.so +0 -0
  119. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/Gemfile +4 -0
  120. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/LICENSE.txt +22 -0
  121. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/README.md +87 -0
  122. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/Rakefile +7 -0
  123. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/bin/emot +5 -0
  124. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/emot.gemspec +26 -0
  125. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/cli.rb +62 -0
  126. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/map.rb +894 -0
  127. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/symbol_ext.rb +11 -0
  128. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/version.rb +3 -0
  129. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot.rb +34 -0
  130. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/cli_spec.rb +56 -0
  131. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/emot_spec.rb +50 -0
  132. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/spec_helper.rb +2 -0
  133. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/MIT-LICENSE +20 -0
  134. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/README.md +209 -0
  135. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage.rb +471 -0
  136. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/avif.rb +12 -0
  137. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/bmp.rb +17 -0
  138. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/exif.rb +76 -0
  139. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/fiber_stream.rb +58 -0
  140. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/gif.rb +63 -0
  141. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/heic.rb +8 -0
  142. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/ico.rb +9 -0
  143. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/image_base.rb +17 -0
  144. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/iso_bmff.rb +176 -0
  145. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jpeg.rb +52 -0
  146. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jxl.rb +13 -0
  147. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jxlc.rb +75 -0
  148. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/png.rb +26 -0
  149. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/psd.rb +7 -0
  150. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/stream_util.rb +19 -0
  151. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/svg.rb +69 -0
  152. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/tiff.rb +16 -0
  153. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/type_parser.rb +74 -0
  154. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/webp.rb +60 -0
  155. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/version.rb +5 -0
  156. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage.rb +73 -0
  157. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/COPYING +28 -0
  158. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/Gemfile +4 -0
  159. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/NEWS +36 -0
  160. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/NEWS.ja +36 -0
  161. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README +95 -0
  162. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.ja +92 -0
  163. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.ja.md +112 -0
  164. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.md +114 -0
  165. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/Rakefile +18 -0
  166. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules +320 -0
  167. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.ja +318 -0
  168. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.ja.md +385 -0
  169. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.md +388 -0
  170. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/bin/hikidoc +70 -0
  171. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/hikidoc.gemspec +24 -0
  172. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/lib/hikidoc.rb +912 -0
  173. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/test/hikidoc_test.rb +514 -0
  174. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/BSDL +22 -0
  175. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/COPYING +56 -0
  176. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/README.md +104 -0
  177. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/errors.rb +9 -0
  178. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/formatter.rb +36 -0
  179. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/log_device.rb +265 -0
  180. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/period.rb +47 -0
  181. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/severity.rb +38 -0
  182. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/version.rb +5 -0
  183. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger.rb +789 -0
  184. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/MIT-LICENSE +20 -0
  185. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/README.md +771 -0
  186. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/attachments_list.rb +109 -0
  187. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/body.rb +305 -0
  188. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/configuration.rb +78 -0
  189. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/constants.rb +79 -0
  190. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/address.rb +258 -0
  191. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/address_list.rb +34 -0
  192. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_disposition_element.rb +20 -0
  193. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_location_element.rb +17 -0
  194. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_transfer_encoding_element.rb +13 -0
  195. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_type_element.rb +25 -0
  196. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/date_time_element.rb +15 -0
  197. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/envelope_from_element.rb +39 -0
  198. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/message_ids_element.rb +31 -0
  199. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/mime_version_element.rb +15 -0
  200. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/phrase_list.rb +19 -0
  201. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/received_element.rb +35 -0
  202. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements.rb +15 -0
  203. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/7bit.rb +27 -0
  204. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/8bit.rb +18 -0
  205. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/base64.rb +38 -0
  206. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/binary.rb +13 -0
  207. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/identity.rb +24 -0
  208. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/quoted_printable.rb +45 -0
  209. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/transfer_encoding.rb +77 -0
  210. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/unix_to_unix.rb +20 -0
  211. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings.rb +314 -0
  212. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/envelope.rb +28 -0
  213. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/field.rb +313 -0
  214. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/field_list.rb +87 -0
  215. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/bcc_field.rb +49 -0
  216. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/cc_field.rb +33 -0
  217. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/comments_field.rb +31 -0
  218. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_address_field.rb +162 -0
  219. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_date_field.rb +56 -0
  220. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_field.rb +77 -0
  221. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_message_id_field.rb +41 -0
  222. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_description_field.rb +12 -0
  223. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_disposition_field.rb +44 -0
  224. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_id_field.rb +35 -0
  225. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_location_field.rb +28 -0
  226. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_transfer_encoding_field.rb +44 -0
  227. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_type_field.rb +171 -0
  228. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/date_field.rb +28 -0
  229. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/from_field.rb +33 -0
  230. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/in_reply_to_field.rb +45 -0
  231. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/keywords_field.rb +30 -0
  232. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/message_id_field.rb +36 -0
  233. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/mime_version_field.rb +42 -0
  234. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/named_structured_field.rb +10 -0
  235. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/named_unstructured_field.rb +10 -0
  236. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/optional_field.rb +15 -0
  237. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/parameter_hash.rb +61 -0
  238. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/received_field.rb +61 -0
  239. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/references_field.rb +42 -0
  240. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/reply_to_field.rb +33 -0
  241. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_bcc_field.rb +33 -0
  242. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_cc_field.rb +33 -0
  243. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_date_field.rb +10 -0
  244. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_from_field.rb +33 -0
  245. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_message_id_field.rb +10 -0
  246. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_sender_field.rb +32 -0
  247. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_to_field.rb +33 -0
  248. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/return_path_field.rb +60 -0
  249. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/sender_field.rb +45 -0
  250. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/structured_field.rb +24 -0
  251. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/subject_field.rb +14 -0
  252. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/to_field.rb +33 -0
  253. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/unstructured_field.rb +189 -0
  254. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields.rb +45 -0
  255. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/header.rb +237 -0
  256. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/indifferent_hash.rb +147 -0
  257. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/mail.rb +267 -0
  258. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/matchers/attachment_matchers.rb +44 -0
  259. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/matchers/has_sent_mail.rb +201 -0
  260. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/message.rb +2159 -0
  261. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/chars.rb +318 -0
  262. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/unicode.rb +405 -0
  263. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/utils.rb +44 -0
  264. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte.rb +82 -0
  265. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/exim.rb +50 -0
  266. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/file_delivery.rb +43 -0
  267. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  268. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/sendmail.rb +87 -0
  269. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/smtp.rb +200 -0
  270. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/smtp_connection.rb +57 -0
  271. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/test_mailer.rb +44 -0
  272. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/base.rb +64 -0
  273. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/imap.rb +190 -0
  274. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/pop3.rb +143 -0
  275. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/test_retriever.rb +45 -0
  276. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network.rb +16 -0
  277. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parser_tools.rb +15 -0
  278. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/address_lists_parser.rb +33245 -0
  279. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/address_lists_parser.rl +183 -0
  280. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rb +904 -0
  281. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rl +93 -0
  282. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_location_parser.rb +825 -0
  283. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_location_parser.rl +82 -0
  284. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rb +525 -0
  285. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
  286. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_type_parser.rb +1051 -0
  287. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_type_parser.rl +94 -0
  288. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/date_time_parser.rb +894 -0
  289. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/date_time_parser.rl +73 -0
  290. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rb +3678 -0
  291. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rl +93 -0
  292. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/message_ids_parser.rb +5164 -0
  293. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/message_ids_parser.rl +97 -0
  294. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/mime_version_parser.rb +516 -0
  295. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/mime_version_parser.rl +72 -0
  296. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rb +887 -0
  297. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rl +94 -0
  298. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/received_parser.rb +8785 -0
  299. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/received_parser.rl +95 -0
  300. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  301. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  302. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_mime.rl +16 -0
  303. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  304. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  305. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  306. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322.rl +74 -0
  307. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_address.rl +72 -0
  308. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_date_time.rl +37 -0
  309. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  310. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers.rb +13 -0
  311. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/part.rb +119 -0
  312. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parts_list.rb +131 -0
  313. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/smtp_envelope.rb +57 -0
  314. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/utilities.rb +576 -0
  315. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/values/unicode_tables.dat +0 -0
  316. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/version.rb +17 -0
  317. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/yaml.rb +30 -0
  318. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail.rb +65 -0
  319. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/CHANGELOG +65 -0
  320. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/CODE_OF_CONDUCT.md +74 -0
  321. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/Gemfile +9 -0
  322. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/LICENSE.txt +21 -0
  323. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/README.md +114 -0
  324. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/Rakefile +97 -0
  325. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bench/bench.rb +51 -0
  326. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/console +15 -0
  327. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/db_pull_request +20 -0
  328. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/setup +8 -0
  329. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/db/content_type_mime.db +880 -0
  330. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/db/ext_mime.db +1201 -0
  331. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/mini_mime/version.rb +4 -0
  332. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/mini_mime.rb +186 -0
  333. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/mini_mime.gemspec +31 -0
  334. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/BSDL +22 -0
  335. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/COPYING +56 -0
  336. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Gemfile +25 -0
  337. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/LICENSE.txt +65 -0
  338. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/README.md +77 -0
  339. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Rakefile +13 -0
  340. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/docs/styles.css +85 -0
  341. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/authenticators.rb +37 -0
  342. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/command_data.rb +507 -0
  343. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_accessors.rb +75 -0
  344. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_inheritance.rb +90 -0
  345. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_type_coercion.rb +74 -0
  346. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_version_defaults.rb +93 -0
  347. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config.rb +500 -0
  348. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/connection_state.rb +48 -0
  349. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_encoding.rb +214 -0
  350. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_lite.rb +226 -0
  351. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/deprecated_client_options.rb +142 -0
  352. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/errors.rb +118 -0
  353. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/esearch_result.rb +219 -0
  354. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/fetch_data.rb +597 -0
  355. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/flags.rb +262 -0
  356. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_data.rb +1113 -0
  357. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_parser/parser_utils.rb +245 -0
  358. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_parser.rb +2282 -0
  359. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_reader.rb +92 -0
  360. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/anonymous_authenticator.rb +69 -0
  361. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/authentication_exchange.rb +139 -0
  362. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/authenticators.rb +122 -0
  363. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/client_adapter.rb +123 -0
  364. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/cram_md5_authenticator.rb +61 -0
  365. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/digest_md5_authenticator.rb +342 -0
  366. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/external_authenticator.rb +83 -0
  367. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/gs2_header.rb +80 -0
  368. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/login_authenticator.rb +56 -0
  369. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/oauthbearer_authenticator.rb +199 -0
  370. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/plain_authenticator.rb +101 -0
  371. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/protocol_adapters.rb +101 -0
  372. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/scram_algorithm.rb +58 -0
  373. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/scram_authenticator.rb +361 -0
  374. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/stringprep.rb +12 -0
  375. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/xoauth2_authenticator.rb +106 -0
  376. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl.rb +182 -0
  377. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl_adapter.rb +20 -0
  378. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/search_result.rb +145 -0
  379. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sequence_set.rb +1952 -0
  380. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/nameprep.rb +70 -0
  381. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/saslprep.rb +69 -0
  382. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/saslprep_tables.rb +96 -0
  383. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/tables.rb +146 -0
  384. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/trace.rb +85 -0
  385. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep.rb +159 -0
  386. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/uidplus_data.rb +244 -0
  387. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/vanished_data.rb +65 -0
  388. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap.rb +3968 -0
  389. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/net-imap.gemspec +38 -0
  390. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/benchmarks.rake +91 -0
  391. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/rdoc.rake +70 -0
  392. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/rfcs.rake +170 -0
  393. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/saslprep.rake +30 -0
  394. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/string_prep_tables_generator.rb +449 -0
  395. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/sample/net-imap.rb +167 -0
  396. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/Gemfile +7 -0
  397. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/LICENSE.txt +22 -0
  398. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/README.md +66 -0
  399. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/Rakefile +17 -0
  400. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/lib/net/pop.rb +1025 -0
  401. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/net-pop.gemspec +32 -0
  402. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Gemfile +7 -0
  403. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/LICENSE.txt +22 -0
  404. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/README.md +29 -0
  405. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Rakefile +10 -0
  406. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/console +14 -0
  407. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/setup +8 -0
  408. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/lib/net/protocol.rb +544 -0
  409. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/net-protocol.gemspec +33 -0
  410. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/LICENSE.txt +2 -0
  411. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/NEWS.md +133 -0
  412. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/README.md +97 -0
  413. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_cram_md5.rb +48 -0
  414. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_login.rb +11 -0
  415. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_plain.rb +9 -0
  416. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_xoauth2.rb +17 -0
  417. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/authenticator.rb +57 -0
  418. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp.rb +1164 -0
  419. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/net-smtp.gemspec +31 -0
  420. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/BSDL +22 -0
  421. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/COPYING +56 -0
  422. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/Gemfile +10 -0
  423. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/README.md +95 -0
  424. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/Rakefile +10 -0
  425. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/bin/console +14 -0
  426. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/bin/setup +8 -0
  427. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/lib/pstore.rb +736 -0
  428. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/pstore.gemspec +32 -0
  429. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/CHANGELOG.md +1346 -0
  430. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/CONTRIBUTING.md +144 -0
  431. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/MIT-LICENSE +20 -0
  432. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/README.md +384 -0
  433. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/SPEC.rdoc +258 -0
  434. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/abstract/handler.rb +41 -0
  435. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/abstract/request.rb +51 -0
  436. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/basic.rb +58 -0
  437. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/bad_request.rb +8 -0
  438. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/body_proxy.rb +63 -0
  439. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/builder.rb +296 -0
  440. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/cascade.rb +67 -0
  441. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/common_logger.rb +89 -0
  442. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/conditional_get.rb +87 -0
  443. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/config.rb +22 -0
  444. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/constants.rb +68 -0
  445. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/content_length.rb +34 -0
  446. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/content_type.rb +33 -0
  447. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/deflater.rb +158 -0
  448. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/directory.rb +208 -0
  449. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/etag.rb +71 -0
  450. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/events.rb +172 -0
  451. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/files.rb +216 -0
  452. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/head.rb +25 -0
  453. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/headers.rb +238 -0
  454. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/lint.rb +964 -0
  455. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/lock.rb +29 -0
  456. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/media_type.rb +52 -0
  457. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/method_override.rb +56 -0
  458. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mime.rb +694 -0
  459. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock.rb +3 -0
  460. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock_request.rb +161 -0
  461. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock_response.rb +156 -0
  462. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/generator.rb +99 -0
  463. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/parser.rb +621 -0
  464. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/uploaded_file.rb +82 -0
  465. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart.rb +77 -0
  466. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/null_logger.rb +48 -0
  467. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/query_parser.rb +261 -0
  468. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/recursive.rb +66 -0
  469. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/reloader.rb +112 -0
  470. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/request.rb +790 -0
  471. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/response.rb +403 -0
  472. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/rewindable_input.rb +116 -0
  473. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/runtime.rb +35 -0
  474. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/sendfile.rb +197 -0
  475. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/show_exceptions.rb +409 -0
  476. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/show_status.rb +121 -0
  477. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/static.rb +192 -0
  478. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/tempfile_reaper.rb +33 -0
  479. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/urlmap.rb +99 -0
  480. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/utils.rb +714 -0
  481. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/version.rb +17 -0
  482. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack.rb +64 -0
  483. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/abstract/id.rb +535 -0
  484. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/constants.rb +13 -0
  485. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/cookie.rb +315 -0
  486. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/encryptor.rb +415 -0
  487. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/pool.rb +82 -0
  488. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/version.rb +10 -0
  489. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session.rb +12 -0
  490. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/license.md +72 -0
  491. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/readme.md +47 -0
  492. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/releases.md +31 -0
  493. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/security.md +3 -0
  494. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/bin/rackup +5 -0
  495. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler/cgi.rb +61 -0
  496. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler/webrick.rb +196 -0
  497. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler.rb +113 -0
  498. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/lobster.rb +81 -0
  499. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/server.rb +462 -0
  500. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/stream.rb +199 -0
  501. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/version.rb +8 -0
  502. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup.rb +21 -0
  503. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/license.md +80 -0
  504. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/readme.md +82 -0
  505. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/releases.md +28 -0
  506. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/security.md +3 -0
  507. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/History.rdoc +2454 -0
  508. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
  509. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/README.rdoc +155 -0
  510. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/command_line_usage.rdoc +171 -0
  511. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile1 +38 -0
  512. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile2 +35 -0
  513. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/a.c +6 -0
  514. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/b.c +6 -0
  515. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/main.c +11 -0
  516. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/glossary.rdoc +42 -0
  517. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/jamis.rb +592 -0
  518. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/proto_rake.rdoc +127 -0
  519. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rake.1 +156 -0
  520. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rakefile.rdoc +635 -0
  521. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rational.rdoc +151 -0
  522. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/exe/rake +27 -0
  523. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/application.rb +847 -0
  524. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/backtrace.rb +25 -0
  525. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/clean.rb +78 -0
  526. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cloneable.rb +17 -0
  527. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cpu_counter.rb +122 -0
  528. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/default_loader.rb +15 -0
  529. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/dsl_definition.rb +196 -0
  530. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/early_time.rb +22 -0
  531. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/core.rb +26 -0
  532. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/string.rb +176 -0
  533. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_creation_task.rb +25 -0
  534. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_list.rb +435 -0
  535. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_task.rb +58 -0
  536. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils.rb +137 -0
  537. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils_ext.rb +135 -0
  538. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_chain.rb +57 -0
  539. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_exception_mixin.rb +17 -0
  540. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/late_time.rb +18 -0
  541. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/linked_list.rb +112 -0
  542. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/loaders/makefile.rb +54 -0
  543. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/multi_task.rb +14 -0
  544. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/name_space.rb +38 -0
  545. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/options.rb +31 -0
  546. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/packagetask.rb +222 -0
  547. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/phony.rb +16 -0
  548. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/private_reader.rb +21 -0
  549. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/promise.rb +100 -0
  550. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/pseudo_status.rb +30 -0
  551. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_module.rb +67 -0
  552. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_test_loader.rb +27 -0
  553. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
  554. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/scope.rb +43 -0
  555. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task.rb +434 -0
  556. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_argument_error.rb +8 -0
  557. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_arguments.rb +113 -0
  558. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_manager.rb +333 -0
  559. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/tasklib.rb +12 -0
  560. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/testtask.rb +192 -0
  561. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_history_display.rb +49 -0
  562. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_pool.rb +157 -0
  563. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/trace_output.rb +23 -0
  564. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/version.rb +10 -0
  565. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/win32.rb +17 -0
  566. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake.rb +69 -0
  567. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/rake.gemspec +102 -0
  568. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/CONTRIBUTING.md +32 -0
  569. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/LICENSE.md +20 -0
  570. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/README.md +44 -0
  571. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/bin/thor +6 -0
  572. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/create_file.rb +105 -0
  573. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/create_link.rb +61 -0
  574. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/directory.rb +108 -0
  575. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/empty_directory.rb +143 -0
  576. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/file_manipulation.rb +407 -0
  577. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/inject_into_file.rb +163 -0
  578. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions.rb +340 -0
  579. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/base.rb +826 -0
  580. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/command.rb +151 -0
  581. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/core_ext/hash_with_indifferent_access.rb +107 -0
  582. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/error.rb +106 -0
  583. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/group.rb +292 -0
  584. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/invocation.rb +178 -0
  585. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor/basic.rb +37 -0
  586. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor/readline.rb +88 -0
  587. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor.rb +17 -0
  588. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/nested_context.rb +29 -0
  589. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/argument.rb +86 -0
  590. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/arguments.rb +195 -0
  591. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/option.rb +178 -0
  592. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/options.rb +294 -0
  593. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser.rb +4 -0
  594. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/rake_compat.rb +72 -0
  595. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/runner.rb +335 -0
  596. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/basic.rb +392 -0
  597. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/color.rb +117 -0
  598. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/column_printer.rb +29 -0
  599. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/html.rb +84 -0
  600. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/lcs_diff.rb +49 -0
  601. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/table_printer.rb +118 -0
  602. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/terminal.rb +42 -0
  603. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/wrapped_printer.rb +38 -0
  604. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell.rb +81 -0
  605. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/util.rb +285 -0
  606. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/version.rb +3 -0
  607. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor.rb +707 -0
  608. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/thor.gemspec +33 -0
  609. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/BSDL +22 -0
  610. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/COPYING +56 -0
  611. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/Gemfile +10 -0
  612. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/README.md +39 -0
  613. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/lib/timeout.rb +314 -0
  614. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/timeout.gemspec +33 -0
  615. data/vendor/bundle/ruby/3.4.0/specifications/base64-0.3.0.gemspec +23 -0
  616. data/vendor/bundle/ruby/3.4.0/specifications/cgi-0.5.2.gemspec +25 -0
  617. data/vendor/bundle/ruby/3.4.0/specifications/date-3.5.1.gemspec +25 -0
  618. data/vendor/bundle/ruby/3.4.0/specifications/emot-0.0.4.gemspec +30 -0
  619. data/vendor/bundle/ruby/3.4.0/specifications/fastimage-2.4.1.gemspec +32 -0
  620. data/vendor/bundle/ruby/3.4.0/specifications/hikidoc-0.1.1.gemspec +28 -0
  621. data/vendor/bundle/ruby/3.4.0/specifications/logger-1.7.0.gemspec +22 -0
  622. data/vendor/bundle/ruby/3.4.0/specifications/mail-2.9.1.gemspec +38 -0
  623. data/vendor/bundle/ruby/3.4.0/specifications/mini_mime-1.1.5.gemspec +30 -0
  624. data/vendor/bundle/ruby/3.4.0/specifications/net-imap-0.5.15.gemspec +28 -0
  625. data/vendor/bundle/ruby/3.4.0/specifications/net-pop-0.1.2.gemspec +26 -0
  626. data/vendor/bundle/ruby/3.4.0/specifications/net-protocol-0.2.2.gemspec +26 -0
  627. data/vendor/bundle/ruby/3.4.0/specifications/net-smtp-0.5.1.gemspec +26 -0
  628. data/vendor/bundle/ruby/3.4.0/specifications/pstore-0.2.1.gemspec +22 -0
  629. data/vendor/bundle/ruby/3.4.0/specifications/rack-3.2.6.gemspec +31 -0
  630. data/vendor/bundle/ruby/3.4.0/specifications/rack-session-2.1.2.gemspec +30 -0
  631. data/vendor/bundle/ruby/3.4.0/specifications/rackup-2.3.1.gemspec +26 -0
  632. data/vendor/bundle/ruby/3.4.0/specifications/rake-13.4.2.gemspec +26 -0
  633. data/vendor/bundle/ruby/3.4.0/specifications/thor-1.5.0.gemspec +28 -0
  634. data/vendor/bundle/ruby/3.4.0/specifications/timeout-0.6.1.gemspec +22 -0
  635. metadata +595 -20
  636. data/js/02edit.js +0 -15
  637. data/lib/tdiary/compatible.rb +0 -56
  638. data/misc/lib/fcgi_patch.rb +0 -89
  639. data/misc/paas/heroku/Gemfile.local +0 -12
  640. data/misc/paas/heroku/Gemfile.lock +0 -287
  641. data/public/index.rdf +0 -22
@@ -0,0 +1,2282 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errors"
4
+ require_relative "response_parser/parser_utils"
5
+
6
+ module Net
7
+ class IMAP < Protocol
8
+
9
+ # Parses an \IMAP server response.
10
+ class ResponseParser
11
+ include ParserUtils
12
+ extend ParserUtils::Generator
13
+
14
+ attr_reader :config
15
+
16
+ # Creates a new ResponseParser.
17
+ #
18
+ # When +config+ is frozen or global, the parser #config inherits from it.
19
+ # Otherwise, +config+ will be used directly.
20
+ def initialize(config: Config.global)
21
+ @str = nil
22
+ @pos = nil
23
+ @lex_state = nil
24
+ @token = nil
25
+ @config = Config[config]
26
+ @config = @config.new if @config == Config.global || @config.frozen?
27
+ end
28
+
29
+ # :call-seq:
30
+ # parse(str) -> ContinuationRequest
31
+ # parse(str) -> UntaggedResponse
32
+ # parse(str) -> TaggedResponse
33
+ #
34
+ # Raises ResponseParseError for unparsable strings.
35
+ def parse(str)
36
+ @str = str
37
+ @pos = 0
38
+ @lex_state = EXPR_BEG
39
+ @token = nil
40
+ return response
41
+ end
42
+
43
+ private
44
+
45
+ # :stopdoc:
46
+
47
+ EXPR_BEG = :EXPR_BEG # the default, used in most places
48
+ EXPR_DATA = :EXPR_DATA # envelope, body(structure), namespaces
49
+
50
+ T_SPACE = :SPACE # atom special
51
+ T_ATOM = :ATOM # atom (subset of astring chars)
52
+ T_NIL = :NIL # subset of atom and label
53
+ T_NUMBER = :NUMBER # subset of atom
54
+ T_LBRA = :LBRA # subset of atom
55
+ T_PLUS = :PLUS # subset of atom; tag special
56
+ T_RBRA = :RBRA # atom special; resp_special; valid astring char
57
+ T_QUOTED = :QUOTED # starts/end with atom special
58
+ T_BSLASH = :BSLASH # atom special; quoted special
59
+ T_LPAR = :LPAR # atom special; paren list delimiter
60
+ T_RPAR = :RPAR # atom special; paren list delimiter
61
+ T_STAR = :STAR # atom special; list wildcard
62
+ T_PERCENT = :PERCENT # atom special; list wildcard
63
+ T_LITERAL = :LITERAL # starts with atom special
64
+ T_LITERAL8 = :LITERAL8 # starts with atom char "~"
65
+ T_CRLF = :CRLF # atom special; text special; quoted special
66
+ T_TEXT = :TEXT # any char except CRLF
67
+ T_EOF = :EOF # end of response string
68
+
69
+ module ResponseConditions
70
+ OK = "OK"
71
+ NO = "NO"
72
+ BAD = "BAD"
73
+ BYE = "BYE"
74
+ PREAUTH = "PREAUTH"
75
+
76
+ RESP_COND_STATES = [OK, NO, BAD ].freeze
77
+ RESP_DATA_CONDS = [OK, NO, BAD, BYE, ].freeze
78
+ AUTH_CONDS = [OK, PREAUTH].freeze
79
+ GREETING_CONDS = [OK, BYE, PREAUTH].freeze
80
+ RESP_CONDS = [OK, NO, BAD, BYE, PREAUTH].freeze
81
+ end
82
+ include ResponseConditions
83
+
84
+ module Patterns
85
+
86
+ module CharClassSubtraction
87
+ refine Regexp do
88
+ def -(rhs); /[#{source}&&[^#{rhs.source}]]/n.freeze end
89
+ end
90
+ end
91
+ using CharClassSubtraction
92
+
93
+ # From RFC5234, "Augmented BNF for Syntax Specifications: ABNF"
94
+ # >>>
95
+ # ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
96
+ # CHAR = %x01-7F
97
+ # CRLF = CR LF
98
+ # ; Internet standard newline
99
+ # CTL = %x00-1F / %x7F
100
+ # ; controls
101
+ # DIGIT = %x30-39
102
+ # ; 0-9
103
+ # DQUOTE = %x22
104
+ # ; " (Double Quote)
105
+ # HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
106
+ # OCTET = %x00-FF
107
+ # SP = %x20
108
+ module RFC5234
109
+ ALPHA = /[A-Za-z]/n
110
+ CHAR = /[\x01-\x7f]/n
111
+ CRLF = /\r\n/n
112
+ CTL = /[\x00-\x1F\x7F]/n
113
+ DIGIT = /\d/n
114
+ DQUOTE = /"/n
115
+ HEXDIG = /\h/
116
+ OCTET = /[\x00-\xFF]/n # not using /./m for embedding purposes
117
+ SP = / /n
118
+ end
119
+
120
+ # UTF-8, a transformation format of ISO 10646
121
+ # >>>
122
+ # UTF8-1 = %x00-7F
123
+ # UTF8-tail = %x80-BF
124
+ # UTF8-2 = %xC2-DF UTF8-tail
125
+ # UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
126
+ # %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
127
+ # UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
128
+ # %xF4 %x80-8F 2( UTF8-tail )
129
+ # UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
130
+ # UTF8-octets = *( UTF8-char )
131
+ #
132
+ # n.b. String * Integer is used for repetition, rather than /x{3}/,
133
+ # because ruby 3.2's linear-time cache-based optimization doesn't work
134
+ # with "bounded or fixed times repetition nesting in another repetition
135
+ # (e.g. /(a{2,3})*/). It is an implementation issue entirely, but we
136
+ # believe it is hard to support this case correctly."
137
+ # See https://bugs.ruby-lang.org/issues/19104
138
+ module RFC3629
139
+ UTF8_1 = /[\x00-\x7f]/n # aka ASCII 7bit
140
+ UTF8_TAIL = /[\x80-\xBF]/n
141
+ UTF8_2 = /[\xC2-\xDF]#{UTF8_TAIL}/n
142
+ UTF8_3 = Regexp.union(/\xE0[\xA0-\xBF]#{UTF8_TAIL}/n,
143
+ /\xED[\x80-\x9F]#{UTF8_TAIL}/n,
144
+ /[\xE1-\xEC]#{ UTF8_TAIL.source * 2}/n,
145
+ /[\xEE-\xEF]#{ UTF8_TAIL.source * 2}/n)
146
+ UTF8_4 = Regexp.union(/[\xF1-\xF3]#{ UTF8_TAIL.source * 3}/n,
147
+ /\xF0[\x90-\xBF]#{UTF8_TAIL.source * 2}/n,
148
+ /\xF4[\x80-\x8F]#{UTF8_TAIL.source * 2}/n)
149
+ UTF8_CHAR = Regexp.union(UTF8_1, UTF8_2, UTF8_3, UTF8_4)
150
+ UTF8_OCTETS = /#{UTF8_CHAR}*/n
151
+ end
152
+
153
+ include RFC5234
154
+ include RFC3629
155
+
156
+ # CHAR8 = %x01-ff
157
+ # ; any OCTET except NUL, %x00
158
+ CHAR8 = /[\x01-\xff]/n
159
+
160
+ # list-wildcards = "%" / "*"
161
+ LIST_WILDCARDS = /[%*]/n
162
+ # quoted-specials = DQUOTE / "\"
163
+ QUOTED_SPECIALS = /["\\]/n
164
+ # resp-specials = "]"
165
+ RESP_SPECIALS = /[\]]/n
166
+
167
+ # atomish = 1*<any ATOM-CHAR except "[">
168
+ # ; We use "atomish" for msg-att and section, in order
169
+ # ; to simplify "BODY[HEADER.FIELDS (foo bar)]".
170
+ #
171
+ # atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
172
+ # quoted-specials / resp-specials
173
+ # ATOM-CHAR = <any CHAR except atom-specials>
174
+ # atom = 1*ATOM-CHAR
175
+ # ASTRING-CHAR = ATOM-CHAR / resp-specials
176
+ # tag = 1*<any ASTRING-CHAR except "+">
177
+
178
+ ATOM_SPECIALS = /[(){ \x00-\x1f\x7f%*"\\\]]/n
179
+ ASTRING_SPECIALS = /[(){ \x00-\x1f\x7f%*"\\]/n
180
+
181
+ ASTRING_CHAR = CHAR - ASTRING_SPECIALS
182
+ ATOM_CHAR = CHAR - ATOM_SPECIALS
183
+
184
+ ATOM = /#{ATOM_CHAR}+/n
185
+ ASTRING_CHARS = /#{ASTRING_CHAR}+/n
186
+ ATOMISH = /#{ATOM_CHAR - /[\[]/ }+/
187
+ TAG = /#{ASTRING_CHAR - /[+]/ }+/
188
+
189
+ # TEXT-CHAR = <any CHAR except CR and LF>
190
+ TEXT_CHAR = CHAR - /[\r\n]/
191
+
192
+ # resp-text-code = ... / atom [SP 1*<any TEXT-CHAR except "]">]
193
+ CODE_TEXT_CHAR = TEXT_CHAR - RESP_SPECIALS
194
+ CODE_TEXT = /#{CODE_TEXT_CHAR}+/n
195
+
196
+ # flag = "\Answered" / "\Flagged" / "\Deleted" /
197
+ # "\Seen" / "\Draft" / flag-keyword / flag-extension
198
+ # ; Does not include "\Recent"
199
+ # flag-extension = "\" atom
200
+ # ; Future expansion. Client implementations
201
+ # ; MUST accept flag-extension flags. Server
202
+ # ; implementations MUST NOT generate
203
+ # ; flag-extension flags except as defined by
204
+ # ; a future Standard or Standards Track
205
+ # ; revisions of this specification.
206
+ # flag-keyword = "$MDNSent" / "$Forwarded" / "$Junk" /
207
+ # "$NotJunk" / "$Phishing" / atom
208
+ #
209
+ # flag-perm = flag / "\*"
210
+ #
211
+ # Not checking for max one mbx-list-sflag in the parser.
212
+ # >>>
213
+ # mbx-list-oflag = "\Noinferiors" / child-mbox-flag /
214
+ # "\Subscribed" / "\Remote" / flag-extension
215
+ # ; Other flags; multiple from this list are
216
+ # ; possible per LIST response, but each flag
217
+ # ; can only appear once per LIST response
218
+ # mbx-list-sflag = "\NonExistent" / "\Noselect" / "\Marked" /
219
+ # "\Unmarked"
220
+ # ; Selectability flags; only one per LIST response
221
+ # child-mbox-flag = "\HasChildren" / "\HasNoChildren"
222
+ # ; attributes for the CHILDREN return option, at most
223
+ # ; one possible per LIST response
224
+ FLAG = /\\?#{ATOM}/n
225
+ FLAG_EXTENSION = /\\#{ATOM}/n
226
+ FLAG_KEYWORD = ATOM
227
+ FLAG_PERM = Regexp.union(FLAG, "\\*")
228
+ MBX_FLAG = FLAG_EXTENSION
229
+
230
+ # flag-list = "(" [flag *(SP flag)] ")"
231
+ # resp-text-code =/ "PERMANENTFLAGS" SP
232
+ # "(" [flag-perm *(SP flag-perm)] ")"
233
+ # mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
234
+ # *(SP mbx-list-oflag) /
235
+ # mbx-list-oflag *(SP mbx-list-oflag)
236
+ # (Not checking for max one mbx-list-sflag in the parser.)
237
+ FLAG_LIST = /\G\((#{FLAG }(?:#{SP}#{FLAG })*|)\)/ni
238
+ FLAG_PERM_LIST = /\G\((#{FLAG_PERM}(?:#{SP}#{FLAG_PERM})*|)\)/ni
239
+ MBX_LIST_FLAGS = /\G (#{MBX_FLAG }(?:#{SP}#{MBX_FLAG })*) /nix
240
+
241
+ # Gmail allows SP and "]" in flags.......
242
+ QUIRKY_FLAG = Regexp.union(/\\?#{ASTRING_CHARS}/n, "\\*")
243
+ QUIRKY_FLAGS_LIST = /\G\(( [^)]* )\)/nx
244
+
245
+ # RFC3501:
246
+ # QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
247
+ # "\" quoted-specials
248
+ # RFC9051:
249
+ # QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
250
+ # "\" quoted-specials / UTF8-2 / UTF8-3 / UTF8-4
251
+ # RFC3501 & RFC9051:
252
+ # quoted = DQUOTE *QUOTED-CHAR DQUOTE
253
+ QUOTED_CHAR_safe = TEXT_CHAR - QUOTED_SPECIALS
254
+ QUOTED_CHAR_esc = /\\#{QUOTED_SPECIALS}/n
255
+ QUOTED_CHAR_rev1 = Regexp.union(QUOTED_CHAR_safe, QUOTED_CHAR_esc)
256
+ QUOTED_CHAR_rev2 = Regexp.union(QUOTED_CHAR_rev1,
257
+ UTF8_2, UTF8_3, UTF8_4)
258
+ QUOTED_rev1 = /"(#{QUOTED_CHAR_rev1}*)"/n
259
+ QUOTED_rev2 = /"(#{QUOTED_CHAR_rev2}*)"/n
260
+
261
+ # RFC3501:
262
+ # text = 1*TEXT-CHAR
263
+ # RFC9051:
264
+ # text = 1*(TEXT-CHAR / UTF8-2 / UTF8-3 / UTF8-4)
265
+ # ; Non-ASCII text can only be returned
266
+ # ; after ENABLE IMAP4rev2 command
267
+ TEXT_rev1 = /#{TEXT_CHAR}+/
268
+ TEXT_rev2 = /#{Regexp.union TEXT_CHAR, UTF8_2, UTF8_3, UTF8_4}+/
269
+
270
+ # tagged-label-fchar = ALPHA / "-" / "_" / "."
271
+ TAGGED_LABEL_FCHAR = /[a-zA-Z\-_.]/n
272
+ # tagged-label-char = tagged-label-fchar / DIGIT / ":"
273
+ TAGGED_LABEL_CHAR = /[a-zA-Z\-_.0-9:]*/n
274
+ # tagged-ext-label = tagged-label-fchar *tagged-label-char
275
+ # ; Is a valid RFC 3501 "atom".
276
+ TAGGED_EXT_LABEL = /#{TAGGED_LABEL_FCHAR}#{TAGGED_LABEL_CHAR}*/n
277
+
278
+ # nz-number = digit-nz *DIGIT
279
+ # ; Non-zero unsigned 32-bit integer
280
+ # ; (0 < n < 4,294,967,296)
281
+ NZ_NUMBER = /[1-9]\d*/n
282
+
283
+ # seq-number = nz-number / "*"
284
+ # ; message sequence number (COPY, FETCH, STORE
285
+ # ; commands) or unique identifier (UID COPY,
286
+ # ; UID FETCH, UID STORE commands).
287
+ # ; * represents the largest number in use. In
288
+ # ; the case of message sequence numbers, it is
289
+ # ; the number of messages in a non-empty mailbox.
290
+ # ; In the case of unique identifiers, it is the
291
+ # ; unique identifier of the last message in the
292
+ # ; mailbox or, if the mailbox is empty, the
293
+ # ; mailbox's current UIDNEXT value.
294
+ # ; The server should respond with a tagged BAD
295
+ # ; response to a command that uses a message
296
+ # ; sequence number greater than the number of
297
+ # ; messages in the selected mailbox. This
298
+ # ; includes "*" if the selected mailbox is empty.
299
+ SEQ_NUMBER = /#{NZ_NUMBER}|\*/n
300
+
301
+ # seq-range = seq-number ":" seq-number
302
+ # ; two seq-number values and all values between
303
+ # ; these two regardless of order.
304
+ # ; Example: 2:4 and 4:2 are equivalent and
305
+ # ; indicate values 2, 3, and 4.
306
+ # ; Example: a unique identifier sequence range of
307
+ # ; 3291:* includes the UID of the last message in
308
+ # ; the mailbox, even if that value is less than
309
+ # ; 3291.
310
+ SEQ_RANGE = /#{SEQ_NUMBER}:#{SEQ_NUMBER}/n
311
+
312
+ # sequence-set = (seq-number / seq-range) ["," sequence-set]
313
+ # ; set of seq-number values, regardless of order.
314
+ # ; Servers MAY coalesce overlaps and/or execute
315
+ # ; the sequence in any order.
316
+ # ; Example: a message sequence number set of
317
+ # ; 2,4:7,9,12:* for a mailbox with 15 messages is
318
+ # ; equivalent to 2,4,5,6,7,9,12,13,14,15
319
+ # ; Example: a message sequence number set of
320
+ # ; *:4,5:7 for a mailbox with 10 messages is
321
+ # ; equivalent to 10,9,8,7,6,5,4,5,6,7 and MAY
322
+ # ; be reordered and overlap coalesced to be
323
+ # ; 4,5,6,7,8,9,10.
324
+ SEQUENCE_SET_ITEM = /#{SEQ_NUMBER}|#{SEQ_RANGE}/n
325
+ SEQUENCE_SET = /#{SEQUENCE_SET_ITEM}(?:,#{SEQUENCE_SET_ITEM})*/n
326
+ SEQUENCE_SET_STR = /\A#{SEQUENCE_SET}\z/n
327
+
328
+ # partial-range-first = nz-number ":" nz-number
329
+ # ;; Request to search from oldest (lowest UIDs) to
330
+ # ;; more recent messages.
331
+ # ;; A range 500:400 is the same as 400:500.
332
+ # ;; This is similar to <seq-range> from [RFC3501]
333
+ # ;; but cannot contain "*".
334
+ PARTIAL_RANGE_FIRST = /\A(#{NZ_NUMBER}):(#{NZ_NUMBER})\z/n
335
+
336
+ # partial-range-last = MINUS nz-number ":" MINUS nz-number
337
+ # ;; Request to search from newest (highest UIDs) to
338
+ # ;; oldest messages.
339
+ # ;; A range -500:-400 is the same as -400:-500.
340
+ PARTIAL_RANGE_LAST = /\A(-#{NZ_NUMBER}):(-#{NZ_NUMBER})\z/n
341
+
342
+ # partial-range = partial-range-first / partial-range-last
343
+ PARTIAL_RANGE = Regexp.union(PARTIAL_RANGE_FIRST,
344
+ PARTIAL_RANGE_LAST)
345
+
346
+ # RFC3501:
347
+ # literal = "{" number "}" CRLF *CHAR8
348
+ # ; Number represents the number of CHAR8s
349
+ # RFC9051:
350
+ # literal = "{" number64 ["+"] "}" CRLF *CHAR8
351
+ # ; <number64> represents the number of CHAR8s.
352
+ # ; A non-synchronizing literal is distinguished
353
+ # ; from a synchronizing literal by the presence of
354
+ # ; "+" before the closing "}".
355
+ # ; Non-synchronizing literals are not allowed when
356
+ # ; sent from server to the client.
357
+ LITERAL = /\{(\d+)\}\r\n/n
358
+
359
+ # RFC3516 (BINARY):
360
+ # literal8 = "~{" number "}" CRLF *OCTET
361
+ # ; <number> represents the number of OCTETs
362
+ # ; in the response string.
363
+ # RFC9051:
364
+ # literal8 = "~{" number64 "}" CRLF *OCTET
365
+ # ; <number64> represents the number of OCTETs
366
+ # ; in the response string.
367
+ LITERAL8 = /~\{(\d+)\}\r\n/n
368
+
369
+ module_function
370
+
371
+ def unescape_quoted!(quoted)
372
+ quoted
373
+ &.gsub!(/\\(#{QUOTED_SPECIALS})/n, "\\1")
374
+ &.force_encoding("UTF-8")
375
+ end
376
+
377
+ def unescape_quoted(quoted)
378
+ quoted
379
+ &.gsub(/\\(#{QUOTED_SPECIALS})/n, "\\1")
380
+ &.force_encoding("UTF-8")
381
+ end
382
+
383
+ end
384
+
385
+ # the default, used in most places
386
+ BEG_REGEXP = /\G(?:\
387
+ (?# 1: SPACE )( )|\
388
+ (?# 2: LITERAL8)#{Patterns::LITERAL8}|\
389
+ (?# 3: ATOM prefixed with a compatible subtype)\
390
+ ((?:\
391
+ (?# 4: NIL )(NIL)|\
392
+ (?# 5: NUMBER )(\d+)|\
393
+ (?# 6: PLUS )(\+))\
394
+ (?# 7: ATOM remaining after prefix )(#{Patterns::ATOMISH})?\
395
+ (?# This enables greedy alternation without lookahead, in linear time.)\
396
+ )|\
397
+ (?# Also need to check for ATOM without a subtype prefix.)\
398
+ (?# 8: ATOM )(#{Patterns::ATOMISH})|\
399
+ (?# 9: QUOTED )#{Patterns::QUOTED_rev2}|\
400
+ (?# 10: LPAR )(\()|\
401
+ (?# 11: RPAR )(\))|\
402
+ (?# 12: BSLASH )(\\)|\
403
+ (?# 13: STAR )(\*)|\
404
+ (?# 14: LBRA )(\[)|\
405
+ (?# 15: RBRA )(\])|\
406
+ (?# 16: LITERAL )#{Patterns::LITERAL}|\
407
+ (?# 17: PERCENT )(%)|\
408
+ (?# 18: CRLF )(\r\n)|\
409
+ (?# 19: EOF )(\z))/ni
410
+
411
+ # envelope, body(structure), namespaces
412
+ DATA_REGEXP = /\G(?:\
413
+ (?# 1: SPACE )( )|\
414
+ (?# 2: NIL )(NIL)|\
415
+ (?# 3: NUMBER )(\d+)|\
416
+ (?# 4: QUOTED )#{Patterns::QUOTED_rev2}|\
417
+ (?# 5: LITERAL )#{Patterns::LITERAL}|\
418
+ (?# 6: LPAR )(\()|\
419
+ (?# 7: RPAR )(\)))/ni
420
+
421
+ # text, after 'resp-text-code "]"'
422
+ TEXT_REGEXP = /\G(#{Patterns::TEXT_rev2})/n
423
+
424
+ # resp-text-code, after 'atom SP'
425
+ CTEXT_REGEXP = /\G(#{Patterns::CODE_TEXT})/n
426
+
427
+ Token = Struct.new(:symbol, :value)
428
+
429
+ def_char_matchers :SP, " ", :T_SPACE
430
+ def_char_matchers :PLUS, "+", :T_PLUS
431
+ def_char_matchers :STAR, "*", :T_STAR
432
+
433
+ def_char_matchers :lpar, "(", :T_LPAR
434
+ def_char_matchers :rpar, ")", :T_RPAR
435
+
436
+ def_char_matchers :lbra, "[", :T_LBRA
437
+ def_char_matchers :rbra, "]", :T_RBRA
438
+
439
+ # valid number ranges are not enforced by parser
440
+ # number = 1*DIGIT
441
+ # ; Unsigned 32-bit integer
442
+ # ; (0 <= n < 4,294,967,296)
443
+ def_token_matchers :number, T_NUMBER, coerce: Integer
444
+
445
+ def_token_matchers :quoted, T_QUOTED
446
+
447
+ # string = quoted / literal
448
+ def_token_matchers :string, T_QUOTED, T_LITERAL
449
+
450
+ # used by nstring8 = nstring / literal8
451
+ def_token_matchers :string8, T_QUOTED, T_LITERAL, T_LITERAL8
452
+
453
+ # use where string represents "LABEL" values
454
+ def_token_matchers :case_insensitive__string,
455
+ T_QUOTED, T_LITERAL,
456
+ send: :upcase
457
+
458
+ # n.b: NIL? and NIL! return the "NIL" atom string (truthy) on success.
459
+ # NIL? returns nil when it does *not* match
460
+ def_token_matchers :NIL, T_NIL
461
+
462
+ # In addition to explicitly uses of +tagged-ext-label+, use this to match
463
+ # keywords when the grammar has not provided any extension syntax.
464
+ #
465
+ # Do *not* use this for labels where the grammar specifies extensions
466
+ # can be +atom+, even if all currently defined labels would match. For
467
+ # example response codes in +resp-text-code+.
468
+ #
469
+ # tagged-ext-label = tagged-label-fchar *tagged-label-char
470
+ # ; Is a valid RFC 3501 "atom".
471
+ # tagged-label-fchar = ALPHA / "-" / "_" / "."
472
+ # tagged-label-char = tagged-label-fchar / DIGIT / ":"
473
+ #
474
+ # TODO: add to lexer and only match tagged-ext-label
475
+ def_token_matchers :tagged_ext_label, T_ATOM, T_NIL, send: :upcase
476
+
477
+ def_token_matchers :CRLF, T_CRLF
478
+ def_token_matchers :EOF, T_EOF
479
+
480
+ # atom = 1*ATOM-CHAR
481
+ # ATOM-CHAR = <any CHAR except atom-specials>
482
+ ATOM_TOKENS = [T_ATOM, T_NUMBER, T_NIL, T_LBRA, T_PLUS]
483
+
484
+ SEQUENCE_SET_TOKENS = [T_ATOM, T_NUMBER, T_STAR]
485
+
486
+ # sequence-set = (seq-number / seq-range) ["," sequence-set]
487
+ # sequence-set =/ seq-last-command
488
+ # ; Allow for "result of the last command"
489
+ # ; indicator.
490
+ # seq-last-command = "$"
491
+ #
492
+ # *note*: doesn't match seq-last-command
493
+ def sequence_set
494
+ str = combine_adjacent(*SEQUENCE_SET_TOKENS)
495
+ if Patterns::SEQUENCE_SET_STR.match?(str)
496
+ SequenceSet[str]
497
+ else
498
+ parse_error("unexpected atom %p, expected sequence-set", str)
499
+ end
500
+ end
501
+
502
+ # ASTRING-CHAR = ATOM-CHAR / resp-specials
503
+ # resp-specials = "]"
504
+ ASTRING_CHARS_TOKENS = [*ATOM_TOKENS, T_RBRA].freeze
505
+
506
+ ASTRING_TOKENS = [T_QUOTED, *ASTRING_CHARS_TOKENS, T_LITERAL].freeze
507
+
508
+ # tag = 1*<any ASTRING-CHAR except "+">
509
+ TAG_TOKENS = (ASTRING_CHARS_TOKENS - [T_PLUS]).freeze
510
+
511
+ # TODO: handle atom, astring_chars, and tag entirely inside the lexer
512
+ def atom; combine_adjacent(*ATOM_TOKENS) end
513
+ def astring_chars; combine_adjacent(*ASTRING_CHARS_TOKENS) end
514
+ def tag; combine_adjacent(*TAG_TOKENS) end
515
+
516
+ # the #accept version of #atom
517
+ def atom?; -combine_adjacent(*ATOM_TOKENS) if lookahead?(*ATOM_TOKENS) end
518
+
519
+ # Returns <tt>atom.upcase</tt>
520
+ def case_insensitive__atom; -combine_adjacent(*ATOM_TOKENS).upcase end
521
+
522
+ # Returns <tt>atom?&.upcase</tt>
523
+ def case_insensitive__atom?
524
+ -combine_adjacent(*ATOM_TOKENS).upcase if lookahead?(*ATOM_TOKENS)
525
+ end
526
+
527
+ # astring = 1*ASTRING-CHAR / string
528
+ def astring
529
+ lookahead?(*ASTRING_CHARS_TOKENS) ? astring_chars : string
530
+ end
531
+
532
+ def astring?
533
+ lookahead?(*ASTRING_CHARS_TOKENS) ? astring_chars : string?
534
+ end
535
+
536
+ # Use #label or #label_in to assert specific known labels
537
+ # (+tagged-ext-label+ only, not +atom+).
538
+ def label(word)
539
+ (val = tagged_ext_label) == word and return val
540
+ parse_error("unexpected atom %p, expected %p instead", val, word)
541
+ end
542
+
543
+ # Use #label or #label_in to assert specific known labels
544
+ # (+tagged-ext-label+ only, not +atom+).
545
+ def label_in(*labels)
546
+ lbl = tagged_ext_label and labels.include?(lbl) and return lbl
547
+ parse_error("unexpected atom %p, expected one of %s instead",
548
+ lbl, labels.join(" or "))
549
+ end
550
+
551
+ # expects "OK" or "PREAUTH" and raises InvalidResponseError on failure
552
+ def resp_cond_auth__name
553
+ lbl = tagged_ext_label and AUTH_CONDS.include? lbl and return lbl
554
+ raise InvalidResponseError, "bad response type %p, expected %s" % [
555
+ lbl, AUTH_CONDS.join(" or ")
556
+ ]
557
+ end
558
+
559
+ # expects "OK" or "NO" or "BAD" and raises InvalidResponseError on failure
560
+ def resp_cond_state__name
561
+ lbl = tagged_ext_label and RESP_COND_STATES.include? lbl and return lbl
562
+ raise InvalidResponseError, "bad response type %p, expected %s" % [
563
+ lbl, RESP_COND_STATES.join(" or ")
564
+ ]
565
+ end
566
+
567
+ # nstring = string / nil
568
+ def nstring
569
+ NIL? ? nil : string
570
+ end
571
+
572
+ def nstring8
573
+ NIL? ? nil : string8
574
+ end
575
+
576
+ def nquoted
577
+ NIL? ? nil : quoted
578
+ end
579
+
580
+ # use where nstring represents "LABEL" values
581
+ def case_insensitive__nstring
582
+ NIL? ? nil : case_insensitive__string
583
+ end
584
+
585
+ # tagged-ext-comp = astring /
586
+ # tagged-ext-comp *(SP tagged-ext-comp) /
587
+ # "(" tagged-ext-comp ")"
588
+ # ; Extensions that follow this general
589
+ # ; syntax should use nstring instead of
590
+ # ; astring when appropriate in the context
591
+ # ; of the extension.
592
+ # ; Note that a message set or a "number"
593
+ # ; can always be represented as an "atom".
594
+ # ; A URL should be represented as
595
+ # ; a "quoted" string.
596
+ def tagged_ext_comp
597
+ vals = []
598
+ while true
599
+ vals << case lookahead!(*ASTRING_TOKENS, T_LPAR).symbol
600
+ when T_LPAR then lpar; ary = tagged_ext_comp; rpar; ary
601
+ when T_NUMBER then number
602
+ else astring
603
+ end
604
+ SP? or break
605
+ end
606
+ vals
607
+ end
608
+
609
+ # tagged-ext-simple is a subset of atom
610
+ # TODO: recognize sequence-set in the lexer
611
+ #
612
+ # tagged-ext-simple = sequence-set / number / number64
613
+ def tagged_ext_simple
614
+ number? || sequence_set
615
+ end
616
+
617
+ # tagged-ext-val = tagged-ext-simple /
618
+ # "(" [tagged-ext-comp] ")"
619
+ def tagged_ext_val
620
+ if lpar?
621
+ _ = peek_rpar? ? [] : tagged_ext_comp
622
+ rpar
623
+ _
624
+ else
625
+ tagged_ext_simple
626
+ end
627
+ end
628
+
629
+ # mailbox = "INBOX" / astring
630
+ # ; INBOX is case-insensitive. All case variants of
631
+ # ; INBOX (e.g., "iNbOx") MUST be interpreted as INBOX
632
+ # ; not as an astring. An astring which consists of
633
+ # ; the case-insensitive sequence "I" "N" "B" "O" "X"
634
+ # ; is considered to be INBOX and not an astring.
635
+ # ; Refer to section 5.1 for further
636
+ # ; semantic details of mailbox names.
637
+ alias mailbox astring
638
+
639
+ # valid number ranges are not enforced by parser
640
+ # number64 = 1*DIGIT
641
+ # ; Unsigned 63-bit integer
642
+ # ; (0 <= n <= 9,223,372,036,854,775,807)
643
+ alias number64 number
644
+ alias number64? number?
645
+
646
+ # valid number ranges are not enforced by parser
647
+ # nz-number = digit-nz *DIGIT
648
+ # ; Non-zero unsigned 32-bit integer
649
+ # ; (0 < n < 4,294,967,296)
650
+ alias nz_number number
651
+ alias nz_number? number?
652
+
653
+ # valid number ranges are not enforced by parser
654
+ # nz-number64 = digit-nz *DIGIT
655
+ # ; Unsigned 63-bit integer
656
+ # ; (0 < n <= 9,223,372,036,854,775,807)
657
+ alias nz_number64 nz_number
658
+
659
+ # valid number ranges are not enforced by parser
660
+ # uniqueid = nz-number
661
+ # ; Strictly ascending
662
+ alias uniqueid nz_number
663
+
664
+ # valid number ranges are not enforced by parser
665
+ #
666
+ # a 64-bit unsigned integer and is the decimal equivalent for the ID hex
667
+ # string used in the web interface and the Gmail API.
668
+ alias x_gm_id number
669
+
670
+ # [RFC3501 & RFC9051:]
671
+ # response = *(continue-req / response-data) response-done
672
+ #
673
+ # For simplicity, response isn't interpreted as the combination of the
674
+ # three response types, but instead represents any individual server
675
+ # response. Our simplified interpretation is defined as:
676
+ # response = continue-req | response_data | response-tagged
677
+ #
678
+ # n.b: our "response-tagged" definition parses "greeting" too.
679
+ def response
680
+ resp = case lookahead!(T_PLUS, T_STAR, *TAG_TOKENS).symbol
681
+ when T_PLUS then continue_req
682
+ when T_STAR then response_data
683
+ else response_tagged
684
+ end
685
+ accept_spaces # QUIRKY: Ignore trailing space (MS Exchange Server?)
686
+ CRLF!
687
+ EOF!
688
+ resp
689
+ end
690
+
691
+ # RFC3501 & RFC9051:
692
+ # continue-req = "+" SP (resp-text / base64) CRLF
693
+ #
694
+ # n.b: base64 is valid resp-text. And in the spirit of RFC9051 Appx E 23
695
+ # (and to workaround existing servers), we use the following grammar:
696
+ #
697
+ # continue-req = "+" (SP (resp-text)) CRLF
698
+ def continue_req
699
+ PLUS!
700
+ ContinuationRequest.new(SP? ? resp_text : ResponseText::EMPTY, @str)
701
+ end
702
+
703
+ RE_RESPONSE_TYPE = /\G(?:\d+ )?(?<type>#{Patterns::TAGGED_EXT_LABEL})/n
704
+
705
+ # [RFC3501:]
706
+ # response-data = "*" SP (resp-cond-state / resp-cond-bye /
707
+ # mailbox-data / message-data / capability-data) CRLF
708
+ # [RFC4466:]
709
+ # response-data = "*" SP response-payload CRLF
710
+ # response-payload = resp-cond-state / resp-cond-bye /
711
+ # mailbox-data / message-data / capability-data
712
+ # RFC5161 (ENABLE capability):
713
+ # response-data =/ "*" SP enable-data CRLF
714
+ # RFC5255 (LANGUAGE capability)
715
+ # response-payload =/ language-data
716
+ # RFC5255 (I18NLEVEL=1 and I18NLEVEL=2 capabilities)
717
+ # response-payload =/ comparator-data
718
+ # [RFC9051:]
719
+ # response-data = "*" SP (resp-cond-state / resp-cond-bye /
720
+ # mailbox-data / message-data / capability-data /
721
+ # enable-data) CRLF
722
+ #
723
+ # [merging in greeting and response-fatal:]
724
+ # greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
725
+ # response-fatal = "*" SP resp-cond-bye CRLF
726
+ # response-data =/ "*" SP (resp-cond-auth / resp-cond-bye) CRLF
727
+ # [removing duplicates, this is simply]
728
+ # response-payload =/ resp-cond-auth
729
+ #
730
+ # TODO: remove resp-cond-auth and handle greeting separately
731
+ def response_data
732
+ STAR!; SP!
733
+ m = peek_re(RE_RESPONSE_TYPE) or parse_error("unparsable response")
734
+ case m["type"].upcase
735
+ when "OK" then resp_cond_state__untagged # RFC3501, RFC9051
736
+ when "FETCH" then message_data__fetch # RFC3501, RFC9051
737
+ when "EXPUNGE" then message_data__expunge # RFC3501, RFC9051
738
+ when "EXISTS" then mailbox_data__exists # RFC3501, RFC9051
739
+ when "ESEARCH" then esearch_response # RFC4731, RFC9051, etc
740
+ when "VANISHED" then expunged_resp # RFC7162
741
+ when "UIDFETCH" then uidfetch_resp # RFC9586
742
+ when "SEARCH" then mailbox_data__search # RFC3501 (obsolete)
743
+ when "CAPABILITY" then capability_data__untagged # RFC3501, RFC9051
744
+ when "FLAGS" then mailbox_data__flags # RFC3501, RFC9051
745
+ when "LIST" then mailbox_data__list # RFC3501, RFC9051
746
+ when "STATUS" then mailbox_data__status # RFC3501, RFC9051
747
+ when "NAMESPACE" then namespace_response # RFC2342, RFC9051
748
+ when "ENABLED" then enable_data # RFC5161, RFC9051
749
+ when "BAD" then resp_cond_state__untagged # RFC3501, RFC9051
750
+ when "NO" then resp_cond_state__untagged # RFC3501, RFC9051
751
+ when "PREAUTH" then resp_cond_auth # RFC3501, RFC9051
752
+ when "BYE" then resp_cond_bye # RFC3501, RFC9051
753
+ when "RECENT" then mailbox_data__recent # RFC3501 (obsolete)
754
+ when "SORT" then sort_data # RFC5256, RFC7162
755
+ when "THREAD" then thread_data # RFC5256
756
+ when "QUOTA" then quota_response # RFC2087, RFC9208
757
+ when "QUOTAROOT" then quotaroot_response # RFC2087, RFC9208
758
+ when "ID" then id_response # RFC2971
759
+ when "ACL" then acl_data # RFC4314
760
+ when "LISTRIGHTS" then listrights_data # RFC4314
761
+ when "MYRIGHTS" then myrights_data # RFC4314
762
+ when "METADATA" then metadata_resp # RFC5464
763
+ when "LANGUAGE" then language_data # RFC5255
764
+ when "COMPARATOR" then comparator_data # RFC5255
765
+ when "CONVERTED" then message_data__converted # RFC5259
766
+ when "LSUB" then mailbox_data__lsub # RFC3501 (obsolete)
767
+ when "XLIST" then mailbox_data__xlist # deprecated
768
+ when "NOOP" then response_data__noop
769
+ else response_data__unhandled
770
+ end
771
+ end
772
+
773
+ def response_data__unhandled(klass = UntaggedResponse)
774
+ num = number?; SP?
775
+ type = tagged_ext_label; SP?
776
+ text = remaining_unparsed
777
+ data =
778
+ if num && text then UnparsedNumericResponseData.new(num, text)
779
+ elsif text then UnparsedData.new(text)
780
+ else num
781
+ end
782
+ klass.new(type, data, @str)
783
+ end
784
+
785
+ # reads all the way up until CRLF
786
+ def remaining_unparsed
787
+ str = @str[@pos...-2] and @pos += str.bytesize
788
+ str&.empty? ? nil : str
789
+ end
790
+
791
+ def response_data__ignored; response_data__unhandled(IgnoredResponse) end
792
+ alias response_data__noop response_data__ignored
793
+
794
+ alias listrights_data response_data__unhandled
795
+ alias myrights_data response_data__unhandled
796
+ alias metadata_resp response_data__unhandled
797
+ alias language_data response_data__unhandled
798
+ alias comparator_data response_data__unhandled
799
+ alias message_data__converted response_data__unhandled
800
+
801
+ # RFC3501 & RFC9051:
802
+ # response-tagged = tag SP resp-cond-state CRLF
803
+ def response_tagged
804
+ TaggedResponse.new(tag, *(SP!; resp_cond_state), @str)
805
+ end
806
+
807
+ # RFC3501 & RFC9051:
808
+ # resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
809
+ #
810
+ # NOTE: In the spirit of RFC9051 Appx E 23 (and to workaround existing
811
+ # servers), we don't require a final SP and instead parse this as:
812
+ #
813
+ # resp-cond-state = ("OK" / "NO" / "BAD") [SP resp-text]
814
+ def resp_cond_state
815
+ [resp_cond_state__name, SP? ? resp_text : ResponseText::EMPTY]
816
+ end
817
+
818
+ def resp_cond_state__untagged
819
+ UntaggedResponse.new(*resp_cond_state, @str)
820
+ end
821
+
822
+ # resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
823
+ #
824
+ # NOTE: In the spirit of RFC9051 Appx E 23 (and to workaround existing
825
+ # servers), we don't require a final SP and instead parse this as:
826
+ #
827
+ # resp-cond-auth = ("OK" / "PREAUTH") [SP resp-text]
828
+ def resp_cond_auth
829
+ UntaggedResponse.new(resp_cond_auth__name,
830
+ SP? ? resp_text : ResponseText::EMPTY,
831
+ @str)
832
+ end
833
+
834
+ # resp-cond-bye = "BYE" SP resp-text
835
+ #
836
+ # NOTE: In the spirit of RFC9051 Appx E 23 (and to workaround existing
837
+ # servers), we don't require a final SP and instead parse this as:
838
+ #
839
+ # resp-cond-bye = "BYE" [SP resp-text]
840
+ def resp_cond_bye
841
+ UntaggedResponse.new(label(BYE),
842
+ SP? ? resp_text : ResponseText::EMPTY,
843
+ @str)
844
+ end
845
+
846
+ # message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
847
+ def message_data__fetch
848
+ seq = nz_number; SP!
849
+ name = label "FETCH"; SP!
850
+ data = FetchData.new(seq, msg_att(seq))
851
+ UntaggedResponse.new(name, data, @str)
852
+ end
853
+
854
+ # uidfetch-resp = uniqueid SP "UIDFETCH" SP msg-att
855
+ def uidfetch_resp
856
+ uid = uniqueid; SP!
857
+ name = label "UIDFETCH"; SP!
858
+ data = UIDFetchData.new(uid, msg_att(uid))
859
+ UntaggedResponse.new(name, data, @str)
860
+ end
861
+
862
+ def response_data__simple_numeric
863
+ data = nz_number; SP!
864
+ name = tagged_ext_label
865
+ UntaggedResponse.new(name, data, @str)
866
+ end
867
+
868
+ alias message_data__expunge response_data__simple_numeric
869
+ alias mailbox_data__exists response_data__simple_numeric
870
+ alias mailbox_data__recent response_data__simple_numeric
871
+
872
+ # The name for this is confusing, because it *replaces* EXPUNGE
873
+ # >>>
874
+ # expunged-resp = "VANISHED" [SP "(EARLIER)"] SP known-uids
875
+ def expunged_resp
876
+ name = label "VANISHED"; SP!
877
+ earlier = if lpar? then label("EARLIER"); rpar; SP!; true else false end
878
+ uids = known_uids
879
+ data = VanishedData[uids, earlier]
880
+ UntaggedResponse.new name, data, @str
881
+ end
882
+
883
+ # TODO: replace with uid_set
884
+ alias known_uids sequence_set
885
+
886
+ # RFC3501 & RFC9051:
887
+ # msg-att = "(" (msg-att-dynamic / msg-att-static)
888
+ # *(SP (msg-att-dynamic / msg-att-static)) ")"
889
+ #
890
+ # msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
891
+ # RFC5257 (ANNOTATE extension):
892
+ # msg-att-dynamic =/ "ANNOTATION" SP
893
+ # ( "(" entry-att *(SP entry-att) ")" /
894
+ # "(" entry *(SP entry) ")" )
895
+ # RFC7162 (CONDSTORE extension):
896
+ # msg-att-dynamic =/ fetch-mod-resp
897
+ # fetch-mod-resp = "MODSEQ" SP "(" permsg-modsequence ")"
898
+ # RFC8970 (PREVIEW extension):
899
+ # msg-att-dynamic =/ "PREVIEW" SP nstring
900
+ #
901
+ # RFC3501:
902
+ # msg-att-static = "ENVELOPE" SP envelope /
903
+ # "INTERNALDATE" SP date-time /
904
+ # "RFC822" [".HEADER" / ".TEXT"] SP nstring /
905
+ # "RFC822.SIZE" SP number /
906
+ # "BODY" ["STRUCTURE"] SP body /
907
+ # "BODY" section ["<" number ">"] SP nstring /
908
+ # "UID" SP uniqueid
909
+ # RFC3516 (BINARY extension):
910
+ # msg-att-static =/ "BINARY" section-binary SP (nstring / literal8)
911
+ # / "BINARY.SIZE" section-binary SP number
912
+ # RFC8514 (SAVEDATE extension):
913
+ # msg-att-static =/ "SAVEDATE" SP (date-time / nil)
914
+ # RFC8474 (OBJECTID extension):
915
+ # msg-att-static =/ fetch-emailid-resp / fetch-threadid-resp
916
+ # fetch-emailid-resp = "EMAILID" SP "(" objectid ")"
917
+ # fetch-threadid-resp = "THREADID" SP ( "(" objectid ")" / nil )
918
+ # RFC9051:
919
+ # msg-att-static = "ENVELOPE" SP envelope /
920
+ # "INTERNALDATE" SP date-time /
921
+ # "RFC822.SIZE" SP number64 /
922
+ # "BODY" ["STRUCTURE"] SP body /
923
+ # "BODY" section ["<" number ">"] SP nstring /
924
+ # "BINARY" section-binary SP (nstring / literal8) /
925
+ # "BINARY.SIZE" section-binary SP number /
926
+ # "UID" SP uniqueid
927
+ #
928
+ # Re https://www.rfc-editor.org/errata/eid7246, I'm adding "offset" to the
929
+ # official "BINARY" ABNF, like so:
930
+ #
931
+ # msg-att-static =/ "BINARY" section-binary ["<" number ">"] SP
932
+ # (nstring / literal8)
933
+ def msg_att(n)
934
+ lpar
935
+ attr = {}
936
+ while true
937
+ name = msg_att__label; SP!
938
+ val =
939
+ case name
940
+ when "UID" then uniqueid
941
+ when "FLAGS" then flag_list
942
+ when "BODY" then body
943
+ when /\ABODY\[/ni then nstring
944
+ when "BODYSTRUCTURE" then body
945
+ when "ENVELOPE" then envelope
946
+ when "INTERNALDATE" then date_time
947
+ when "RFC822.SIZE" then number64
948
+ when /\ABINARY\[/ni then nstring8 # BINARY, IMAP4rev2
949
+ when /\ABINARY\.SIZE\[/ni then number # BINARY, IMAP4rev2
950
+ when "RFC822" then nstring # not in rev2
951
+ when "RFC822.HEADER" then nstring # not in rev2
952
+ when "RFC822.TEXT" then nstring # not in rev2
953
+ when "MODSEQ" then parens__modseq # CONDSTORE
954
+ when "EMAILID" then parens__objectid # OBJECTID
955
+ when "THREADID" then nparens__objectid # OBJECTID
956
+ when "X-GM-MSGID" then x_gm_id # GMail
957
+ when "X-GM-THRID" then x_gm_id # GMail
958
+ when "X-GM-LABELS" then x_gm_labels # GMail
959
+ else parse_error("unknown attribute `%s' for {%d}", name, n)
960
+ end
961
+ attr[name] = val
962
+ break unless SP?
963
+ break if lookahead_rpar?
964
+ end
965
+ rpar
966
+ attr
967
+ end
968
+
969
+ # appends "[section]" and "<partial>" to the base label
970
+ def msg_att__label
971
+ case (name = tagged_ext_label)
972
+ when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni
973
+ # ignoring "[]" fixes https://bugs.ruby-lang.org/issues/5620
974
+ lbra? and rbra
975
+ when "BODY"
976
+ peek_lbra? and name << section and
977
+ peek_str?("<") and name << gt__number__lt # partial
978
+ when "BINARY", "BINARY.SIZE"
979
+ name << section_binary
980
+ # see https://www.rfc-editor.org/errata/eid7246 and the note above
981
+ peek_str?("<") and name << gt__number__lt # partial
982
+ end
983
+ name
984
+ end
985
+
986
+ # this represents the partial size for BODY or BINARY
987
+ alias gt__number__lt atom
988
+
989
+ # RFC3501 & RFC9051:
990
+ # envelope = "(" env-date SP env-subject SP env-from SP
991
+ # env-sender SP env-reply-to SP env-to SP env-cc SP
992
+ # env-bcc SP env-in-reply-to SP env-message-id ")"
993
+ def envelope
994
+ @lex_state = EXPR_DATA
995
+ lpar; date = env_date
996
+ SP!; subject = env_subject
997
+ SP!; from = env_from
998
+ SP!; sender = env_sender
999
+ SP!; reply_to = env_reply_to
1000
+ SP!; to = env_to
1001
+ SP!; cc = env_cc
1002
+ SP!; bcc = env_bcc
1003
+ SP!; in_reply_to = env_in_reply_to
1004
+ SP!; message_id = env_message_id
1005
+ rpar
1006
+ Envelope.new(date, subject, from, sender, reply_to,
1007
+ to, cc, bcc, in_reply_to, message_id)
1008
+ ensure
1009
+ @lex_state = EXPR_BEG
1010
+ end
1011
+
1012
+ # env-date = nstring
1013
+ # env-subject = nstring
1014
+ # env-in-reply-to = nstring
1015
+ # env-message-id = nstring
1016
+ alias env_date nstring
1017
+ alias env_subject nstring
1018
+ alias env_in_reply_to nstring
1019
+ alias env_message_id nstring
1020
+
1021
+ # env-from = "(" 1*address ")" / nil
1022
+ # env-sender = "(" 1*address ")" / nil
1023
+ # env-reply-to = "(" 1*address ")" / nil
1024
+ # env-to = "(" 1*address ")" / nil
1025
+ # env-cc = "(" 1*address ")" / nil
1026
+ # env-bcc = "(" 1*address ")" / nil
1027
+ def nlist__address
1028
+ return if NIL?
1029
+ lpar; list = [address]; list << address until (quirky_SP?; rpar?)
1030
+ list
1031
+ end
1032
+
1033
+ alias env_from nlist__address
1034
+ alias env_sender nlist__address
1035
+ alias env_reply_to nlist__address
1036
+ alias env_to nlist__address
1037
+ alias env_cc nlist__address
1038
+ alias env_bcc nlist__address
1039
+
1040
+ # Used when servers erroneously send an extra SP.
1041
+ #
1042
+ # As of 2023-11-28, Outlook.com (still) sends SP
1043
+ # between +address+ in <tt>env-*</tt> lists.
1044
+ alias quirky_SP? SP?
1045
+
1046
+ # date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
1047
+ # SP time SP zone DQUOTE
1048
+ alias date_time quoted
1049
+ alias ndatetime nquoted
1050
+
1051
+ # RFC-3501 & RFC-9051:
1052
+ # body = "(" (body-type-1part / body-type-mpart) ")"
1053
+ def body
1054
+ @lex_state = EXPR_DATA
1055
+ lpar; result = peek_lpar? ? body_type_mpart : body_type_1part; rpar
1056
+ result
1057
+ ensure
1058
+ @lex_state = EXPR_BEG
1059
+ end
1060
+ alias lookahead_body? lookahead_lpar?
1061
+
1062
+ # RFC-3501 & RFC9051:
1063
+ # body-type-1part = (body-type-basic / body-type-msg / body-type-text)
1064
+ # [SP body-ext-1part]
1065
+ def body_type_1part
1066
+ # This regexp peek is a performance optimization.
1067
+ # The lookahead fallback would work fine too.
1068
+ m = peek_re(/\G(?:
1069
+ (?<TEXT> "TEXT" \s "[^"]+" )
1070
+ |(?<MESSAGE> "MESSAGE" \s "(?:RFC822|GLOBAL)" )
1071
+ |(?<BASIC> "[^"]+" \s "[^"]+" )
1072
+ |(?<MIXED> "MIXED" )
1073
+ )/nix)
1074
+ choice = m&.named_captures&.compact&.keys&.first
1075
+ # In practice, the following line should never be used. But the ABNF
1076
+ # *does* allow literals, and this will handle them.
1077
+ choice ||= lookahead_case_insensitive__string!
1078
+ case choice
1079
+ when "BASIC" then body_type_basic # => BodyTypeBasic
1080
+ when "MESSAGE" then body_type_msg # => BodyTypeMessage | BodyTypeBasic
1081
+ when "TEXT" then body_type_text # => BodyTypeText
1082
+ when "MIXED" then body_type_mixed # => BodyTypeMultipart (server bug)
1083
+ else body_type_basic # might be a bug; server's or ours?
1084
+ end
1085
+ end
1086
+
1087
+ # RFC-3501 & RFC9051:
1088
+ # body-type-basic = media-basic SP body-fields
1089
+ def body_type_basic
1090
+ type = media_basic # n.b. "basic" type isn't enforced here
1091
+ if lookahead_rpar? then return BodyTypeBasic.new(*type) end # invalid
1092
+ SP!; flds = body_fields
1093
+ SP? and exts = body_ext_1part
1094
+ BodyTypeBasic.new(*type, *flds, *exts)
1095
+ end
1096
+
1097
+ # RFC-3501 & RFC-9051:
1098
+ # body-type-text = media-text SP body-fields SP body-fld-lines
1099
+ def body_type_text
1100
+ type = media_text
1101
+ SP!; flds = body_fields
1102
+ SP!; lines = body_fld_lines
1103
+ SP? and exts = body_ext_1part
1104
+ BodyTypeText.new(*type, *flds, lines, *exts)
1105
+ end
1106
+
1107
+ # RFC-3501 & RFC-9051:
1108
+ # body-type-msg = media-message SP body-fields SP envelope
1109
+ # SP body SP body-fld-lines
1110
+ def body_type_msg
1111
+ # n.b. "message/rfc822" type isn't enforced here
1112
+ type = media_message
1113
+ SP!; flds = body_fields
1114
+
1115
+ # Sometimes servers send body-type-basic when body-type-msg should be.
1116
+ # E.g: when a message/rfc822 part has "Content-Disposition: attachment".
1117
+ #
1118
+ # * SP "(" --> SP envelope --> continue as body-type-msg
1119
+ # * ")" --> no body-ext-1part --> completed body-type-basic
1120
+ # * SP nstring --> SP body-fld-md5
1121
+ # --> SP body-ext-1part --> continue as body-type-basic
1122
+ #
1123
+ # It's probably better to return BodyTypeBasic---even for
1124
+ # "message/rfc822"---than BodyTypeMessage with invalid fields.
1125
+ unless peek_str?(" (")
1126
+ SP? and exts = body_ext_1part
1127
+ return BodyTypeBasic.new(*type, *flds, *exts)
1128
+ end
1129
+
1130
+ SP!; env = envelope
1131
+ SP!; bdy = body
1132
+ SP!; lines = body_fld_lines
1133
+ SP? and exts = body_ext_1part
1134
+ BodyTypeMessage.new(*type, *flds, env, bdy, lines, *exts)
1135
+ end
1136
+
1137
+ # This is a malformed body-type-mpart with no subparts.
1138
+ def body_type_mixed
1139
+ # warn "malformed body-type-mpart: multipart/mixed with no parts."
1140
+ type = media_subtype # => "MIXED"
1141
+ SP? and exts = body_ext_mpart
1142
+ BodyTypeMultipart.new("MULTIPART", type, nil, *exts)
1143
+ end
1144
+
1145
+ # RFC-3501 & RFC-9051:
1146
+ # body-type-mpart = 1*body SP media-subtype
1147
+ # [SP body-ext-mpart]
1148
+ def body_type_mpart
1149
+ parts = [body]; parts << body until SP?; msubtype = media_subtype
1150
+ SP? and exts = body_ext_mpart
1151
+ BodyTypeMultipart.new("MULTIPART", msubtype, parts, *exts)
1152
+ end
1153
+
1154
+ # n.b. this handles both type and subtype
1155
+ #
1156
+ # RFC-3501 vs RFC-9051:
1157
+ # media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
1158
+ # "MESSAGE" /
1159
+ # "VIDEO") DQUOTE) / string) SP media-subtype
1160
+ # media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
1161
+ # "FONT" / "MESSAGE" / "MODEL" /
1162
+ # "VIDEO") DQUOTE) / string) SP media-subtype
1163
+ #
1164
+ # media-message = DQUOTE "MESSAGE" DQUOTE SP
1165
+ # DQUOTE "RFC822" DQUOTE
1166
+ # media-message = DQUOTE "MESSAGE" DQUOTE SP
1167
+ # DQUOTE ("RFC822" / "GLOBAL") DQUOTE
1168
+ #
1169
+ # RFC-3501 & RFC-9051:
1170
+ # media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
1171
+ # media-subtype = string
1172
+ def media_type
1173
+ mtype = case_insensitive__string
1174
+ SP? or return mtype, nil # ??? quirky!
1175
+ msubtype = media_subtype
1176
+ return mtype, msubtype
1177
+ end
1178
+
1179
+ # TODO: check types
1180
+ alias media_basic media_type # */* --- catchall
1181
+ alias media_message media_type # message/rfc822, message/global
1182
+ alias media_text media_type # text/*
1183
+
1184
+ alias media_subtype case_insensitive__string
1185
+
1186
+ # RFC-3501 & RFC-9051:
1187
+ # body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
1188
+ # body-fld-enc SP body-fld-octets
1189
+ def body_fields
1190
+ fields = []
1191
+ fields << body_fld_param; SP!
1192
+ fields << body_fld_id; SP!
1193
+ fields << body_fld_desc; SP!
1194
+ fields << body_fld_enc; SP!
1195
+ fields << body_fld_octets
1196
+ fields
1197
+ end
1198
+
1199
+ # RFC3501, RFC9051:
1200
+ # body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
1201
+ def body_fld_param
1202
+ quirky_SP? # See comments on test_bodystructure_extra_space
1203
+ return if NIL?
1204
+ param = {}
1205
+ lpar
1206
+ name = case_insensitive__string; SP!; param[name] = string
1207
+ while SP?
1208
+ name = case_insensitive__string; SP!; param[name] = string
1209
+ end
1210
+ rpar
1211
+ param
1212
+ end
1213
+
1214
+ # RFC2060
1215
+ # body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp
1216
+ # [SPACE body_fld_lang
1217
+ # [SPACE 1#body_extension]]]
1218
+ # ;; MUST NOT be returned on non-extensible
1219
+ # ;; "BODY" fetch
1220
+ # RFC3501 & RFC9051
1221
+ # body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
1222
+ # [SP body-fld-loc *(SP body-extension)]]]
1223
+ # ; MUST NOT be returned on non-extensible
1224
+ # ; "BODY" fetch
1225
+ def body_ext_1part
1226
+ fields = []; fields << body_fld_md5
1227
+ SP? or return fields; fields << body_fld_dsp
1228
+ SP? or return fields; fields << body_fld_lang
1229
+ SP? or return fields; fields << body_fld_loc
1230
+ SP? or return fields; fields << body_extensions
1231
+ fields
1232
+ end
1233
+
1234
+ # RFC-2060:
1235
+ # body_ext_mpart = body_fld_param [SP body_fld_dsp SP body_fld_lang
1236
+ # [SP 1#body_extension]]
1237
+ # ;; MUST NOT be returned on non-extensible
1238
+ # ;; "BODY" fetch
1239
+ # RFC-3501 & RFC-9051:
1240
+ # body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
1241
+ # [SP body-fld-loc *(SP body-extension)]]]
1242
+ # ; MUST NOT be returned on non-extensible
1243
+ # ; "BODY" fetch
1244
+ def body_ext_mpart
1245
+ fields = []; fields << body_fld_param
1246
+ SP? or return fields; fields << body_fld_dsp
1247
+ SP? or return fields; fields << body_fld_lang
1248
+ SP? or return fields; fields << body_fld_loc
1249
+ SP? or return fields; fields << body_extensions
1250
+ fields
1251
+ end
1252
+
1253
+ alias body_fld_desc nstring
1254
+ alias body_fld_id nstring
1255
+ alias body_fld_loc nstring
1256
+ alias body_fld_lines number64 # number in 3501, number64 in 9051
1257
+ alias body_fld_md5 nstring
1258
+ alias body_fld_octets number
1259
+
1260
+ # RFC-3501 & RFC-9051:
1261
+ # body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
1262
+ # "QUOTED-PRINTABLE") DQUOTE) / string
1263
+ alias body_fld_enc case_insensitive__string
1264
+
1265
+ # body-fld-dsp = "(" string SP body-fld-param ")" / nil
1266
+ def body_fld_dsp
1267
+ return if NIL?
1268
+ lpar; dsp_type = case_insensitive__string
1269
+ SP!; param = body_fld_param
1270
+ rpar
1271
+ ContentDisposition.new(dsp_type, param)
1272
+ end
1273
+
1274
+ # body-fld-lang = nstring / "(" string *(SP string) ")"
1275
+ def body_fld_lang
1276
+ if lpar?
1277
+ result = [case_insensitive__string]
1278
+ result << case_insensitive__string while SP?
1279
+ rpar
1280
+ result
1281
+ else
1282
+ case_insensitive__nstring
1283
+ end
1284
+ end
1285
+
1286
+ # body-extension *(SP body-extension)
1287
+ def body_extensions
1288
+ result = []
1289
+ result << body_extension; while SP? do result << body_extension end
1290
+ result
1291
+ end
1292
+
1293
+ # body-extension = nstring / number / number64 /
1294
+ # "(" body-extension *(SP body-extension) ")"
1295
+ # ; Future expansion. Client implementations
1296
+ # ; MUST accept body-extension fields. Server
1297
+ # ; implementations MUST NOT generate
1298
+ # ; body-extension fields except as defined by
1299
+ # ; future Standard or Standards Track
1300
+ # ; revisions of this specification.
1301
+ def body_extension
1302
+ if (uint = number64?) then uint
1303
+ elsif lpar? then exts = body_extensions; rpar; exts
1304
+ else nstring
1305
+ end
1306
+ end
1307
+
1308
+ # section = "[" [section-spec] "]"
1309
+ def section
1310
+ str = +lbra
1311
+ str << section_spec unless peek_rbra?
1312
+ str << rbra
1313
+ end
1314
+
1315
+ # section-binary = "[" [section-part] "]"
1316
+ def section_binary
1317
+ str = +lbra
1318
+ str << section_part unless peek_rbra?
1319
+ str << rbra
1320
+ end
1321
+
1322
+ # section-spec = section-msgtext / (section-part ["." section-text])
1323
+ # section-msgtext = "HEADER" /
1324
+ # "HEADER.FIELDS" [".NOT"] SP header-list /
1325
+ # "TEXT"
1326
+ # ; top-level or MESSAGE/RFC822 or
1327
+ # ; MESSAGE/GLOBAL part
1328
+ # section-part = nz-number *("." nz-number)
1329
+ # ; body part reference.
1330
+ # ; Allows for accessing nested body parts.
1331
+ # section-text = section-msgtext / "MIME"
1332
+ # ; text other than actual body part (headers,
1333
+ # ; etc.)
1334
+ #
1335
+ # n.b: we could "cheat" here and just grab all text inside the brackets,
1336
+ # but literals would need special treatment.
1337
+ def section_spec
1338
+ str = "".b
1339
+ str << atom # grabs everything up to "SP header-list" or "]"
1340
+ str << " " << header_list if SP?
1341
+ str
1342
+ end
1343
+
1344
+ # header-list = "(" header-fld-name *(SP header-fld-name) ")"
1345
+ def header_list
1346
+ str = +""
1347
+ str << lpar << header_fld_name
1348
+ str << " " << header_fld_name while SP?
1349
+ str << rpar
1350
+ end
1351
+
1352
+ # section-part = nz-number *("." nz-number)
1353
+ # ; body part reference.
1354
+ # ; Allows for accessing nested body parts.
1355
+ alias section_part atom
1356
+
1357
+ # RFC3501 & RFC9051:
1358
+ # header-fld-name = astring
1359
+ #
1360
+ # NOTE: Previously, Net::IMAP recreated the raw original source string.
1361
+ # Now, it returns the decoded astring value. Although this is technically
1362
+ # incompatible, it should almost never make a difference: all standard
1363
+ # header field names are valid atoms:
1364
+ #
1365
+ # https://www.iana.org/assignments/message-headers/message-headers.xhtml
1366
+ #
1367
+ # See also RFC5233:
1368
+ # optional-field = field-name ":" unstructured CRLF
1369
+ # field-name = 1*ftext
1370
+ # ftext = %d33-57 / ; Printable US-ASCII
1371
+ # %d59-126 ; characters not including
1372
+ # ; ":".
1373
+ alias header_fld_name astring
1374
+
1375
+ # mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
1376
+ # "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
1377
+ # "STATUS" SP mailbox SP "(" [status-att-list] ")" /
1378
+ # number SP "EXISTS" / number SP "RECENT"
1379
+
1380
+ def mailbox_data__flags
1381
+ name = label("FLAGS")
1382
+ SP!
1383
+ UntaggedResponse.new(name, flag_list, @str)
1384
+ end
1385
+
1386
+ def mailbox_data__list
1387
+ name = label_in("LIST", "LSUB", "XLIST")
1388
+ SP!
1389
+ UntaggedResponse.new(name, mailbox_list, @str)
1390
+ end
1391
+ alias mailbox_data__lsub mailbox_data__list
1392
+ alias mailbox_data__xlist mailbox_data__list
1393
+
1394
+ # mailbox-list = "(" [mbx-list-flags] ")" SP
1395
+ # (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
1396
+ # [SP mbox-list-extended]
1397
+ # ; This is the list information pointed to by the ABNF
1398
+ # ; item "mailbox-data", which is defined above
1399
+ def mailbox_list
1400
+ lpar; attr = peek_rpar? ? [] : mbx_list_flags; rpar
1401
+ SP!; delim = nquoted
1402
+ SP!; name = mailbox
1403
+ # TODO: mbox-list-extended
1404
+ MailboxList.new(attr, delim, name)
1405
+ end
1406
+
1407
+ def quota_response
1408
+ # If quota never established, get back
1409
+ # `NO Quota root does not exist'.
1410
+ # If quota removed, get `()' after the
1411
+ # folder spec with no mention of `STORAGE'.
1412
+ token = match(T_ATOM)
1413
+ name = token.value.upcase
1414
+ match(T_SPACE)
1415
+ mailbox = astring
1416
+ match(T_SPACE)
1417
+ match(T_LPAR)
1418
+ token = lookahead
1419
+ case token.symbol
1420
+ when T_RPAR
1421
+ shift_token
1422
+ data = MailboxQuota.new(mailbox, nil, nil)
1423
+ return UntaggedResponse.new(name, data, @str)
1424
+ when T_ATOM
1425
+ shift_token
1426
+ match(T_SPACE)
1427
+ token = match(T_NUMBER)
1428
+ usage = token.value
1429
+ match(T_SPACE)
1430
+ token = match(T_NUMBER)
1431
+ quota = token.value
1432
+ match(T_RPAR)
1433
+ data = MailboxQuota.new(mailbox, usage, quota)
1434
+ return UntaggedResponse.new(name, data, @str)
1435
+ else
1436
+ parse_error("unexpected token %s", token.symbol)
1437
+ end
1438
+ end
1439
+
1440
+ def quotaroot_response
1441
+ # Similar to getquota, but only admin can use getquota.
1442
+ token = match(T_ATOM)
1443
+ name = token.value.upcase
1444
+ match(T_SPACE)
1445
+ mailbox = astring
1446
+ quotaroots = []
1447
+ while true
1448
+ token = lookahead
1449
+ break unless token.symbol == T_SPACE
1450
+ shift_token
1451
+ quotaroots.push(astring)
1452
+ end
1453
+ data = MailboxQuotaRoot.new(mailbox, quotaroots)
1454
+ return UntaggedResponse.new(name, data, @str)
1455
+ end
1456
+
1457
+ # acl-data = "ACL" SP mailbox *(SP identifier SP rights)
1458
+ def acl_data
1459
+ token = match(T_ATOM)
1460
+ name = token.value.upcase
1461
+ match(T_SPACE)
1462
+ mailbox = astring
1463
+ data = []
1464
+ token = lookahead
1465
+ if token.symbol == T_SPACE
1466
+ shift_token
1467
+ while true
1468
+ token = lookahead
1469
+ case token.symbol
1470
+ when T_CRLF
1471
+ break
1472
+ when T_SPACE
1473
+ shift_token
1474
+ end
1475
+ user = astring
1476
+ match(T_SPACE)
1477
+ rights = astring
1478
+ data.push(MailboxACLItem.new(user, rights, mailbox))
1479
+ end
1480
+ end
1481
+ return UntaggedResponse.new(name, data, @str)
1482
+ end
1483
+
1484
+ # RFC3501:
1485
+ # mailbox-data = "SEARCH" *(SP nz-number) / ...
1486
+ # RFC5256: SORT
1487
+ # sort-data = "SORT" *(SP nz-number)
1488
+ # RFC7162: CONDSTORE, QRESYNC
1489
+ # mailbox-data =/ "SEARCH" [1*(SP nz-number) SP
1490
+ # search-sort-mod-seq]
1491
+ # sort-data = "SORT" [1*(SP nz-number) SP
1492
+ # search-sort-mod-seq]
1493
+ # ; Updates the SORT response from RFC 5256.
1494
+ # search-sort-mod-seq = "(" "MODSEQ" SP mod-sequence-value ")"
1495
+ # RFC9051:
1496
+ # mailbox-data = obsolete-search-response / ...
1497
+ # obsolete-search-response = "SEARCH" *(SP nz-number)
1498
+ def mailbox_data__search
1499
+ name = label_in("SEARCH", "SORT")
1500
+ data = []
1501
+ while _ = SP? && nz_number? do data << _ end
1502
+ if lpar?
1503
+ label("MODSEQ"); SP!
1504
+ modseq = mod_sequence_value
1505
+ rpar
1506
+ end
1507
+ data = SearchResult.new(data, modseq: modseq)
1508
+ UntaggedResponse.new(name, data, @str)
1509
+ end
1510
+ alias sort_data mailbox_data__search
1511
+
1512
+ # esearch-response = "ESEARCH" [search-correlator] [SP "UID"]
1513
+ # *(SP search-return-data)
1514
+ # ;; Note that SEARCH and ESEARCH responses
1515
+ # ;; SHOULD be mutually exclusive,
1516
+ # ;; i.e., only one of the response types
1517
+ # ;; should be
1518
+ # ;; returned as a result of a command.
1519
+ # esearch-response = "ESEARCH" [search-correlator] [SP "UID"]
1520
+ # *(SP search-return-data)
1521
+ # ; ESEARCH response replaces SEARCH response
1522
+ # ; from IMAP4rev1.
1523
+ # search-correlator = SP "(" "TAG" SP tag-string ")"
1524
+ def esearch_response
1525
+ name = label("ESEARCH")
1526
+ tag = search_correlator if peek_str?(" (")
1527
+ uid = peek_re?(/\G UID\b/i) && (SP!; label("UID"); true)
1528
+ data = []
1529
+ data << search_return_data while SP?
1530
+ esearch = ESearchResult.new(tag, uid, data)
1531
+ UntaggedResponse.new(name, esearch, @str)
1532
+ end
1533
+
1534
+ # From RFC4731 (ESEARCH):
1535
+ # search-return-data = "MIN" SP nz-number /
1536
+ # "MAX" SP nz-number /
1537
+ # "ALL" SP sequence-set /
1538
+ # "COUNT" SP number /
1539
+ # search-ret-data-ext
1540
+ # ; All return data items conform to
1541
+ # ; search-ret-data-ext syntax.
1542
+ # search-ret-data-ext = search-modifier-name SP search-return-value
1543
+ # search-modifier-name = tagged-ext-label
1544
+ # search-return-value = tagged-ext-val
1545
+ #
1546
+ # From RFC4731 (ESEARCH):
1547
+ # search-return-data =/ "MODSEQ" SP mod-sequence-value
1548
+ #
1549
+ # From RFC9394 (PARTIAL):
1550
+ # search-return-data =/ ret-data-partial
1551
+ #
1552
+ def search_return_data
1553
+ label = search_modifier_name; SP!
1554
+ value =
1555
+ case label
1556
+ when "MIN" then nz_number
1557
+ when "MAX" then nz_number
1558
+ when "ALL" then sequence_set
1559
+ when "COUNT" then number
1560
+ when "MODSEQ" then mod_sequence_value # RFC7162: CONDSTORE
1561
+ when "PARTIAL" then ret_data_partial__value # RFC9394: PARTIAL
1562
+ else search_return_value
1563
+ end
1564
+ [label, value]
1565
+ end
1566
+
1567
+ # From RFC5267 (CONTEXT=SEARCH, CONTEXT=SORT) and RFC9394 (PARTIAL):
1568
+ # ret-data-partial = "PARTIAL"
1569
+ # SP "(" partial-range SP partial-results ")"
1570
+ def ret_data_partial__value
1571
+ lpar
1572
+ range = partial_range; SP!
1573
+ results = partial_results
1574
+ rpar
1575
+ ESearchResult::PartialResult.new(range, results)
1576
+ end
1577
+
1578
+ # partial-range = partial-range-first / partial-range-last
1579
+ # tagged-ext-simple =/ partial-range-last
1580
+ def partial_range
1581
+ case (str = atom)
1582
+ when Patterns::PARTIAL_RANGE_FIRST, Patterns::PARTIAL_RANGE_LAST
1583
+ min, max = [Integer($1), Integer($2)].minmax
1584
+ min..max
1585
+ else
1586
+ parse_error("unexpected atom %p, expected partial-range", str)
1587
+ end
1588
+ end
1589
+
1590
+ # partial-results = sequence-set / "NIL"
1591
+ # ;; <sequence-set> from [RFC3501].
1592
+ # ;; NIL indicates that no results correspond to
1593
+ # ;; the requested range.
1594
+ def partial_results; NIL? ? nil : sequence_set end
1595
+
1596
+ # search-modifier-name = tagged-ext-label
1597
+ alias search_modifier_name tagged_ext_label
1598
+
1599
+ # search-return-value = tagged-ext-val
1600
+ # ; Data for the returned search option.
1601
+ # ; A single "nz-number"/"number"/"number64" value
1602
+ # ; can be returned as an atom (i.e., without
1603
+ # ; quoting). A sequence-set can be returned
1604
+ # ; as an atom as well.
1605
+ def search_return_value; ExtensionData.new(tagged_ext_val) end
1606
+
1607
+ # search-correlator = SP "(" "TAG" SP tag-string ")"
1608
+ def search_correlator
1609
+ SP!; lpar; label("TAG"); SP!; tag = tag_string; rpar
1610
+ tag
1611
+ end
1612
+
1613
+ # tag-string = astring
1614
+ # ; <tag> represented as <astring>
1615
+ alias tag_string astring
1616
+
1617
+ # RFC5256: THREAD
1618
+ # thread-data = "THREAD" [SP 1*thread-list]
1619
+ def thread_data
1620
+ name = label("THREAD")
1621
+ threads = []
1622
+ if SP?
1623
+ threads << thread_list while lookahead_thread_list?
1624
+ end
1625
+ UntaggedResponse.new(name, threads, @str)
1626
+ end
1627
+
1628
+ alias lookahead_thread_list? lookahead_lpar?
1629
+ alias lookahead_thread_nested? lookahead_thread_list?
1630
+
1631
+ # RFC5256: THREAD
1632
+ # thread-list = "(" (thread-members / thread-nested) ")"
1633
+ def thread_list
1634
+ lpar
1635
+ thread = if lookahead_thread_nested?
1636
+ ThreadMember.new(nil, thread_nested)
1637
+ else
1638
+ thread_members
1639
+ end
1640
+ rpar
1641
+ thread
1642
+ end
1643
+
1644
+ # RFC5256: THREAD
1645
+ # thread-members = nz-number *(SP nz-number) [SP thread-nested]
1646
+ def thread_members
1647
+ members = []
1648
+ members << nz_number # thread root
1649
+ while SP?
1650
+ case lookahead!(T_NUMBER, T_LPAR).symbol
1651
+ when T_NUMBER then members << nz_number
1652
+ else nested = thread_nested; break
1653
+ end
1654
+ end
1655
+ members.reverse.inject(nested || []) {|subthreads, number|
1656
+ [ThreadMember.new(number, subthreads)]
1657
+ }.first
1658
+ end
1659
+
1660
+ # RFC5256: THREAD
1661
+ # thread-nested = 2*thread-list
1662
+ def thread_nested
1663
+ nested = [thread_list, thread_list]
1664
+ while lookahead_thread_list? do nested << thread_list end
1665
+ nested
1666
+ end
1667
+
1668
+ # mailbox-data =/ "STATUS" SP mailbox SP "(" [status-att-list] ")"
1669
+ def mailbox_data__status
1670
+ resp_name = label("STATUS"); SP!
1671
+ mbox_name = mailbox; SP!
1672
+ lpar; attr = status_att_list; rpar
1673
+ UntaggedResponse.new(resp_name, StatusData.new(mbox_name, attr), @str)
1674
+ end
1675
+
1676
+ # RFC3501
1677
+ # status-att-list = status-att SP number *(SP status-att SP number)
1678
+ # RFC4466, RFC9051, and RFC3501 Errata
1679
+ # status-att-list = status-att-val *(SP status-att-val)
1680
+ def status_att_list
1681
+ attrs = [status_att_val]
1682
+ while SP? do attrs << status_att_val end
1683
+ attrs.to_h
1684
+ end
1685
+
1686
+ # RFC3501 Errata:
1687
+ # status-att-val = ("MESSAGES" SP number) / ("RECENT" SP number) /
1688
+ # ("UIDNEXT" SP nz-number) / ("UIDVALIDITY" SP nz-number) /
1689
+ # ("UNSEEN" SP number)
1690
+ # RFC4466:
1691
+ # status-att-val = ("MESSAGES" SP number) /
1692
+ # ("RECENT" SP number) /
1693
+ # ("UIDNEXT" SP nz-number) /
1694
+ # ("UIDVALIDITY" SP nz-number) /
1695
+ # ("UNSEEN" SP number)
1696
+ # ;; Extensions to the STATUS responses
1697
+ # ;; should extend this production.
1698
+ # ;; Extensions should use the generic
1699
+ # ;; syntax defined by tagged-ext.
1700
+ # RFC9051:
1701
+ # status-att-val = ("MESSAGES" SP number) /
1702
+ # ("UIDNEXT" SP nz-number) /
1703
+ # ("UIDVALIDITY" SP nz-number) /
1704
+ # ("UNSEEN" SP number) /
1705
+ # ("DELETED" SP number) /
1706
+ # ("SIZE" SP number64)
1707
+ # ; Extensions to the STATUS responses
1708
+ # ; should extend this production.
1709
+ # ; Extensions should use the generic
1710
+ # ; syntax defined by tagged-ext.
1711
+ # RFC7162:
1712
+ # status-att-val =/ "HIGHESTMODSEQ" SP mod-sequence-valzer
1713
+ # ;; Extends non-terminal defined in [RFC4466].
1714
+ # ;; Value 0 denotes that the mailbox doesn't
1715
+ # ;; support persistent mod-sequences
1716
+ # ;; as described in Section 3.1.2.2.
1717
+ # RFC7889:
1718
+ # status-att-val =/ "APPENDLIMIT" SP (number / nil)
1719
+ # ;; status-att-val is defined in RFC 4466
1720
+ # RFC8438:
1721
+ # status-att-val =/ "SIZE" SP number64
1722
+ # RFC8474:
1723
+ # status-att-val =/ "MAILBOXID" SP "(" objectid ")"
1724
+ # ; follows tagged-ext production from [RFC4466]
1725
+ def status_att_val
1726
+ key = tagged_ext_label
1727
+ SP!
1728
+ val =
1729
+ case key
1730
+ when "MESSAGES" then number # RFC3501, RFC9051
1731
+ when "UNSEEN" then number # RFC3501, RFC9051
1732
+ when "DELETED" then number # RFC3501, RFC9051
1733
+ when "UIDNEXT" then nz_number # RFC3501, RFC9051
1734
+ when "UIDVALIDITY" then nz_number # RFC3501, RFC9051
1735
+ when "RECENT" then number # RFC3501 (obsolete)
1736
+ when "SIZE" then number64 # RFC8483, RFC9051
1737
+ when "HIGHESTMODSEQ" then mod_sequence_valzer # RFC7162
1738
+ when "MAILBOXID" then parens__objectid # RFC8474
1739
+ else
1740
+ number? || ExtensionData.new(tagged_ext_val)
1741
+ end
1742
+ [key, val]
1743
+ end
1744
+
1745
+ # The presence of "IMAP4rev1" or "IMAP4rev2" is unenforced here.
1746
+ # The grammar rule is used by both response-data and resp-text-code.
1747
+ # But this method only returns UntaggedResponse (response-data).
1748
+ #
1749
+ # RFC3501:
1750
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
1751
+ # *(SP capability)
1752
+ # RFC9051:
1753
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev2"
1754
+ # *(SP capability)
1755
+ def capability_data__untagged
1756
+ UntaggedResponse.new label("CAPABILITY"), capability__list, @str
1757
+ end
1758
+
1759
+ # enable-data = "ENABLED" *(SP capability)
1760
+ def enable_data
1761
+ UntaggedResponse.new label("ENABLED"), capability__list, @str
1762
+ end
1763
+
1764
+ # As a workaround for buggy servers, allow a trailing SP:
1765
+ # *(SP capability) [SP]
1766
+ def capability__list
1767
+ list = []; while SP? && (capa = capability?) do list << capa end; list
1768
+ end
1769
+
1770
+ alias resp_code__capability capability__list
1771
+
1772
+ # capability = ("AUTH=" auth-type) / atom
1773
+ # ; New capabilities MUST begin with "X" or be
1774
+ # ; registered with IANA as standard or
1775
+ # ; standards-track
1776
+ alias capability case_insensitive__atom
1777
+ alias capability? case_insensitive__atom?
1778
+
1779
+ def id_response
1780
+ token = match(T_ATOM)
1781
+ name = token.value.upcase
1782
+ match(T_SPACE)
1783
+ token = match(T_LPAR, T_NIL)
1784
+ if token.symbol == T_NIL
1785
+ return UntaggedResponse.new(name, nil, @str)
1786
+ else
1787
+ data = {}
1788
+ while true
1789
+ token = lookahead
1790
+ case token.symbol
1791
+ when T_RPAR
1792
+ shift_token
1793
+ break
1794
+ when T_SPACE
1795
+ shift_token
1796
+ next
1797
+ else
1798
+ key = string
1799
+ match(T_SPACE)
1800
+ val = nstring
1801
+ data[key] = val
1802
+ end
1803
+ end
1804
+ return UntaggedResponse.new(name, data, @str)
1805
+ end
1806
+ end
1807
+
1808
+ # namespace-response = "NAMESPACE" SP namespace
1809
+ # SP namespace SP namespace
1810
+ # ; The first Namespace is the Personal Namespace(s).
1811
+ # ; The second Namespace is the Other Users'
1812
+ # ; Namespace(s).
1813
+ # ; The third Namespace is the Shared Namespace(s).
1814
+ def namespace_response
1815
+ name = label("NAMESPACE")
1816
+ @lex_state = EXPR_DATA
1817
+ data = Namespaces.new((SP!; namespace),
1818
+ (SP!; namespace),
1819
+ (SP!; namespace))
1820
+ UntaggedResponse.new(name, data, @str)
1821
+ ensure
1822
+ @lex_state = EXPR_BEG
1823
+ end
1824
+
1825
+ # namespace = nil / "(" 1*namespace-descr ")"
1826
+ def namespace
1827
+ NIL? and return []
1828
+ lpar
1829
+ list = [namespace_descr]
1830
+ list << namespace_descr until rpar?
1831
+ list
1832
+ end
1833
+
1834
+ # namespace-descr = "(" string SP
1835
+ # (DQUOTE QUOTED-CHAR DQUOTE / nil)
1836
+ # [namespace-response-extensions] ")"
1837
+ def namespace_descr
1838
+ lpar
1839
+ prefix = string; SP!
1840
+ delimiter = nquoted # n.b: should only accept single char
1841
+ extensions = namespace_response_extensions
1842
+ rpar
1843
+ Namespace.new(prefix, delimiter, extensions)
1844
+ end
1845
+
1846
+ # namespace-response-extensions = *namespace-response-extension
1847
+ # namespace-response-extension = SP string SP
1848
+ # "(" string *(SP string) ")"
1849
+ def namespace_response_extensions
1850
+ data = {}
1851
+ while SP?
1852
+ name = string; SP!
1853
+ lpar
1854
+ data[name] ||= []
1855
+ data[name] << string
1856
+ data[name] << string while SP?
1857
+ rpar
1858
+ end
1859
+ data
1860
+ end
1861
+
1862
+ # TEXT-CHAR = <any CHAR except CR and LF>
1863
+ # RFC3501:
1864
+ # text = 1*TEXT-CHAR
1865
+ # RFC9051:
1866
+ # text = 1*(TEXT-CHAR / UTF8-2 / UTF8-3 / UTF8-4)
1867
+ # ; Non-ASCII text can only be returned
1868
+ # ; after ENABLE IMAP4rev2 command
1869
+ def text
1870
+ match_re(TEXT_REGEXP, "text")[0].force_encoding("UTF-8")
1871
+ end
1872
+
1873
+ # an "accept" versiun of #text
1874
+ def text?
1875
+ accept_re(TEXT_REGEXP)&.[](0)&.force_encoding("UTF-8")
1876
+ end
1877
+
1878
+ # RFC3501:
1879
+ # resp-text = ["[" resp-text-code "]" SP] text
1880
+ # RFC9051:
1881
+ # resp-text = ["[" resp-text-code "]" SP] [text]
1882
+ #
1883
+ # We leniently re-interpret this as
1884
+ # resp-text = ["[" resp-text-code "]" [SP [text]] / [text]
1885
+ def resp_text
1886
+ if lbra?
1887
+ code = resp_text_code; rbra
1888
+ ResponseText.new(code, SP? && text? || "")
1889
+ else
1890
+ ResponseText.new(nil, text? || "")
1891
+ end
1892
+ end
1893
+
1894
+ # RFC3501 (See https://www.rfc-editor.org/errata/rfc3501):
1895
+ # resp-text-code = "ALERT" /
1896
+ # "BADCHARSET" [SP "(" charset *(SP charset) ")" ] /
1897
+ # capability-data / "PARSE" /
1898
+ # "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
1899
+ # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
1900
+ # "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
1901
+ # "UNSEEN" SP nz-number /
1902
+ # atom [SP 1*<any TEXT-CHAR except "]">]
1903
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
1904
+ # *(SP capability)
1905
+ #
1906
+ # RFC5530:
1907
+ # resp-text-code =/ "UNAVAILABLE" / "AUTHENTICATIONFAILED" /
1908
+ # "AUTHORIZATIONFAILED" / "EXPIRED" /
1909
+ # "PRIVACYREQUIRED" / "CONTACTADMIN" / "NOPERM" /
1910
+ # "INUSE" / "EXPUNGEISSUED" / "CORRUPTION" /
1911
+ # "SERVERBUG" / "CLIENTBUG" / "CANNOT" /
1912
+ # "LIMIT" / "OVERQUOTA" / "ALREADYEXISTS" /
1913
+ # "NONEXISTENT"
1914
+ # RFC9051:
1915
+ # resp-text-code = "ALERT" /
1916
+ # "BADCHARSET" [SP "(" charset *(SP charset) ")" ] /
1917
+ # capability-data / "PARSE" /
1918
+ # "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" /
1919
+ # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
1920
+ # "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
1921
+ # resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" /
1922
+ # "UNAVAILABLE" / "AUTHENTICATIONFAILED" /
1923
+ # "AUTHORIZATIONFAILED" / "EXPIRED" /
1924
+ # "PRIVACYREQUIRED" / "CONTACTADMIN" / "NOPERM" /
1925
+ # "INUSE" / "EXPUNGEISSUED" / "CORRUPTION" /
1926
+ # "SERVERBUG" / "CLIENTBUG" / "CANNOT" /
1927
+ # "LIMIT" / "OVERQUOTA" / "ALREADYEXISTS" /
1928
+ # "NONEXISTENT" / "NOTSAVED" / "HASCHILDREN" /
1929
+ # "CLOSED" /
1930
+ # "UNKNOWN-CTE" /
1931
+ # atom [SP 1*<any TEXT-CHAR except "]">]
1932
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev2"
1933
+ # *(SP capability)
1934
+ #
1935
+ # RFC4315 (UIDPLUS), RFC9051 (IMAP4rev2):
1936
+ # resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
1937
+ # resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set
1938
+ # resp-text-code =/ resp-code-apnd / resp-code-copy / "UIDNOTSTICKY"
1939
+ #
1940
+ # RFC7162 (CONDSTORE):
1941
+ # resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value /
1942
+ # "NOMODSEQ" /
1943
+ # "MODIFIED" SP sequence-set
1944
+ # RFC7162 (QRESYNC):
1945
+ # resp-text-code =/ "CLOSED"
1946
+ #
1947
+ # RFC8474: OBJECTID
1948
+ # resp-text-code =/ "MAILBOXID" SP "(" objectid ")"
1949
+ #
1950
+ # RFC9586: UIDONLY
1951
+ # resp-text-code =/ "UIDREQUIRED"
1952
+ def resp_text_code
1953
+ name = resp_text_code__name
1954
+ data =
1955
+ case name
1956
+ when "CAPABILITY" then resp_code__capability
1957
+ when "PERMANENTFLAGS" then SP? ? flag_perm__list : []
1958
+ when "UIDNEXT" then SP!; nz_number
1959
+ when "UIDVALIDITY" then SP!; nz_number
1960
+ when "UNSEEN" then SP!; nz_number # rev1 only
1961
+ when "APPENDUID" then SP!; resp_code_apnd__data # rev2, UIDPLUS
1962
+ when "COPYUID" then SP!; resp_code_copy__data # rev2, UIDPLUS
1963
+ when "BADCHARSET" then SP? ? charset__list : []
1964
+ when "ALERT", "PARSE", "READ-ONLY", "READ-WRITE", "TRYCREATE",
1965
+ "UNAVAILABLE", "AUTHENTICATIONFAILED", "AUTHORIZATIONFAILED",
1966
+ "EXPIRED", "PRIVACYREQUIRED", "CONTACTADMIN", "NOPERM", "INUSE",
1967
+ "EXPUNGEISSUED", "CORRUPTION", "SERVERBUG", "CLIENTBUG", "CANNOT",
1968
+ "LIMIT", "OVERQUOTA", "ALREADYEXISTS", "NONEXISTENT", "CLOSED",
1969
+ "NOTSAVED", "UIDNOTSTICKY", "UNKNOWN-CTE", "HASCHILDREN"
1970
+ when "NOMODSEQ" then nil # CONDSTORE
1971
+ when "HIGHESTMODSEQ" then SP!; mod_sequence_value # CONDSTORE
1972
+ when "MODIFIED" then SP!; sequence_set # CONDSTORE
1973
+ when "MAILBOXID" then SP!; parens__objectid # RFC8474: OBJECTID
1974
+ when "UIDREQUIRED" then # RFC9586: UIDONLY
1975
+ else
1976
+ SP? and text_chars_except_rbra
1977
+ end
1978
+ ResponseCode.new(name, data)
1979
+ end
1980
+
1981
+ alias resp_text_code__name case_insensitive__atom
1982
+
1983
+ # 1*<any TEXT-CHAR except "]">
1984
+ def text_chars_except_rbra
1985
+ match_re(CTEXT_REGEXP, '1*<any TEXT-CHAR except "]">')[0]
1986
+ end
1987
+
1988
+ # "(" charset *(SP charset) ")"
1989
+ def charset__list
1990
+ lpar; list = [charset]; while SP? do list << charset end; rpar; list
1991
+ end
1992
+
1993
+ # already matched: "APPENDUID"
1994
+ #
1995
+ # +UIDPLUS+ ABNF:: https://www.rfc-editor.org/rfc/rfc4315.html#section-4
1996
+ # resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
1997
+ # append-uid = uniqueid
1998
+ # append-uid =/ uid-set
1999
+ # ; only permitted if client uses [MULTIAPPEND]
2000
+ # ; to append multiple messages.
2001
+ #
2002
+ # n.b, uniqueid ⊂ uid-set. To avoid inconsistent return types, we always
2003
+ # match uid_set even if that returns a single-member array.
2004
+ def resp_code_apnd__data
2005
+ validity = number; SP!
2006
+ dst_uids = uid_set # uniqueid ⊂ uid-set
2007
+ AppendUID(validity, dst_uids)
2008
+ end
2009
+
2010
+ # already matched: "COPYUID"
2011
+ #
2012
+ # resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set
2013
+ def resp_code_copy__data
2014
+ validity = number; SP!
2015
+ src_uids = uid_set; SP!
2016
+ dst_uids = uid_set
2017
+ CopyUID(validity, src_uids, dst_uids)
2018
+ end
2019
+
2020
+ def AppendUID(...) DeprecatedUIDPlus(...) || AppendUIDData.new(...) end
2021
+ def CopyUID(...) DeprecatedUIDPlus(...) || CopyUIDData.new(...) end
2022
+
2023
+ # TODO: remove this code in the v0.6.0 release
2024
+ def DeprecatedUIDPlus(validity, src_uids = nil, dst_uids)
2025
+ return unless config.parser_use_deprecated_uidplus_data
2026
+ compact_uid_sets = [src_uids, dst_uids].compact
2027
+ count = compact_uid_sets.map { _1.count_with_duplicates }.max
2028
+ max = config.parser_max_deprecated_uidplus_data_size
2029
+ if count <= max
2030
+ src_uids &&= src_uids.each_ordered_number.to_a
2031
+ dst_uids = dst_uids.each_ordered_number.to_a
2032
+ UIDPlusData.new(validity, src_uids, dst_uids)
2033
+ elsif config.parser_use_deprecated_uidplus_data != :up_to_max_size
2034
+ parse_error("uid-set is too large: %d > %d", count, max)
2035
+ end
2036
+ end
2037
+
2038
+ ADDRESS_REGEXP = /\G
2039
+ \( (?: NIL | #{Patterns::QUOTED_rev2} ) # 1: NAME
2040
+ \s (?: NIL | #{Patterns::QUOTED_rev2} ) # 2: ROUTE
2041
+ \s (?: NIL | #{Patterns::QUOTED_rev2} ) # 3: MAILBOX
2042
+ \s (?: NIL | #{Patterns::QUOTED_rev2} ) # 4: HOST
2043
+ \)
2044
+ /nix
2045
+
2046
+ # address = "(" addr-name SP addr-adl SP addr-mailbox SP
2047
+ # addr-host ")"
2048
+ # addr-adl = nstring
2049
+ # addr-host = nstring
2050
+ # addr-mailbox = nstring
2051
+ # addr-name = nstring
2052
+ def address
2053
+ if (match = accept_re(ADDRESS_REGEXP))
2054
+ # note that "NIL" isn't captured by the regexp
2055
+ name, route, mailbox, host = match.captures
2056
+ .map { Patterns.unescape_quoted _1 }
2057
+ else # address may include literals
2058
+ lpar; name = addr_name
2059
+ SP!; route = addr_adl
2060
+ SP!; mailbox = addr_mailbox
2061
+ SP!; host = addr_host
2062
+ rpar
2063
+ end
2064
+ Address.new(name, route, mailbox, host)
2065
+ end
2066
+
2067
+ alias addr_adl nstring
2068
+ alias addr_host nstring
2069
+ alias addr_mailbox nstring
2070
+ alias addr_name nstring
2071
+
2072
+ # flag-list = "(" [flag *(SP flag)] ")"
2073
+ def flag_list
2074
+ if (match = accept_re(Patterns::FLAG_LIST))
2075
+ match[1].split(nil)
2076
+ .map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
2077
+ else
2078
+ quirky__flag_list "flags-list"
2079
+ end
2080
+ end
2081
+
2082
+ # "(" [flag-perm *(SP flag-perm)] ")"
2083
+ def flag_perm__list
2084
+ if (match = accept_re(Patterns::FLAG_PERM_LIST))
2085
+ match[1].split(nil)
2086
+ .map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
2087
+ else
2088
+ quirky__flag_list "PERMANENTFLAGS flag-perm list"
2089
+ end
2090
+ end
2091
+
2092
+ # This allows illegal "]" in flag names (Gmail),
2093
+ # or "\*" in a FLAGS response (greenmail).
2094
+ def quirky__flag_list(name)
2095
+ match_re(Patterns::QUIRKY_FLAGS_LIST, "quirks mode #{name}")[1]
2096
+ .scan(Patterns::QUIRKY_FLAG)
2097
+ .map! { _1.delete_prefix!("\\") ? _1.capitalize.to_sym : _1 }
2098
+ end
2099
+
2100
+ # See Patterns::MBX_LIST_FLAGS
2101
+ def mbx_list_flags
2102
+ match_re(Patterns::MBX_LIST_FLAGS, "mbx-list-flags")[1]
2103
+ .split(nil)
2104
+ .map! { _1.delete_prefix!("\\"); _1.capitalize.to_sym }
2105
+ end
2106
+
2107
+ # See https://developers.google.com/gmail/imap/imap-extensions
2108
+ def x_gm_label; accept(T_BSLASH) ? atom.capitalize.to_sym : astring end
2109
+
2110
+ # See https://developers.google.com/gmail/imap/imap-extensions
2111
+ def x_gm_labels
2112
+ lpar; return [] if rpar?
2113
+ labels = []
2114
+ labels << x_gm_label
2115
+ labels << x_gm_label while SP?
2116
+ rpar
2117
+ labels
2118
+ end
2119
+
2120
+ # See https://www.rfc-editor.org/errata/rfc3501
2121
+ #
2122
+ # charset = atom / quoted
2123
+ def charset; quoted? || atom end
2124
+
2125
+ # RFC7162:
2126
+ # mod-sequence-value = 1*DIGIT
2127
+ # ;; Positive unsigned 63-bit integer
2128
+ # ;; (mod-sequence)
2129
+ # ;; (1 <= n <= 9,223,372,036,854,775,807).
2130
+ alias mod_sequence_value nz_number64
2131
+
2132
+ # RFC7162:
2133
+ # permsg-modsequence = mod-sequence-value
2134
+ # ;; Per-message mod-sequence.
2135
+ alias permsg_modsequence mod_sequence_value
2136
+
2137
+ # RFC7162:
2138
+ # mod-sequence-valzer = "0" / mod-sequence-value
2139
+ alias mod_sequence_valzer number64
2140
+
2141
+ def parens__modseq; lpar; _ = permsg_modsequence; rpar; _ end
2142
+
2143
+ # RFC8474:
2144
+ # objectid = 1*255(ALPHA / DIGIT / "_" / "-")
2145
+ # ; characters in object identifiers are case
2146
+ # ; significant
2147
+ alias objectid atom
2148
+
2149
+ def parens__objectid; lpar; _ = objectid; rpar; _ end
2150
+ def nparens__objectid; NIL? ? nil : parens__objectid end
2151
+
2152
+ # RFC-4315 (UIDPLUS) or RFC9051 (IMAP4rev2):
2153
+ # uid-set = (uniqueid / uid-range) *("," uid-set)
2154
+ # uid-range = (uniqueid ":" uniqueid)
2155
+ # ; two uniqueid values and all values
2156
+ # ; between these two regardless of order.
2157
+ # ; Example: 2:4 and 4:2 are equivalent.
2158
+ # uniqueid = nz-number
2159
+ # ; Strictly ascending
2160
+ def uid_set
2161
+ set = sequence_set
2162
+ parse_error("uid-set cannot contain '*'") if set.include_star?
2163
+ set
2164
+ end
2165
+
2166
+ def nil_atom
2167
+ match(T_NIL)
2168
+ return nil
2169
+ end
2170
+
2171
+ SPACES_REGEXP = /\G */n
2172
+
2173
+ # The RFC is very strict about this and usually we should be too.
2174
+ # But skipping spaces is usually a safe workaround for buggy servers.
2175
+ #
2176
+ # This advances @pos directly so it's safe before changing @lex_state.
2177
+ def accept_spaces
2178
+ return false unless SP?
2179
+ @str.index(SPACES_REGEXP, @pos) and
2180
+ @pos = $~.end(0)
2181
+ true
2182
+ end
2183
+
2184
+ def next_token
2185
+ case @lex_state
2186
+ when EXPR_BEG
2187
+ if @str.index(BEG_REGEXP, @pos)
2188
+ @pos = $~.end(0)
2189
+ if $1
2190
+ return Token.new(T_SPACE, $+)
2191
+ elsif $2
2192
+ literal_token($+, T_LITERAL8)
2193
+ elsif $3 && $7
2194
+ # greedily match ATOM, prefixed with NUMBER, NIL, or PLUS.
2195
+ return Token.new(T_ATOM, $3)
2196
+ elsif $4
2197
+ return Token.new(T_NIL, $+)
2198
+ elsif $5
2199
+ return Token.new(T_NUMBER, $+)
2200
+ elsif $6
2201
+ return Token.new(T_PLUS, $+)
2202
+ elsif $8
2203
+ # match ATOM, without a NUMBER, NIL, or PLUS prefix
2204
+ return Token.new(T_ATOM, $+)
2205
+ elsif $9
2206
+ return Token.new(T_QUOTED, Patterns.unescape_quoted($+))
2207
+ elsif $10
2208
+ return Token.new(T_LPAR, $+)
2209
+ elsif $11
2210
+ return Token.new(T_RPAR, $+)
2211
+ elsif $12
2212
+ return Token.new(T_BSLASH, $+)
2213
+ elsif $13
2214
+ return Token.new(T_STAR, $+)
2215
+ elsif $14
2216
+ return Token.new(T_LBRA, $+)
2217
+ elsif $15
2218
+ return Token.new(T_RBRA, $+)
2219
+ elsif $16
2220
+ literal_token($+)
2221
+ elsif $17
2222
+ return Token.new(T_PERCENT, $+)
2223
+ elsif $18
2224
+ return Token.new(T_CRLF, $+)
2225
+ elsif $19
2226
+ return Token.new(T_EOF, $+)
2227
+ else
2228
+ parse_error("[Net::IMAP BUG] BEG_REGEXP is invalid")
2229
+ end
2230
+ else
2231
+ @str.index(/\S*/n, @pos)
2232
+ parse_error("unknown token - %s", $&.dump)
2233
+ end
2234
+ when EXPR_DATA
2235
+ if @str.index(DATA_REGEXP, @pos)
2236
+ @pos = $~.end(0)
2237
+ if $1
2238
+ return Token.new(T_SPACE, $+)
2239
+ elsif $2
2240
+ return Token.new(T_NIL, $+)
2241
+ elsif $3
2242
+ return Token.new(T_NUMBER, $+)
2243
+ elsif $4
2244
+ return Token.new(T_QUOTED, Patterns.unescape_quoted($+))
2245
+ elsif $5
2246
+ literal_token($+)
2247
+ elsif $6
2248
+ return Token.new(T_LPAR, $+)
2249
+ elsif $7
2250
+ return Token.new(T_RPAR, $+)
2251
+ else
2252
+ parse_error("[Net::IMAP BUG] DATA_REGEXP is invalid")
2253
+ end
2254
+ else
2255
+ @str.index(/\S*/n, @pos)
2256
+ parse_error("unknown token - %s", $&.dump)
2257
+ end
2258
+ else
2259
+ parse_error("invalid @lex_state - %s", @lex_state.inspect)
2260
+ end
2261
+ rescue DataFormatError => error
2262
+ parse_error error.message
2263
+ end
2264
+
2265
+ def literal_token(len, type = T_LITERAL)
2266
+ len = coerce_number64 len.to_i
2267
+ val = @str[@pos, len]
2268
+ @pos += len
2269
+ Token.new(type, val)
2270
+ end
2271
+
2272
+ # copied/adapted from NumValidator in v0.6
2273
+ def coerce_number64(num)
2274
+ int = num.to_i
2275
+ return int if 0 <= int && int <= 0x7fff_ffff_ffff_ffff
2276
+ raise DataFormatError,
2277
+ "number64 must be unsigned 63-bit integer: #{num}"
2278
+ end
2279
+
2280
+ end
2281
+ end
2282
+ end