#include "__IMAP_LIST.h" #include "IMAPArgs.h" #include "IMAPServer.h" namespace mail { bool imapListPatternMatch(const std::string &pattern, const std::string &name) { size_t p = 0, n = 0, star = std::string::npos, matchPos = 0; while (n < name.size()) { if (p < pattern.size() && pattern[p] == name[n]) { ++p; ++n; } else if (p < pattern.size() && (pattern[p] == '*' || pattern[p] == '%')) { star = p; matchPos = n; ++p; } else if (star != std::string::npos) { p = star + 1; ++matchPos; n = matchPos; } else { return false; } } while (p < pattern.size() && (pattern[p] == '*' || pattern[p] == '%')) ++p; return p == pattern.size(); } int __IMAP_LIST::processCommand(coreutils::ZString &request, IMAPSession &session, IMAPServer &server) { if (session.state == IMAPSession::NOT_AUTHENTICATED) { session.out << session.tag << " NO Not authenticated" << CRLF; return 1; } IMAPArgs::nextArgument(request); // reference name - unused, no folder hierarchy to resolve against coreutils::ZString patArg = IMAPArgs::nextArgument(request); std::string pattern = IMAPArgs::unwrap(patArg); if (pattern.empty()) { // RFC 3501 6.3.8: an empty mailbox name means "return the // hierarchy delimiter and the root name only". session.out << "* LIST (\\Noselect) \"/\" \"\"" << CRLF; session.out << session.tag << " OK LIST completed" << CRLF; return 1; } coreutils::ZString userNameZ(session.userName); for (coreutils::MString &folder : server.mailFileSystem.listFolders(userNameZ)) { std::string name = folder.str(); if (imapListPatternMatch(pattern, name)) session.out << "* LIST (\\HasNoChildren) \"/\" \"" << name << "\"" << CRLF; } session.out << session.tag << " OK LIST completed" << CRLF; return 1; } }