13#include <QMimeDatabase>
14#include <QRegularExpression>
18using namespace KMime::Parser;
27 , m_boundary(boundary)
31bool MultiPart::parse()
43 if ((pos1 = m_src.indexOf(b, pos1)) == -1 || pos1 == 0 ||
44 m_src[pos1 - 1] ==
'\n') {
52 if (m_src[pos1] ==
'-' && m_src[pos1 + 1] ==
'-') {
56 }
else if ((pos1 - blen) > 1) {
57 m_preamble = m_src.left(pos1 - blen - 1);
61 while (pos1 > -1 && pos2 > -1) {
64 if ((pos1 = m_src.indexOf(
'\n', pos1)) > -1) {
69 if ((pos2 = m_src.indexOf(b, pos2)) == -1 ||
70 m_src[pos2 - 1] ==
'\n') {
77 part = m_src.
mid(pos1, m_src.length() - pos1);
82 part = m_src.
mid(pos1, pos2 - pos1 - 1);
85 if (m_src[pos2] ==
'-' && m_src[pos2 + 1] ==
'-') {
88 if ((pos1 = m_src.indexOf(
'\n', pos1)) > -1) {
90 m_epilouge = m_src.mid(pos1 + 1, m_src.length() - pos1 - 1);
101 return !m_parts.isEmpty();
106NonMimeParser::NonMimeParser(
const QByteArray &src) :
107 m_src(src), m_partNr(-1), m_totalNr(-1)
111NonMimeParser::~NonMimeParser() =
default;
115[[nodiscard]]
static qsizetype findUuencodeBeginMarker(
const QByteArray &s, qsizetype startPos)
119 idx = s.indexOf(
"begin ", idx);
120 if (idx < 0 || idx + 9 >= s.size()) {
123 if (std::isdigit(s[idx + 6]) && std::isdigit(s[idx + 7]) && std::isdigit(s[idx + 8])) {
132 NonMimeParser(src), m_head(head)
135bool UUEncoded::parse()
137 qsizetype currentPos = 0;
139 bool firstIteration =
true;
142 qsizetype beginPos = currentPos;
143 qsizetype uuStart = currentPos;
144 qsizetype endPos = 0;
149 bool containsBegin =
false;
150 bool containsEnd =
false;
154 if ((beginPos = findUuencodeBeginMarker(m_src, currentPos)) > -1 &&
155 (beginPos == 0 || m_src.at(beginPos - 1) ==
'\n')) {
156 containsBegin =
true;
157 uuStart = m_src.indexOf(
'\n', beginPos);
165 beginPos = currentPos;
168 if (!containsBegin || (endPos = m_src.indexOf(
"\nend", (uuStart > 0) ? uuStart - 1 : 0)) == -1) {
169 endPos = m_src.length();
174 if ((containsBegin && containsEnd) || firstIteration) {
178 for (
auto idx = uuStart; idx < endPos; idx++) {
179 if (m_src.at(idx) ==
'\n') {
181 if (idx + 1 < endPos && m_src.at(idx + 1) ==
'M') {
188 if ((lineCount - MCount) > 10) {
196 if (MCount == 0 || (lineCount - MCount) > 10 || ((!containsBegin || !containsEnd) && (MCount < 15))) {
202 const auto subject = KMime::extractHeader(m_head,
"Subject");
203 if ((!containsBegin || !containsEnd) && !subject.isNull()) {
207 pos =
match.capturedStart(0);
208 len =
match.capturedLength(0);
210 tmp = subject.
mid(pos, len);
222 m_text.append(m_src.mid(currentPos, beginPos - currentPos));
227 fileName = m_src.
mid(beginPos + 10, uuStart - beginPos - 11);
231 m_filenames.append(fileName);
233 m_bins.append(m_src.mid(uuStart, endPos - uuStart + 1));
236 firstIteration =
false;
238 auto next = m_src.indexOf(
'\n', endPos + 1);
253 if (!m_bins.isEmpty() || isPartial()) {
254 m_text.append(m_src.right(m_src.length() - currentPos));
263YENCEncoded::YENCEncoded(
const QByteArray &src) :
273 auto iPos = src.
indexOf(sought);
275 auto pos1 = src.
indexOf(
' ', iPos);
276 auto pos2 = src.
indexOf(
'\r', iPos);
277 auto pos3 = src.
indexOf(
'\t', iPos);
278 auto pos4 = src.
indexOf(
'\n', iPos);
279 if (pos2 >= 0 && (pos1 < 0 || pos1 > pos2)) {
282 if (pos3 >= 0 && (pos1 < 0 || pos1 > pos3)) {
285 if (pos4 >= 0 && (pos1 < 0 || pos1 > pos4)) {
290 char c = src.
at(iPos);
291 if (c >=
'0' && c <=
'9') {
293 *value = src.
mid(iPos, pos1 - iPos).
toInt();
300bool YENCEncoded::parse()
302 qsizetype currentPos = 0;
305 qsizetype beginPos = currentPos;
306 qsizetype yencStart = currentPos;
307 bool containsPart =
false;
310 if ((beginPos = m_src.indexOf(
"=ybegin ", currentPos)) > -1 &&
311 (beginPos == 0 || m_src.at(beginPos - 1) ==
'\n')) {
312 yencStart = m_src.indexOf(
'\n', beginPos);
313 if (yencStart == -1) {
318 if (m_src.indexOf(
"=ypart", yencStart) == yencStart) {
320 yencStart = m_src.indexOf(
'\n', yencStart);
321 if (yencStart == -1) {
332 qsizetype namePos = meta.
indexOf(
"name=");
337 qsizetype eolPos = meta.
indexOf(
'\r', namePos);
339 eolPos = meta.
indexOf(
'\n', namePos);
345 fileName = meta.
mid(namePos + 5, eolPos - (namePos + 5));
349 if (!yencMeta(meta,
"line", ¥cLine)) {
354 if (!yencMeta(meta,
"size", ¥cSize)) {
362 if (!yencMeta(meta,
"part", &m_partNr)) {
366 if (!yencMeta(meta,
"begin", &partBegin) ||
367 !yencMeta(meta,
"end", &partEnd)) {
371 if (!yencMeta(meta,
"total", &m_totalNr)) {
372 m_totalNr = m_partNr + 1;
374 if (yencSize == partEnd - partBegin + 1) {
377 yencSize = partEnd - partBegin + 1;
383 qsizetype pos = yencStart;
384 qsizetype len = m_src.
length();
385 bool lineStart =
true;
387 bool containsEnd =
false;
391 int ch = m_src.at(pos);
396 if (lineLength != yencLine && totalSize != yencSize) {
400 }
else if (ch ==
'\n') {
407 ch = m_src.at(pos + 1);
408 if (lineStart && ch ==
'y') {
417 if (totalSize >= yencSize) {
420 binary[totalSize++] = ch;
430 if (totalSize >= yencSize) {
433 binary[totalSize++] = ch;
445 if (totalSize != yencSize) {
451 eolPos = m_src.indexOf(
'\n', pos);
456 meta = m_src.
mid(pos, eolPos - pos);
457 if (!yencMeta(meta,
"size", &totalSize)) {
461 if (totalSize != yencSize) {
466 m_filenames.
append(fileName);
469 m_bins.append(binary);
473 m_text.append(m_src.mid(currentPos, beginPos - currentPos));
475 currentPos = eolPos + 1;
483 if (!m_bins.isEmpty()) {
484 m_text.append(m_src.right(m_src.length() - currentPos));
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QString name(StandardAction id)
const QList< QKeySequence > & next()
QByteArray & append(QByteArrayView data)
char at(qsizetype i) const const
qsizetype indexOf(QByteArrayView bv, qsizetype from) const const
qsizetype lastIndexOf(QByteArrayView bv) const const
QByteArray left(qsizetype len) const const
qsizetype length() const const
QByteArray mid(qsizetype pos, qsizetype len) const const
void resize(qsizetype newSize, char c)
QByteArray right(qsizetype len) const const
int toInt(bool *ok, int base) const const
QMimeType mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const const
QString fromUtf8(QByteArrayView str)