Archived
1
0
This repository has been archived on 2023-08-12. You can view files and clone it, but cannot push or open issues or pull requests.
nntpchan/contrib/backends/nntpchan-daemon/libnntpchan/nntp_handler.cpp

220 lines
4.9 KiB
C++
Raw Normal View History

2016-10-15 21:37:59 +05:00
#include "nntp_handler.hpp"
#include "sanitize.hpp"
2016-10-15 21:37:59 +05:00
#include <algorithm>
#include <cctype>
2017-05-03 22:33:04 +05:00
#include <cstring>
2016-10-15 21:37:59 +05:00
#include <string>
#include <sstream>
#include <iostream>
namespace nntpchan
{
NNTPServerHandler::NNTPServerHandler(const std::string & storage) :
2017-05-03 17:09:23 +05:00
LineReader(1024),
2017-05-03 22:33:04 +05:00
m_article(nullptr),
2016-10-15 22:53:35 +05:00
m_auth(nullptr),
2016-10-15 21:37:59 +05:00
m_store(storage),
m_authed(false),
m_state(eStateReadCommand)
{
}
2016-10-15 22:53:35 +05:00
NNTPServerHandler::~NNTPServerHandler()
{
}
2017-04-14 15:24:53 +05:00
2016-10-15 21:37:59 +05:00
void NNTPServerHandler::HandleLine(const std::string &line)
{
2017-05-03 22:33:04 +05:00
if(m_state == eStateReadCommand)
{
2016-10-15 21:37:59 +05:00
std::deque<std::string> command;
std::istringstream s;
s.str(line);
for (std::string part; std::getline(s, part, ' '); ) {
2017-10-09 21:51:49 +05:00
if(part.size()) command.push_back(part);
2016-10-15 21:37:59 +05:00
}
if(command.size())
HandleCommand(command);
else
QueueLine("501 Syntax error");
}
2017-05-03 22:33:04 +05:00
else if(m_state == eStateStoreArticle)
{
2017-05-04 03:31:19 +05:00
std::string l = line + "\r\n";
OnData(l.c_str(), l.size());
2017-05-03 22:33:04 +05:00
}
else
{
std::cerr << "invalid state" << std::endl;
}
2016-10-15 21:37:59 +05:00
}
2017-05-03 18:44:42 +05:00
void NNTPServerHandler::OnData(const char * data, ssize_t l)
{
2017-05-03 22:33:04 +05:00
if(l <= 0 ) return;
if(m_state == eStateStoreArticle)
{
2017-05-04 03:31:19 +05:00
const char * end = strstr(data, "\r\n.\r\n");
2017-05-03 22:33:04 +05:00
if(end)
{
std::size_t diff = end - data ;
if(m_article)
2017-10-09 21:51:49 +05:00
{
2017-05-04 03:31:19 +05:00
m_article->write(data, diff+2);
2017-10-09 21:51:49 +05:00
m_article->flush();
}
2017-05-03 22:33:04 +05:00
ArticleObtained();
diff += 5;
2017-05-04 03:31:19 +05:00
Data(end+5, l-diff);
2017-05-03 22:33:04 +05:00
return;
}
if(m_article)
2017-10-09 21:51:49 +05:00
{
2017-05-03 22:33:04 +05:00
m_article->write(data, l);
2017-10-09 21:51:49 +05:00
m_article->flush();
}
2017-05-03 22:33:04 +05:00
}
else
Data(data, l);
2017-05-03 18:44:42 +05:00
}
2016-10-15 21:37:59 +05:00
void NNTPServerHandler::HandleCommand(const std::deque<std::string> & command)
{
auto cmd = command[0];
2017-05-03 20:01:32 +05:00
std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::toupper);
2016-10-15 21:37:59 +05:00
std::size_t cmdlen = command.size();
2017-05-03 22:33:04 +05:00
for(const auto & part : command)
std::cerr << " " << part;
std::cerr << std::endl;
2016-10-15 21:37:59 +05:00
if (cmd == "QUIT") {
Quit();
return;
2017-05-03 22:33:04 +05:00
}
else if (cmd[0] == '5')
{
return;
}
else if (cmd == "MODE" ) {
2017-05-03 20:01:32 +05:00
if(cmdlen == 2) {
2016-10-15 21:37:59 +05:00
// set mode
SwitchMode(command[1]);
} else if(cmdlen) {
// too many arguments
2017-05-03 20:01:32 +05:00
QueueLine("500 too many arguments");
2016-10-15 21:37:59 +05:00
} else {
// get mode
2017-05-03 20:01:32 +05:00
QueueLine("500 wrong arguments");
2016-10-15 21:37:59 +05:00
}
2017-05-03 22:33:04 +05:00
} else if(cmd == "CAPABILITIES") {
QueueLine("101 I support the following:");
QueueLine("READER");
QueueLine("IMPLEMENTATION nntpchan-daemon");
QueueLine("VERSION 2");
QueueLine("STREAMING");
QueueLine(".");
} else if (cmd == "CHECK") {
if(cmdlen == 2) {
const std::string & msgid = command[1];
if(IsValidMessageID(msgid) && m_store.Accept(msgid))
{
QueueLine("238 "+msgid);
return;
}
QueueLine("438 "+msgid);
}
else
QueueLine("501 syntax error");
} else if (cmd == "TAKETHIS") {
if (cmdlen == 2)
{
const std::string & msgid = command[1];
if(m_store.Accept(msgid))
{
m_article = m_store.OpenWrite(msgid);
}
m_articleName = msgid;
EnterState(eStateStoreArticle);
return;
}
QueueLine("501 invalid syntax");
2016-10-15 21:37:59 +05:00
} else {
// unknown command
QueueLine("500 Unknown Command");
}
}
2017-05-03 22:33:04 +05:00
void NNTPServerHandler::ArticleObtained()
{
if(m_article)
{
m_article->close();
m_article = nullptr;
QueueLine("239 "+m_articleName);
std::cerr << "stored " << m_articleName << std::endl;
}
else
QueueLine("439 "+m_articleName);
m_articleName = "";
EnterState(eStateReadCommand);
}
2016-10-15 21:37:59 +05:00
void NNTPServerHandler::SwitchMode(const std::string & mode)
{
2017-05-03 20:01:32 +05:00
std::string m = mode;
std::transform(m.begin(), m.end(), m.begin(), ::toupper);
if (m == "READER") {
m_mode = m;
2017-04-14 15:24:53 +05:00
if(PostingAllowed()) {
QueueLine("200 Posting is permitted yo");
} else {
QueueLine("201 Posting is not permitted yo");
}
2017-05-03 20:01:32 +05:00
} else if (m == "STREAM") {
m_mode = m;
2017-04-14 15:24:53 +05:00
if (PostingAllowed()) {
QueueLine("203 Streaming enabled");
} else {
QueueLine("483 Streaming Denied");
}
} else {
// unknown mode
QueueLine("500 Unknown mode");
}
2016-10-15 21:37:59 +05:00
}
2017-05-03 22:33:04 +05:00
void NNTPServerHandler::EnterState(State st)
{
std::cerr << "enter state " << st << std::endl;
m_state = st;
}
2016-10-15 21:37:59 +05:00
void NNTPServerHandler::Quit()
{
2017-05-03 22:33:04 +05:00
EnterState(eStateQuit);
2016-10-15 21:37:59 +05:00
QueueLine("205 quitting");
}
2017-05-03 18:15:06 +05:00
bool NNTPServerHandler::ShouldClose()
2016-10-15 21:37:59 +05:00
{
return m_state == eStateQuit;
}
2016-10-15 22:53:35 +05:00
bool NNTPServerHandler::PostingAllowed()
{
return m_authed || m_auth == nullptr;
}
2017-04-14 15:24:53 +05:00
2016-10-15 22:53:35 +05:00
void NNTPServerHandler::Greet()
{
2017-04-14 15:24:53 +05:00
if(PostingAllowed())
2016-10-15 22:53:35 +05:00
QueueLine("200 Posting allowed");
else
QueueLine("201 Posting not allowed");
}
void NNTPServerHandler::SetAuth(CredDB_ptr creds)
2016-10-15 22:53:35 +05:00
{
m_auth = creds;
}
2016-10-15 21:37:59 +05:00
}