ruby-changes:66071
From: nicholas <ko1@a...>
Date: Thu, 6 May 2021 15:20:58 +0900 (JST)
Subject: [ruby-changes:66071] 395a287736 (master): [ruby/net-imap] move ResponseParser to lib/net/imap/response_parser
https://git.ruby-lang.org/ruby.git/commit/?id=395a287736 From 395a2877364aff662ef0625039c34d85346bfd8b Mon Sep 17 00:00:00 2001 From: "nicholas a. evans" <nicholas.evans@g...> Date: Mon, 3 May 2021 17:07:36 -0400 Subject: [ruby/net-imap] move ResponseParser to lib/net/imap/response_parser Partially implements #10. https://github.com/ruby/net-imap/commit/c2408aac9a --- lib/net/imap.rb | 1524 +------------------------------------- lib/net/imap/response_parser.rb | 1530 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 1532 insertions(+), 1522 deletions(-) create mode 100644 lib/net/imap/response_parser.rb diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 8a6b295..703b077 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -22,6 +22,8 @@ begin https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L22 rescue LoadError end +require_relative "imap/response_parser" + module Net # @@ -2351,1528 +2353,6 @@ module Net https://github.com/ruby/ruby/blob/trunk/lib/net/imap.rb#L2353 end end - class ResponseParser # :nodoc: - def initialize - @str = nil - @pos = nil - @lex_state = nil - @token = nil - @flag_symbols = {} - end - - def parse(str) - @str = str - @pos = 0 - @lex_state = EXPR_BEG - @token = nil - return response - end - - private - - EXPR_BEG = :EXPR_BEG - EXPR_DATA = :EXPR_DATA - EXPR_TEXT = :EXPR_TEXT - EXPR_RTEXT = :EXPR_RTEXT - EXPR_CTEXT = :EXPR_CTEXT - - T_SPACE = :SPACE - T_NIL = :NIL - T_NUMBER = :NUMBER - T_ATOM = :ATOM - T_QUOTED = :QUOTED - T_LPAR = :LPAR - T_RPAR = :RPAR - T_BSLASH = :BSLASH - T_STAR = :STAR - T_LBRA = :LBRA - T_RBRA = :RBRA - T_LITERAL = :LITERAL - T_PLUS = :PLUS - T_PERCENT = :PERCENT - T_CRLF = :CRLF - T_EOF = :EOF - T_TEXT = :TEXT - - BEG_REGEXP = /\G(?:\ -(?# 1: SPACE )( +)|\ -(?# 2: NIL )(NIL)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ -(?# 3: NUMBER )(\d+)(?=[\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+])|\ -(?# 4: ATOM )([^\x80-\xff(){ \x00-\x1f\x7f%*"\\\[\]+]+)|\ -(?# 5: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ -(?# 6: LPAR )(\()|\ -(?# 7: RPAR )(\))|\ -(?# 8: BSLASH )(\\)|\ -(?# 9: STAR )(\*)|\ -(?# 10: LBRA )(\[)|\ -(?# 11: RBRA )(\])|\ -(?# 12: LITERAL )\{(\d+)\}\r\n|\ -(?# 13: PLUS )(\+)|\ -(?# 14: PERCENT )(%)|\ -(?# 15: CRLF )(\r\n)|\ -(?# 16: EOF )(\z))/ni - - DATA_REGEXP = /\G(?:\ -(?# 1: SPACE )( )|\ -(?# 2: NIL )(NIL)|\ -(?# 3: NUMBER )(\d+)|\ -(?# 4: QUOTED )"((?:[^\x00\r\n"\\]|\\["\\])*)"|\ -(?# 5: LITERAL )\{(\d+)\}\r\n|\ -(?# 6: LPAR )(\()|\ -(?# 7: RPAR )(\)))/ni - - TEXT_REGEXP = /\G(?:\ -(?# 1: TEXT )([^\x00\r\n]*))/ni - - RTEXT_REGEXP = /\G(?:\ -(?# 1: LBRA )(\[)|\ -(?# 2: TEXT )([^\x00\r\n]*))/ni - - CTEXT_REGEXP = /\G(?:\ -(?# 1: TEXT )([^\x00\r\n\]]*))/ni - - Token = Struct.new(:symbol, :value) - - def response - token = lookahead - case token.symbol - when T_PLUS - result = continue_req - when T_STAR - result = response_untagged - else - result = response_tagged - end - while lookahead.symbol == T_SPACE - # Ignore trailing space for Microsoft Exchange Server - shift_token - end - match(T_CRLF) - match(T_EOF) - return result - end - - def continue_req - match(T_PLUS) - token = lookahead - if token.symbol == T_SPACE - shift_token - return ContinuationRequest.new(resp_text, @str) - else - return ContinuationRequest.new(ResponseText.new(nil, ""), @str) - end - end - - def response_untagged - match(T_STAR) - match(T_SPACE) - token = lookahead - if token.symbol == T_NUMBER - return numeric_response - elsif token.symbol == T_ATOM - case token.value - when /\A(?:OK|NO|BAD|BYE|PREAUTH)\z/ni - return response_cond - when /\A(?:FLAGS)\z/ni - return flags_response - when /\A(?:ID)\z/ni - return id_response - when /\A(?:LIST|LSUB|XLIST)\z/ni - return list_response - when /\A(?:NAMESPACE)\z/ni - return namespace_response - when /\A(?:QUOTA)\z/ni - return getquota_response - when /\A(?:QUOTAROOT)\z/ni - return getquotaroot_response - when /\A(?:ACL)\z/ni - return getacl_response - when /\A(?:SEARCH|SORT)\z/ni - return search_response - when /\A(?:THREAD)\z/ni - return thread_response - when /\A(?:STATUS)\z/ni - return status_response - when /\A(?:CAPABILITY)\z/ni - return capability_response - when /\A(?:NOOP)\z/ni - return ignored_response - else - return text_response - end - else - parse_error("unexpected token %s", token.symbol) - end - end - - def response_tagged - tag = astring_chars - match(T_SPACE) - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return TaggedResponse.new(tag, name, resp_text, @str) - end - - def response_cond - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return UntaggedResponse.new(name, resp_text, @str) - end - - def numeric_response - n = number - match(T_SPACE) - token = match(T_ATOM) - name = token.value.upcase - case name - when "EXISTS", "RECENT", "EXPUNGE" - return UntaggedResponse.new(name, n, @str) - when "FETCH" - shift_token - match(T_SPACE) - data = FetchData.new(n, msg_att(n)) - return UntaggedResponse.new(name, data, @str) - end - end - - def msg_att(n) - match(T_LPAR) - attr = {} - while true - token = lookahead - case token.symbol - when T_RPAR - shift_token - break - when T_SPACE - shift_token - next - end - case token.value - when /\A(?:ENVELOPE)\z/ni - name, val = envelope_data - when /\A(?:FLAGS)\z/ni - name, val = flags_data - when /\A(?:INTERNALDATE)\z/ni - name, val = internaldate_data - when /\A(?:RFC822(?:\.HEADER|\.TEXT)?)\z/ni - name, val = rfc822_text - when /\A(?:RFC822\.SIZE)\z/ni - name, val = rfc822_size - when /\A(?:BODY(?:STRUCTURE)?)\z/ni - name, val = body_data - when /\A(?:UID)\z/ni - name, val = uid_data - when /\A(?:MODSEQ)\z/ni - name, val = modseq_data - else - parse_error("unknown attribute `%s' for {%d}", token.value, n) - end - attr[name] = val - end - return attr - end - - def envelope_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, envelope - end - - def envelope - @lex_state = EXPR_DATA - token = lookahead - if token.symbol == T_NIL - shift_token - result = nil - else - match(T_LPAR) - date = nstring - match(T_SPACE) - subject = nstring - match(T_SPACE) - from = address_list - match(T_SPACE) - sender = address_list - match(T_SPACE) - reply_to = address_list - match(T_SPACE) - to = address_list - match(T_SPACE) - cc = address_list - match(T_SPACE) - bcc = address_list - match(T_SPACE) - in_reply_to = nstring - match(T_SPACE) - message_id = nstring - match(T_RPAR) - result = Envelope.new(date, subject, from, sender, reply_to, - to, cc, bcc, in_reply_to, message_id) - end - @lex_state = EXPR_BEG - return result - end - - def flags_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, flag_list - end - - def internaldate_data - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - token = match(T_QUOTED) - return name, token.value - end - - def rfc822_text - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - if token.symbol == T_LBRA - shift_token - match(T_RBRA) - end - match(T_SPACE) - return name, nstring - end - - def rfc822_size - token = match(T_ATOM) - name = token.value.upcase - match(T_SPACE) - return name, number - end - - def body_data - token = match(T_ATOM) - name = token.value.upcase - token = lookahead - if token.symbol == T_SPACE - shift_token - return name, body - end - name.concat(section) - token = lookahead - if token.symbol == T_ATOM - name.concat(token.value) - shift_token - end - match(T_SPACE) - data = nstring - return name, data - end - - def body - @lex_state = EXPR_DATA - token = lookahead - if token.symbol == T_NIL - shift_token - result = nil - else - match(T_LPAR) - token = lookahead - if token.symbol == T_LPAR - result = body_type_mpart - else - result = (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/