Skip to content

Commit

Permalink
chore: improve code style
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-virkus committed Jan 13, 2024
1 parent b4d3a06 commit 74fda6e
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 168 deletions.
342 changes: 182 additions & 160 deletions lib/src/private/imap/list_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import 'status_parser.dart';
/// Parses `LIST` and `LSUB` responses
class ListParser extends ResponseParser<List<Mailbox>> {
/// Creates a new parser
ListParser(this.info,
{bool isLsubParser = false,
this.isExtended = false,
bool hasReturnOptions = false})
: startSequence = isLsubParser ? 'LSUB ' : 'LIST ',
ListParser(
this.info, {
bool isLsubParser = false,
this.isExtended = false,
bool hasReturnOptions = false,
}) : startSequence = isLsubParser ? 'LSUB ' : 'LIST ',
// Return options are available only for LIST responses.
_hasReturnOptions = !isLsubParser && hasReturnOptions;

Expand All @@ -34,168 +35,20 @@ class ListParser extends ResponseParser<List<Mailbox>> {

@override
List<Mailbox>? parse(
ImapResponse? imapResponse, Response<List<Mailbox>> response) =>
ImapResponse? imapResponse,
Response<List<Mailbox>> response,
) =>
response.isOkStatus ? boxes : null;

@override
bool parseUntagged(
ImapResponse imapResponse, Response<List<Mailbox>>? response) {
ImapResponse imapResponse,
Response<List<Mailbox>>? response,
) {
final parseText = imapResponse.parseText;
if (parseText.startsWith(startSequence)) {
final boxFlags = <MailboxFlag>[];
var listDetails = parseText.substring(startSequence.length);
final flagsStartIndex = listDetails.indexOf('(');
final flagsEndIndex = listDetails.indexOf(')');
if (flagsStartIndex != -1 && flagsStartIndex < flagsEndIndex) {
if (flagsStartIndex < flagsEndIndex - 1) {
// there are actually flags, not an empty ()
final flagsText = listDetails
.substring(flagsStartIndex + 1, flagsEndIndex)
.toLowerCase();
final flagNames = flagsText.split(' ');
for (final flagName in flagNames) {
switch (flagName) {
case r'\hasnochildren':
boxFlags.add(MailboxFlag.hasNoChildren);
break;
case r'\haschildren':
boxFlags.add(MailboxFlag.hasChildren);
break;
case r'\unmarked':
boxFlags.add(MailboxFlag.unMarked);
break;
case r'\marked':
boxFlags.add(MailboxFlag.marked);
break;
case r'\noselect':
boxFlags.add(MailboxFlag.noSelect);
break;
case r'\select':
boxFlags.add(MailboxFlag.select);
break;
case r'\noinferiors':
boxFlags.add(MailboxFlag.noInferior);
if (isExtended) {
boxFlags.add(MailboxFlag.hasNoChildren);
}
break;
case r'\nonexistent':
boxFlags.add(MailboxFlag.nonExistent);
if (isExtended) {
boxFlags.add(MailboxFlag.noSelect);
}
break;
case r'\subscribed':
boxFlags.add(MailboxFlag.subscribed);
break;
case r'\remote':
boxFlags.add(MailboxFlag.remote);
break;
case r'\all':
boxFlags.add(MailboxFlag.all);
break;
case r'\inbox':
boxFlags.add(MailboxFlag.inbox);
break;
case r'\sent':
boxFlags.add(MailboxFlag.sent);
break;
case r'\drafts':
boxFlags.add(MailboxFlag.drafts);
break;
case r'\junk':
boxFlags.add(MailboxFlag.junk);
break;
case r'\trash':
boxFlags.add(MailboxFlag.trash);
break;
case r'\archive':
boxFlags.add(MailboxFlag.archive);
break;
case r'\flagged':
boxFlags.add(MailboxFlag.flagged);
break;
// X-List flags:
case r'\allmail':
boxFlags.add(MailboxFlag.all);
break;
case r'\important':
boxFlags.add(MailboxFlag.flagged);
break;
case r'\spam':
boxFlags.add(MailboxFlag.junk);
break;
case r'\starred':
boxFlags.add(MailboxFlag.flagged);
break;
_parseBoxFlags(parseText);

default:
print('encountered unexpected flag: [$flagName]');
}
}
}
listDetails = listDetails.substring(flagsEndIndex + 2);
}
// Parses extended data
final boxExtendedData = <String, List<String>>{};
if (isExtended) {
final extraInfoStartIndex = listDetails.indexOf('(');
final extraInfoEndIndex = listDetails.lastIndexOf(')');
if (extraInfoEndIndex != -1 &&
extraInfoStartIndex < extraInfoEndIndex) {
final extraInfo =
listDetails.substring(extraInfoStartIndex + 1, extraInfoEndIndex);
listDetails = listDetails.substring(0, extraInfoStartIndex - 1);
// Convert to loop if more extended data results will be present
//todo Address when multiple extended data list are returned
// by non conforming servers while (extraInfo.isNotEmpty)
if (extraInfo.startsWith(ExtendedData.childinfo) ||
extraInfo.startsWith('"${ExtendedData.childinfo}"')) {
final childInfo = boxExtendedData[ExtendedData.childinfo] ?? [];
if (!boxExtendedData.containsKey(ExtendedData.childinfo)) {
boxExtendedData[ExtendedData.childinfo] = childInfo;
}
final optsStartIndex = extraInfo.indexOf('(');
final optsEndIndex = extraInfo.indexOf(')');
if (optsStartIndex != -1 && optsStartIndex < optsEndIndex) {
final opts = extraInfo
.substring(optsStartIndex + 1, optsEndIndex)
.split(' ')
.map((e) => e.substring(1, e.length - 1));
childInfo.addAll(opts);
}
}
}
}
if (listDetails.startsWith('"')) {
final endOfPathSeparatorIndex = listDetails.indexOf('"', 1);
if (endOfPathSeparatorIndex != -1) {
final separator = listDetails.substring(1, endOfPathSeparatorIndex);
info.pathSeparator = separator;
listDetails = listDetails.substring(endOfPathSeparatorIndex + 2);
}
}
if (listDetails.startsWith('"')) {
listDetails = listDetails.substring(1, listDetails.length - 1);
}
final boxPath = listDetails;
// Maybe was requested only the hierarchy separator without reference name
if (listDetails.length > 2 && info.pathSeparator != null) {
final lastPathSeparatorIndex = listDetails.lastIndexOf(
info.pathSeparator!, listDetails.length - 2);
if (lastPathSeparatorIndex != -1) {
listDetails = listDetails.substring(lastPathSeparatorIndex + 1);
}
}
final boxName = listDetails;
final box = Mailbox(
encodedName: boxName,
encodedPath: boxPath,
flags: boxFlags,
pathSeparator: info.pathSeparator ?? '/',
extendedData: boxExtendedData,
);
boxes.add(box);
return true;
} else if (_hasReturnOptions) {
if (parseText.startsWith('NO')) {
Expand All @@ -209,9 +62,178 @@ class ListParser extends ResponseParser<List<Mailbox>> {
final parser = StatusParser(boxes.last);
// ignore: cascade_invocations
parser.parseUntagged(imapResponse, null);

return true;
}
}

return super.parseUntagged(imapResponse, response);
}

void _parseBoxFlags(String parseText) {
final boxFlags = <MailboxFlag>[];
var listDetails = parseText.substring(startSequence.length);
final flagsStartIndex = listDetails.indexOf('(');
final flagsEndIndex = listDetails.indexOf(')');
if (flagsStartIndex != -1 && flagsStartIndex < flagsEndIndex) {
_addFlags(flagsStartIndex, flagsEndIndex, listDetails, boxFlags);
listDetails = listDetails.substring(flagsEndIndex + 2);
}
// Parses extended data
final boxExtendedData = <String, List<String>>{};
if (isExtended) {
final extraInfoStartIndex = listDetails.indexOf('(');
final extraInfoEndIndex = listDetails.lastIndexOf(')');
if (extraInfoEndIndex != -1 && extraInfoStartIndex < extraInfoEndIndex) {
final extraInfo =
listDetails.substring(extraInfoStartIndex + 1, extraInfoEndIndex);
listDetails = listDetails.substring(0, extraInfoStartIndex - 1);
// Convert to loop if more extended data results will be present
//todo Address when multiple extended data list are returned
// by non conforming servers while (extraInfo.isNotEmpty)
if (extraInfo.startsWith(ExtendedData.childinfo) ||
extraInfo.startsWith('"${ExtendedData.childinfo}"')) {
final childInfo = boxExtendedData[ExtendedData.childinfo] ?? [];
if (!boxExtendedData.containsKey(ExtendedData.childinfo)) {
boxExtendedData[ExtendedData.childinfo] = childInfo;
}
final optsStartIndex = extraInfo.indexOf('(');
final optsEndIndex = extraInfo.indexOf(')');
if (optsStartIndex != -1 && optsStartIndex < optsEndIndex) {
final opts = extraInfo
.substring(optsStartIndex + 1, optsEndIndex)
.split(' ')
.map((e) => e.substring(1, e.length - 1));
childInfo.addAll(opts);
}
}
}
}
if (listDetails.startsWith('"')) {
final endOfPathSeparatorIndex = listDetails.indexOf('"', 1);
if (endOfPathSeparatorIndex != -1) {
final separator = listDetails.substring(1, endOfPathSeparatorIndex);
info.pathSeparator = separator;
listDetails = listDetails.substring(endOfPathSeparatorIndex + 2);
}
}
if (listDetails.startsWith('"')) {
listDetails = listDetails.substring(1, listDetails.length - 1);
}
final boxPath = listDetails;
// Maybe was requested only the hierarchy separator without reference name
if (listDetails.length > 2 && info.pathSeparator != null) {
final lastPathSeparatorIndex = listDetails.lastIndexOf(
info.pathSeparator ?? '/',
listDetails.length - 2,
);
if (lastPathSeparatorIndex != -1) {
listDetails = listDetails.substring(lastPathSeparatorIndex + 1);
}
}
final boxName = listDetails;
final box = Mailbox(
encodedName: boxName,
encodedPath: boxPath,
flags: boxFlags,
pathSeparator: info.pathSeparator ?? '/',
extendedData: boxExtendedData,
);
boxes.add(box);
}

void _addFlags(
int flagsStartIndex,
int flagsEndIndex,
String listDetails,
List<MailboxFlag> boxFlags,
) {
if (flagsStartIndex < flagsEndIndex - 1) {
// there are actually flags, not an empty ()
final flagsText = listDetails
.substring(flagsStartIndex + 1, flagsEndIndex)
.toLowerCase();
final flagNames = flagsText.split(' ');
for (final flagName in flagNames) {
switch (flagName) {
case r'\hasnochildren':
boxFlags.add(MailboxFlag.hasNoChildren);
break;
case r'\haschildren':
boxFlags.add(MailboxFlag.hasChildren);
break;
case r'\unmarked':
boxFlags.add(MailboxFlag.unMarked);
break;
case r'\marked':
boxFlags.add(MailboxFlag.marked);
break;
case r'\noselect':
boxFlags.add(MailboxFlag.noSelect);
break;
case r'\select':
boxFlags.add(MailboxFlag.select);
break;
case r'\noinferiors':
boxFlags.add(MailboxFlag.noInferior);
if (isExtended) {
boxFlags.add(MailboxFlag.hasNoChildren);
}
break;
case r'\nonexistent':
boxFlags.add(MailboxFlag.nonExistent);
if (isExtended) {
boxFlags.add(MailboxFlag.noSelect);
}
break;
case r'\subscribed':
boxFlags.add(MailboxFlag.subscribed);
break;
case r'\remote':
boxFlags.add(MailboxFlag.remote);
break;
case r'\all':
boxFlags.add(MailboxFlag.all);
break;
case r'\inbox':
boxFlags.add(MailboxFlag.inbox);
break;
case r'\sent':
boxFlags.add(MailboxFlag.sent);
break;
case r'\drafts':
boxFlags.add(MailboxFlag.drafts);
break;
case r'\junk':
boxFlags.add(MailboxFlag.junk);
break;
case r'\trash':
boxFlags.add(MailboxFlag.trash);
break;
case r'\archive':
boxFlags.add(MailboxFlag.archive);
break;
case r'\flagged':
boxFlags.add(MailboxFlag.flagged);
break;
// X-List flags:
case r'\allmail':
boxFlags.add(MailboxFlag.all);
break;
case r'\important':
boxFlags.add(MailboxFlag.flagged);
break;
case r'\spam':
boxFlags.add(MailboxFlag.junk);
break;
case r'\starred':
boxFlags.add(MailboxFlag.flagged);
break;

default:
print('encountered unexpected flag: [$flagName]');
}
}
}
}
}
Loading

0 comments on commit 74fda6e

Please sign in to comment.