#include "POP3Command.h" #include namespace mail { MailFolder::Message *pop3FindMessage(POP3Session &session, int msgNum) { const std::vector &messages = session.mailbox.messages(); if (msgNum < 1 || (size_t)msgNum > messages.size()) return nullptr; if (session.deletedMarks.count(msgNum) > 0) return nullptr; return session.mailbox.find(messages[msgNum - 1].uid); } void pop3SendMessage(POP3Session &session, const std::string &content, int maxBodyLines) { size_t pos = 0; bool inBody = false; int bodyLinesSent = 0; while (pos <= content.size()) { size_t next = content.find("\r\n", pos); std::string line = (next == std::string::npos) ? content.substr(pos) : content.substr(pos, next - pos); bool isBlank = line.empty(); if (inBody && maxBodyLines >= 0 && bodyLinesSent >= maxBodyLines) break; if (!line.empty() && line[0] == '.') session.out << "." << line << CRLF; else session.out << line << CRLF; if (inBody) ++bodyLinesSent; if (isBlank && !inBody) inBody = true; if (next == std::string::npos) break; pos = next + 2; } session.out << "." << CRLF; } int POP3Command::processCommand(coreutils::ZString &request, core::TCPSession &session) { // Same bug, same fix as IMAPCommand::processCommand's own doc // comment: session.server is a TCPServer* pointer, and casting // the pointer VALUE directly to a reference type reinterprets the // pointer FIELD'S OWN memory location as the object, not what it // points to. Dereference first. // ZString's copy constructor (ZString.cpp) copies data/length/ // cursor but NOT `list` - and the specific-handler overload just // below takes request BY VALUE, so every POP3 handler's `request` // is such a copy. request[N] (backed by `list`, populated by // CommandList::processRequest()'s own request.split() call before // dispatch) would therefore index into an empty vector - out of // bounds, the same class of bug as MailFileSystem::getMailBoxPath() // had for mailbox[1] before this session's IMAP work fixed it. // POP3 handlers must read arguments off the (correctly-copied) // cursor instead, via getTokenExclude()/skipWhitespace() - which // is also why the command word needs stripping here first, same // reasoning as IMAPCommand::processCommand's own doc comment: // request.reset() (CommandList::processRequest) leaves the cursor // at the true start of the line, still including the command // word itself. request.getTokenExclude(" "); return processCommand(request, (POP3Session &)session, (POP3Server &)(*session.server)); } int POP3Command::processCommand(coreutils::ZString request, POP3Session &session, POP3Server &server) { return 0; } }