You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
3.4 KiB
151 lines
3.4 KiB
/*
|
|
Copyright 2018 Denes Matetelki <denes@matetelki.com>
|
|
|
|
This file is part of webfish.
|
|
|
|
webfish is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License v3 as published by the Free
|
|
Software Foundation.
|
|
|
|
webfish is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License v3 for
|
|
more details.
|
|
|
|
You should have received a copy of the GNU General Public License v3 along
|
|
with webfish. If not, see
|
|
https://www.gnu.org/licenses/gpl-3.0.html.
|
|
*/
|
|
|
|
#ifndef WEBHOOK_MESSAGE_HPP
|
|
#define WEBHOOK_MESSAGE_HPP
|
|
|
|
#include <cpp_utils/Message.hpp>
|
|
#include <cpp_utils/TcpConnection.hpp>
|
|
|
|
#include <iomanip> // put_time
|
|
#include <ctime>
|
|
#include <sstream>
|
|
|
|
#include <vector>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
class WebhookMessage : public Message
|
|
{
|
|
public:
|
|
|
|
struct WebhookMessageParam {
|
|
const std::string script_path;
|
|
const std::string client;
|
|
const std::string secret;
|
|
};
|
|
|
|
WebhookMessage( void *msgParam = 0)
|
|
: Message(msgParam)
|
|
{
|
|
TRACE;
|
|
}
|
|
|
|
bool buildMessage( const void *msgPart,
|
|
const size_t msgLen )
|
|
{
|
|
TRACE;
|
|
m_buffer = std::string( (const char*) msgPart, msgLen );
|
|
|
|
/// @todo use it!
|
|
// not using getExpectedLength
|
|
onMessageReady();
|
|
return true;
|
|
}
|
|
|
|
void onMessageReady()
|
|
{
|
|
TRACE;
|
|
|
|
LOG_BEGIN(Logger::INFO)
|
|
LOG_PROP("buffer", m_buffer)
|
|
LOG_PROP("host", m_connection->getHost())
|
|
LOG_PROP("port", m_connection->getPort())
|
|
LOG_END("Got message.");
|
|
|
|
std::string reply;
|
|
|
|
WebhookMessageParam* p = reinterpret_cast<WebhookMessageParam*>(m_param);
|
|
|
|
try {
|
|
if (m_connection->getHost() != p->client) {
|
|
reply = generateReply("403 Forbidden");
|
|
throw std::runtime_error("Client is not from the hostname we expect.");
|
|
}
|
|
|
|
if (m_buffer.find("POST /gitea-webhook/post HTTP/1.1") != 0) {
|
|
reply = generateReply("400 Bad Request");
|
|
throw std::runtime_error("Received msg is not a gitea-webhook");
|
|
}
|
|
|
|
const std::string s = "\"secret\": \"" + p->secret + "\"";
|
|
if (m_buffer.find(s) == std::string::npos) {
|
|
reply = generateReply("401 Unauthorized");
|
|
throw std::runtime_error("Received msg does not contain the secret.");
|
|
}
|
|
|
|
} catch (const std::exception& e) {
|
|
LOG (Logger::ERR, e.what());
|
|
m_connection->send(reply.c_str(), reply.length());
|
|
m_buffer.clear();
|
|
dynamic_cast<TcpConnection*>(m_connection)->disconnect();
|
|
return;
|
|
}
|
|
|
|
int status = system(p->script_path.c_str());
|
|
reply = generateReply(status == 0 ? "200 OK": "500 Internal Server Error");
|
|
|
|
m_connection->send(reply.c_str(), reply.length());
|
|
m_buffer.clear();
|
|
}
|
|
|
|
std::string generateReply(const std::string status) const {
|
|
const auto t = std::time(nullptr);
|
|
const auto tm = *std::localtime(&t);
|
|
std::ostringstream oss;
|
|
oss << "HTTP/1.1 " << status << "\r\n";
|
|
|
|
// Fri, 08 Feb 2019 12:35:37 GMT
|
|
oss << "Date: " << std::put_time(&tm, "%a, %d %b %Y %T %Z") << "\r\n";
|
|
|
|
oss << "Server: webfish(0.1)\r\n" \
|
|
"Content-Type: text/plain;charset=utf-8\r\n" \
|
|
"Content-Length: 10\r\n" \
|
|
"Connection: close\r\n" \
|
|
"\r\n" \
|
|
"Processed\n";
|
|
|
|
return oss.str();
|
|
}
|
|
|
|
Message* clone()
|
|
{
|
|
TRACE;
|
|
return new WebhookMessage(m_param);
|
|
}
|
|
|
|
std::string getBuffer()
|
|
{
|
|
TRACE;
|
|
return m_buffer;
|
|
}
|
|
|
|
protected:
|
|
|
|
size_t getExpectedLength()
|
|
{
|
|
TRACE;
|
|
return 0;
|
|
}
|
|
|
|
};
|
|
|
|
#endif // WEBHOOK_MESSAGE_HPP
|