File indexing completed on 2024-09-22 04:52:51
0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 0002 0003 This file is part of the Trojita Qt IMAP e-mail client, 0004 http://trojita.flaska.net/ 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include <QDebug> 0024 #include "Imap/Parser/Rfc5322HeaderParser.h" 0025 0026 #define DBG(X) do {qDebug() << X << "(current char:" << *p << ")";} while(false); 0027 //#define RAGEL_DEBUG 0028 0029 namespace Imap { 0030 namespace LowLevelParser { 0031 0032 %%{ 0033 machine rfc5322; 0034 0035 action push_current_char { 0036 #ifdef RAGEL_DEBUG 0037 qDebug() << "push_current_char " << *p; 0038 #endif 0039 str.append(*p); 0040 } 0041 0042 action clear_str { 0043 #ifdef RAGEL_DEBUG 0044 qDebug() << "clear_str"; 0045 #endif 0046 str.clear(); 0047 } 0048 0049 action push_current_backslashed { 0050 switch (*p) { 0051 case 'n': 0052 str += "\n"; 0053 break; 0054 case 'r': 0055 str += "\r"; 0056 break; 0057 case '0': 0058 str += "\0"; 0059 break; 0060 case '\\': 0061 str += "\\"; 0062 break; 0063 default: 0064 str += '\\' + *p; 0065 } 0066 #ifdef RAGEL_DEBUG 0067 qDebug() << "push_current_backslashed \\" << *p; 0068 #endif 0069 } 0070 0071 action push_string_list { 0072 #ifdef RAGEL_DEBUG 0073 qDebug() << "push_string_list " << str.data(); 0074 #endif 0075 list.append(str); 0076 str.clear(); 0077 } 0078 0079 action clear_list { 0080 #ifdef RAGEL_DEBUG 0081 qDebug() << "clear_list"; 0082 #endif 0083 list.clear(); 0084 str.clear(); 0085 } 0086 0087 action got_message_id_header { 0088 if (list.size() == 1) { 0089 #ifdef RAGEL_DEBUG 0090 qDebug() << "Message-Id: " << list[0].data(); 0091 #endif 0092 messageId += list; 0093 } else { 0094 #ifdef RAGEL_DEBUG 0095 qDebug() << "invalid Message-Id"; 0096 #endif 0097 } 0098 } 0099 0100 action got_in_reply_to_header { 0101 inReplyTo += list; 0102 #ifdef RAGEL_DEBUG 0103 qDebug() << "In-Reply-To: " << list; 0104 #endif 0105 } 0106 0107 action got_references_header { 0108 references += list; 0109 #ifdef RAGEL_DEBUG 0110 qDebug() << "got_references_header:" << references; 0111 #endif 0112 } 0113 0114 action got_list_post_header { 0115 listPost += list; 0116 #ifdef RAGEL_DEBUG 0117 qDebug() << "got_list_post_header:" << listPost; 0118 #endif 0119 } 0120 0121 action got_list_post_no { 0122 listPostNo = true; 0123 #ifdef RAGEL_DEBUG 0124 qDebug() << "got_list_post_no"; 0125 #endif 0126 } 0127 0128 action header_error { 0129 #ifdef RAGEL_DEBUG 0130 qDebug() << "Error when parsing RFC5322 headers"; 0131 #endif 0132 m_error = true; 0133 } 0134 0135 0136 include rfc5322 "rfc5322.rl"; 0137 0138 main := ( optional_field | references | obs_references | list_post | message_id | obs_message_id 0139 | in_reply_to | obs_in_reply_to)* @err(header_error) CRLF*; 0140 }%% 0141 0142 #ifdef __clang__ 0143 #pragma clang diagnostic push 0144 #if defined(__has_warning) && __has_warning("-Wunused-const-variable") 0145 #pragma clang diagnostic ignored "-Wunused-const-variable" 0146 #endif 0147 #endif 0148 %%{ 0149 write data; 0150 }%% 0151 #ifdef __clang__ 0152 #pragma clang diagnostic pop 0153 #endif 0154 0155 Rfc5322HeaderParser::Rfc5322HeaderParser(): 0156 listPostNo(false), m_error(false) 0157 { 0158 } 0159 0160 void Rfc5322HeaderParser::clear() 0161 { 0162 m_error = false; 0163 references.clear(); 0164 listPost.clear(); 0165 messageId.clear(); 0166 inReplyTo.clear(); 0167 listPostNo = false; 0168 } 0169 0170 bool Rfc5322HeaderParser::parse(const QByteArray &data) 0171 { 0172 clear(); 0173 0174 const char *p = data.constData(); 0175 const char *pe = p + data.length(); 0176 const char *eof = pe; 0177 int cs; 0178 0179 QByteArray str; 0180 QList<QByteArray> list; 0181 0182 %% write init; 0183 %% write exec; 0184 0185 return !m_error; 0186 } 0187 0188 } 0189 } 0190 0191 #if 0 0192 #include <iostream> 0193 int main() 0194 { 0195 QByteArray data; 0196 std::string line; 0197 0198 while (std::getline(std::cin, line)) { 0199 data += line.c_str(); 0200 data += '\n'; 0201 } 0202 0203 Imap::Parser::Rfc5322HeaderParser parser; 0204 bool res = parser.parse(data); 0205 if (!res) { 0206 qDebug() << "Parsing error."; 0207 return 1; 0208 } 0209 0210 qDebug() << "References:" << parser.references; 0211 0212 return 0; 0213 } 0214 #endif