@@ -199,11 +199,11 @@ def response_untagged
199
199
when /\A (?:STATUS)\z /ni
200
200
return status_response
201
201
when /\A (?:CAPABILITY)\z /ni
202
- return capability_response
202
+ return capability_data__untagged
203
203
when /\A (?:NOOP)\z /ni
204
204
return ignored_response
205
205
when /\A (?:ENABLED)\z /ni
206
- return enabled_response
206
+ return enable_data
207
207
else
208
208
return text_response
209
209
end
@@ -1011,36 +1011,38 @@ def status_response
1011
1011
return UntaggedResponse . new ( name , data , @str )
1012
1012
end
1013
1013
1014
- def capability_response
1015
- token = match ( T_ATOM )
1016
- name = token . value . upcase
1017
- match ( T_SPACE )
1018
- UntaggedResponse . new ( name , capability_data , @str )
1014
+ # The presence of "IMAP4rev1" or "IMAP4rev2" is unenforced here.
1015
+ # The grammar rule is used by both response-data and resp-text-code.
1016
+ # But this method only returns UntaggedResponse (response-data).
1017
+ #
1018
+ # RFC3501:
1019
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
1020
+ # *(SP capability)
1021
+ # RFC9051:
1022
+ # capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev2"
1023
+ # *(SP capability)
1024
+ def capability_data__untagged
1025
+ UntaggedResponse . new label ( "CAPABILITY" ) , capability__list , @str
1019
1026
end
1020
1027
1021
- def enabled_response
1022
- token = match ( T_ATOM )
1023
- name = token . value . upcase
1024
- match ( T_SPACE )
1025
- UntaggedResponse . new ( name , capability_data , @str )
1028
+ # enable-data = "ENABLED" *(SP capability)
1029
+ def enable_data
1030
+ UntaggedResponse . new label ( "ENABLED" ) , capability__list , @str
1026
1031
end
1027
1032
1028
- def capability_data
1029
- data = [ ]
1030
- while true
1031
- token = lookahead
1032
- case token . symbol
1033
- when T_CRLF , T_RBRA
1034
- break
1035
- when T_SPACE
1036
- shift_token
1037
- next
1038
- end
1039
- data . push ( atom . upcase )
1040
- end
1041
- data
1033
+ # As a workaround for buggy servers, allow a trailing SP:
1034
+ # *(SP capapility) [SP]
1035
+ def capability__list
1036
+ data = [ ] ; while _ = SP? && capability? do data << _ end ; data
1042
1037
end
1043
1038
1039
+ # capability = ("AUTH=" auth-type) / atom
1040
+ # ; New capabilities MUST begin with "X" or be
1041
+ # ; registered with IANA as standard or
1042
+ # ; standards-track
1043
+ alias capability case_insensitive__atom
1044
+ alias capability? case_insensitive__atom?
1045
+
1044
1046
def id_response
1045
1047
token = match ( T_ATOM )
1046
1048
name = token . value . upcase
@@ -1176,7 +1178,7 @@ def resp_text_code
1176
1178
when /\A (?:BADCHARSET)\z /n
1177
1179
result = ResponseCode . new ( name , charset_list )
1178
1180
when /\A (?:CAPABILITY)\z /ni
1179
- result = ResponseCode . new ( name , capability_data )
1181
+ result = ResponseCode . new ( name , capability__list )
1180
1182
when /\A (?:PERMANENTFLAGS)\z /n
1181
1183
match ( T_SPACE )
1182
1184
result = ResponseCode . new ( name , flag_list )
0 commit comments