📄 pop3store.cpp
字号:
throw; } if (challenge) delete [] challenge; if (resp) delete [] resp; break; } default: cont = false; break; } } } throw exceptions::authentication_error ("Could not authenticate using SASL: all mechanisms failed.");}#endif // VMIME_HAVE_SASL_SUPPORT#if VMIME_HAVE_TLS_SUPPORTvoid POP3Store::startTLS(){ try { sendRequest("STLS"); string response; readResponse(response, false); if (getResponseCode(response) != RESPONSE_OK) throw exceptions::command_error("STLS", response); ref <tls::TLSSession> tlsSession = vmime::create <tls::TLSSession>(getCertificateVerifier()); ref <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(m_timeoutHandler); m_socket = tlsSocket; m_secured = true; m_cntInfos = vmime::create <tls::TLSSecuredConnectionInfos> (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); } catch (exceptions::command_error&) { // Non-fatal error throw; } catch (exception&) { // Fatal error internalDisconnect(); throw; }}#endif // VMIME_HAVE_TLS_SUPPORTbool POP3Store::isConnected() const{ return (m_socket && m_socket->isConnected() && m_authentified);}bool POP3Store::isSecuredConnection() const{ return m_secured;}ref <connectionInfos> POP3Store::getConnectionInfos() const{ return m_cntInfos;}void POP3Store::disconnect(){ if (!isConnected()) throw exceptions::not_connected(); internalDisconnect();}void POP3Store::internalDisconnect(){ for (std::list <POP3Folder*>::iterator it = m_folders.begin() ; it != m_folders.end() ; ++it) { (*it)->onStoreDisconnected(); } m_folders.clear(); try { sendRequest("QUIT"); } catch (exception&) { // Not important } m_socket->disconnect(); m_socket = NULL; m_timeoutHandler = NULL; m_authentified = false; m_secured = false; m_cntInfos = NULL;}void POP3Store::noop(){ sendRequest("NOOP"); string response; readResponse(response, false); if (!isSuccessResponse(response)) throw exceptions::command_error("NOOP", response);}const std::vector <string> POP3Store::getCapabilities(){ sendRequest("CAPA"); string response; readResponse(response, true); std::vector <string> res; if (isSuccessResponse(response)) { stripFirstLine(response, response); std::istringstream iss(response); string line; while (std::getline(iss, line, '\n')) res.push_back(utility::stringUtils::trim(line)); } return res;}bool POP3Store::isSuccessResponse(const string& buffer){ return getResponseCode(buffer) == RESPONSE_OK;}bool POP3Store::stripFirstLine(const string& buffer, string& result, string* firstLine){ const string::size_type end = buffer.find('\n'); if (end != string::npos) { if (firstLine) *firstLine = buffer.substr(0, end); result = buffer.substr(end + 1); return (true); } else { result = buffer; return (false); }}int POP3Store::getResponseCode(const string& buffer){ if (buffer.length() >= 2) { // +[space] if (buffer[0] == '+' && (buffer[1] == ' ' || buffer[1] == '\t')) { return RESPONSE_READY; } // +OK if (buffer.length() >= 3) { if (buffer[0] == '+' && (buffer[1] == 'O' || buffer[1] == 'o') && (buffer[2] == 'K' || buffer[1] == 'k')) { return RESPONSE_OK; } } } // -ERR or whatever return RESPONSE_ERR;}void POP3Store::stripResponseCode(const string& buffer, string& result){ const string::size_type pos = buffer.find_first_of(" \t"); if (pos != string::npos) result = buffer.substr(pos + 1); else result = buffer;}void POP3Store::sendRequest(const string& buffer, const bool end){ if (end) m_socket->send(buffer + "\r\n"); else m_socket->send(buffer);}void POP3Store::readResponse(string& buffer, const bool multiLine, utility::progressListener* progress){ bool foundTerminator = false; int current = 0, total = 0; if (progress) progress->start(total); if (m_timeoutHandler) m_timeoutHandler->resetTimeOut(); buffer.clear(); string::value_type last1 = '\0', last2 = '\0'; for ( ; !foundTerminator ; ) {#if 0 // not supported // Check for possible cancellation if (progress && progress->cancel()) throw exceptions::operation_cancelled();#endif // Check whether the time-out delay is elapsed if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { if (!m_timeoutHandler->handleTimeOut()) throw exceptions::operation_timed_out(); m_timeoutHandler->resetTimeOut(); } // Receive data from the socket string receiveBuffer; m_socket->receive(receiveBuffer); if (receiveBuffer.empty()) // buffer is empty { platform::getHandler()->wait(); continue; } // We have received data: reset the time-out counter if (m_timeoutHandler) m_timeoutHandler->resetTimeOut(); // Check for transparent characters: '\n..' becomes '\n.' const string::value_type first = receiveBuffer[0]; if (first == '.' && last2 == '\n' && last1 == '.') { receiveBuffer.erase(receiveBuffer.begin()); } else if (receiveBuffer.length() >= 2 && first == '.' && receiveBuffer[1] == '.' && last1 == '\n') { receiveBuffer.erase(receiveBuffer.begin()); } for (string::size_type trans ; string::npos != (trans = receiveBuffer.find("\n..")) ; ) { receiveBuffer.replace(trans, 3, "\n."); } last1 = receiveBuffer[receiveBuffer.length() - 1]; last2 = static_cast <char>((receiveBuffer.length() >= 2) ? receiveBuffer[receiveBuffer.length() - 2] : 0); // Append the data to the response buffer buffer += receiveBuffer; current += receiveBuffer.length(); // Check for terminator string (and strip it if present) foundTerminator = checkTerminator(buffer, multiLine); // Notify progress if (progress) { total = std::max(total, current); progress->progress(current, total); } // If there is an error (-ERR) when executing a command that // requires a multi-line response, the error response will // include only one line, so we stop waiting for a multi-line // terminator and check for a "normal" one. if (multiLine && !foundTerminator && buffer.length() >= 4 && buffer[0] == '-') { foundTerminator = checkTerminator(buffer, false); } } if (progress) progress->stop(total);}void POP3Store::readResponse(utility::outputStream& os, utility::progressListener* progress, const int predictedSize){ int current = 0, total = predictedSize; string temp; bool codeDone = false; if (progress) progress->start(total); if (m_timeoutHandler) m_timeoutHandler->resetTimeOut(); utility::inputStreamSocketAdapter sis(*m_socket); utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n"); utility::dotFilteredInputStream dfis(sfis2); // "\n.." --> "\n." utility::inputStream& is = dfis; while (!is.eof()) {#if 0 // not supported // Check for possible cancellation if (progress && progress->cancel()) throw exceptions::operation_cancelled();#endif // Check whether the time-out delay is elapsed if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { if (!m_timeoutHandler->handleTimeOut()) throw exceptions::operation_timed_out(); } // Receive data from the socket utility::stream::value_type buffer[65536]; const utility::stream::size_type read = is.read(buffer, sizeof(buffer)); if (read == 0) // buffer is empty { platform::getHandler()->wait(); continue; } // We have received data: reset the time-out counter if (m_timeoutHandler) m_timeoutHandler->resetTimeOut(); // If we don't have extracted the response code yet if (!codeDone) { temp += string(buffer, read); string firstLine; if (stripFirstLine(temp, temp, &firstLine) == true) { if (!isSuccessResponse(firstLine)) throw exceptions::command_error("?", firstLine); codeDone = true; os.write(temp.data(), temp.length()); temp.clear(); continue; } } else { // Inject the data into the output stream os.write(buffer, read); current += read; // Notify progress if (progress) { total = std::max(total, current); progress->progress(current, total); } } } if (progress) progress->stop(total);}bool POP3Store::checkTerminator(string& buffer, const bool multiLine){ // Multi-line response if (multiLine) { static const string term1("\r\n.\r\n"); static const string term2("\n.\n"); return (checkOneTerminator(buffer, term1) || checkOneTerminator(buffer, term2)); } // Normal response else { static const string term1("\r\n"); static const string term2("\n"); return (checkOneTerminator(buffer, term1) || checkOneTerminator(buffer, term2)); } return (false);}bool POP3Store::checkOneTerminator(string& buffer, const string& term){ if (buffer.length() >= term.length() && std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) { buffer.erase(buffer.end() - term.length(), buffer.end()); return (true); } return (false);}void POP3Store::registerFolder(POP3Folder* folder){ m_folders.push_back(folder);}void POP3Store::unregisterFolder(POP3Folder* folder){ std::list <POP3Folder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); if (it != m_folders.end()) m_folders.erase(it);}int POP3Store::getCapabilities() const{ return (CAPABILITY_DELETE_MESSAGE);}// Service infosPOP3ServiceInfos POP3Store::sm_infos(false);const serviceInfos& POP3Store::getInfosInstance(){ return sm_infos;}const serviceInfos& POP3Store::getInfos() const{ return sm_infos;}} // pop3} // net} // vmime
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -