@@ -427,6 +427,17 @@ def case_insensitive__nstring
427
427
alias nz_number number
428
428
alias nz_number? number?
429
429
430
+ # valid number ranges are not enforced by parser
431
+ # nz-number64 = digit-nz *DIGIT
432
+ # ; Unsigned 63-bit integer
433
+ # ; (0 < n <= 9,223,372,036,854,775,807)
434
+ alias nz_number64 nz_number
435
+
436
+ # valid number ranges are not enforced by parser
437
+ # uniqueid = nz-number
438
+ # ; Strictly ascending
439
+ alias uniqueid nz_number
440
+
430
441
# [RFC3501 & RFC9051:]
431
442
# response = *(continue-req / response-data) response-done
432
443
#
@@ -658,20 +669,21 @@ def msg_att(n)
658
669
lpar
659
670
attr = { }
660
671
while true
661
- name = lookahead! ( T_ATOM ) . value . upcase
662
- name , val =
672
+ name = msg_att__label ; SP!
673
+ val =
663
674
case name
664
- when "UID" then uid_data
665
- when "FLAGS" then flags_data
666
- when "BODY" then body_data
667
- when "BODYSTRUCTURE" then body_data
668
- when "ENVELOPE" then envelope_data
669
- when "INTERNALDATE" then internaldate_data
670
- when "RFC822.SIZE" then rfc822_size
671
- when "RFC822" then rfc822_text
672
- when "RFC822.HEADER" then rfc822_text # not in rev2
673
- when "RFC822.TEXT" then rfc822_text # not in rev2
674
- when "MODSEQ" then modseq_data # CONDSTORE
675
+ when "UID" then uniqueid
676
+ when "FLAGS" then flag_list
677
+ when "BODY" then body
678
+ when /\A BODY\[ /ni then nstring
679
+ when "BODYSTRUCTURE" then body
680
+ when "ENVELOPE" then envelope
681
+ when "INTERNALDATE" then date_time
682
+ when "RFC822.SIZE" then number64
683
+ when "RFC822" then nstring # not in rev2
684
+ when "RFC822.HEADER" then nstring # not in rev2
685
+ when "RFC822.TEXT" then nstring # not in rev2
686
+ when "MODSEQ" then parens__modseq # CONDSTORE
675
687
else parse_error ( "unknown attribute `%s' for {%d}" , name , n )
676
688
end
677
689
attr [ name ] = val
@@ -682,11 +694,17 @@ def msg_att(n)
682
694
attr
683
695
end
684
696
685
- def envelope_data
686
- token = match ( T_ATOM )
687
- name = token . value . upcase
688
- match ( T_SPACE )
689
- return name , envelope
697
+ # appends "[section]" and "<partial>" to the base label
698
+ def msg_att__label
699
+ case ( name = tagged_ext_label )
700
+ when /\A (?:RFC822(?:\. HEADER|\. TEXT)?)\z /ni
701
+ # ignoring "[]" fixes https://bugs.ruby-lang.org/issues/5620
702
+ lbra? and rbra
703
+ when "BODY"
704
+ peek_lbra? and name << section and
705
+ peek_str? ( "<" ) and name << atom # partial
706
+ end
707
+ name
690
708
end
691
709
692
710
def envelope
@@ -724,58 +742,10 @@ def envelope
724
742
return result
725
743
end
726
744
727
- def flags_data
728
- token = match ( T_ATOM )
729
- name = token . value . upcase
730
- match ( T_SPACE )
731
- return name , flag_list
732
- end
733
-
734
- def internaldate_data
735
- token = match ( T_ATOM )
736
- name = token . value . upcase
737
- match ( T_SPACE )
738
- token = match ( T_QUOTED )
739
- return name , token . value
740
- end
741
-
742
- def rfc822_text
743
- token = match ( T_ATOM )
744
- name = token . value . upcase
745
- token = lookahead
746
- if token . symbol == T_LBRA
747
- shift_token
748
- match ( T_RBRA )
749
- end
750
- match ( T_SPACE )
751
- return name , nstring
752
- end
753
-
754
- def rfc822_size
755
- token = match ( T_ATOM )
756
- name = token . value . upcase
757
- match ( T_SPACE )
758
- return name , number
759
- end
760
-
761
- def body_data
762
- token = match ( T_ATOM )
763
- name = token . value . upcase
764
- token = lookahead
765
- if token . symbol == T_SPACE
766
- shift_token
767
- return name , body
768
- end
769
- name . concat ( section )
770
- token = lookahead
771
- if token . symbol == T_ATOM
772
- name . concat ( token . value )
773
- shift_token
774
- end
775
- match ( T_SPACE )
776
- data = nstring
777
- return name , data
778
- end
745
+ # date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
746
+ # SP time SP zone DQUOTE
747
+ alias date_time quoted
748
+ alias ndatetime nquoted
779
749
780
750
# RFC-3501 & RFC-9051:
781
751
# body = "(" (body-type-1part / body-type-mpart) ")"
@@ -1114,23 +1084,6 @@ def header_fld_name
1114
1084
end
1115
1085
end
1116
1086
1117
- def uid_data
1118
- token = match ( T_ATOM )
1119
- name = token . value . upcase
1120
- match ( T_SPACE )
1121
- return name , number
1122
- end
1123
-
1124
- def modseq_data
1125
- token = match ( T_ATOM )
1126
- name = token . value . upcase
1127
- match ( T_SPACE )
1128
- match ( T_LPAR )
1129
- modseq = number
1130
- match ( T_RPAR )
1131
- return name , modseq
1132
- end
1133
-
1134
1087
def mailbox_data__flags
1135
1088
token = match ( T_ATOM )
1136
1089
name = token . value . upcase
@@ -1698,6 +1651,20 @@ def charset
1698
1651
end
1699
1652
end
1700
1653
1654
+ # RFC7162:
1655
+ # mod-sequence-value = 1*DIGIT
1656
+ # ;; Positive unsigned 63-bit integer
1657
+ # ;; (mod-sequence)
1658
+ # ;; (1 <= n <= 9,223,372,036,854,775,807).
1659
+ alias mod_sequence_value nz_number64
1660
+
1661
+ # RFC7162:
1662
+ # permsg-modsequence = mod-sequence-value
1663
+ # ;; Per-message mod-sequence.
1664
+ alias permsg_modsequence mod_sequence_value
1665
+
1666
+ def parens__modseq ; lpar ; _ = permsg_modsequence ; rpar ; _ end
1667
+
1701
1668
# RFC-4315 (UIDPLUS) or RFC9051 (IMAP4rev2):
1702
1669
# uid-set = (uniqueid / uid-range) *("," uid-set)
1703
1670
# uid-range = (uniqueid ":" uniqueid)
0 commit comments