unstructured = (*([FWS] vchar) *WSP) / obs-unstruct obs-unstruct = *((*LF *CR *(obs-utext) *LF *CR)) / FWS) obs-utext = %d0 / obs-NO-WS-CTL / LF / CR obs-NO-WS-CTL is control characters except WSP/CR/LF. So, basically, we have printable runs, plus control characters or nul
(value)
| 1105 | return ew, value |
| 1106 | |
| 1107 | def get_unstructured(value): |
| 1108 | """unstructured = (*([FWS] vchar) *WSP) / obs-unstruct |
| 1109 | obs-unstruct = *((*LF *CR *(obs-utext) *LF *CR)) / FWS) |
| 1110 | obs-utext = %d0 / obs-NO-WS-CTL / LF / CR |
| 1111 | |
| 1112 | obs-NO-WS-CTL is control characters except WSP/CR/LF. |
| 1113 | |
| 1114 | So, basically, we have printable runs, plus control characters or nulls in |
| 1115 | the obsolete syntax, separated by whitespace. Since RFC 2047 uses the |
| 1116 | obsolete syntax in its specification, but requires whitespace on either |
| 1117 | side of the encoded words, I can see no reason to need to separate the |
| 1118 | non-printable-non-whitespace from the printable runs if they occur, so we |
| 1119 | parse this into xtext tokens separated by WSP tokens. |
| 1120 | |
| 1121 | Because an 'unstructured' value must by definition constitute the entire |
| 1122 | value, this 'get' routine does not return a remaining value, only the |
| 1123 | parsed TokenList. |
| 1124 | |
| 1125 | """ |
| 1126 | # XXX: but what about bare CR and LF? They might signal the start or |
| 1127 | # end of an encoded word. YAGNI for now, since our current parsers |
| 1128 | # will never send us strings with bare CR or LF. |
| 1129 | |
| 1130 | unstructured = UnstructuredTokenList() |
| 1131 | while value: |
| 1132 | if value[0] in WSP: |
| 1133 | token, value = get_fws(value) |
| 1134 | unstructured.append(token) |
| 1135 | continue |
| 1136 | valid_ew = True |
| 1137 | if value.startswith('=?'): |
| 1138 | try: |
| 1139 | token, value = get_encoded_word(value, 'utext') |
| 1140 | except _InvalidEwError: |
| 1141 | valid_ew = False |
| 1142 | except errors.HeaderParseError: |
| 1143 | # XXX: Need to figure out how to register defects when |
| 1144 | # appropriate here. |
| 1145 | pass |
| 1146 | else: |
| 1147 | have_ws = True |
| 1148 | if len(unstructured) > 0: |
| 1149 | if unstructured[-1].token_type != 'fws': |
| 1150 | unstructured.defects.append(errors.InvalidHeaderDefect( |
| 1151 | "missing whitespace before encoded word")) |
| 1152 | have_ws = False |
| 1153 | if have_ws and len(unstructured) > 1: |
| 1154 | if unstructured[-2].token_type == 'encoded-word': |
| 1155 | unstructured[-1] = EWWhiteSpaceTerminal( |
| 1156 | unstructured[-1], 'fws') |
| 1157 | unstructured.append(token) |
| 1158 | continue |
| 1159 | tok, *remainder = _wsp_splitter(value, 1) |
| 1160 | # Split in the middle of an atom if there is a rfc2047 encoded word |
| 1161 | # which does not have WSP on both sides. The defect will be registered |
| 1162 | # the next time through the loop. |
| 1163 | # This needs to only be performed when the encoded word is valid; |
| 1164 | # otherwise, performing it on an invalid encoded word can cause |
no test coverage detected