|
|
@@ -0,0 +1,188 @@
|
|
|
+#include <sstream>
|
|
|
+#include <boost/lexical_cast.hpp>
|
|
|
+#include <boost/algorithm/string/predicate.hpp>
|
|
|
+#include <boost/algorithm/string.hpp>
|
|
|
+#include <boost/filesystem.hpp>
|
|
|
+#include "outputImage.h"
|
|
|
+#include "base64.h"
|
|
|
+#include "message.h"
|
|
|
+
|
|
|
+
|
|
|
+message::message(const std::string& address, const context& context, const std::string& message) :
|
|
|
+ m_address(address),
|
|
|
+ m_context(context),
|
|
|
+ m_mimeBoundary("-_-InvalidBoundary-_-"),
|
|
|
+ m_contentEncoding("none"),
|
|
|
+ m_currentImage(0)
|
|
|
+{
|
|
|
+ processMessage(message);
|
|
|
+}
|
|
|
+
|
|
|
+std::string Decode(const std::string& data)
|
|
|
+{
|
|
|
+ std::string result;
|
|
|
+ if (boost::istarts_with(data, "=?utf-8?"))
|
|
|
+ result = base64_decode(std::string(data.begin() + 10, data.begin() + data.find_last_of('?')));
|
|
|
+ else
|
|
|
+ result = base64_decode(data);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+void message::processMessage(const std::string& message)
|
|
|
+{
|
|
|
+ message::state::type state = message::state::header;
|
|
|
+ std::string line;
|
|
|
+ std::istringstream stream(message);
|
|
|
+ while (std::getline(stream, line, '\r'))
|
|
|
+ {
|
|
|
+ boost::erase_all(line, "\n");
|
|
|
+ switch (state)
|
|
|
+ {
|
|
|
+ case state::header:
|
|
|
+ state = processHeaderLine(line);
|
|
|
+ break;
|
|
|
+ case state::data:
|
|
|
+ state = processDataLine(line);
|
|
|
+ break;
|
|
|
+ case state::mimeBoundary:
|
|
|
+ state = processMimeBoundary(line);
|
|
|
+ break;
|
|
|
+ case state::image:
|
|
|
+ state = processImage(line);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (boost::algorithm::contains(m_contentEncoding, "base64"))
|
|
|
+ {
|
|
|
+ std::string decoded = Decode(m_subject);
|
|
|
+ if (decoded.size() > 0)
|
|
|
+ m_subject = decoded;
|
|
|
+ }
|
|
|
+
|
|
|
+ outputImage image(m_images);
|
|
|
+
|
|
|
+ boost::filesystem::path path(m_context.path);
|
|
|
+ path = boost::filesystem::canonical(path);
|
|
|
+ path /= m_address;
|
|
|
+
|
|
|
+ if (!boost::filesystem::exists(path))
|
|
|
+ boost::filesystem::create_directory(path);
|
|
|
+
|
|
|
+ std::string fileName(getTimeString());
|
|
|
+ fileName.append(".jpg");
|
|
|
+ path /= fileName;
|
|
|
+
|
|
|
+ image.save(path.string());
|
|
|
+
|
|
|
+ if (!m_context.url.empty())
|
|
|
+ {
|
|
|
+ std::stringstream url;
|
|
|
+ url << m_context.url << "?ip=" << m_address << "&file=" << fileName;
|
|
|
+ m_context.client.GetUrlContents(url.str());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+message::state::type message::processHeaderLine(const std::string& line)
|
|
|
+{
|
|
|
+ if (line.empty())
|
|
|
+ return message::state::data;
|
|
|
+
|
|
|
+ if (boost::istarts_with(line, "from:"))
|
|
|
+ {
|
|
|
+ m_sender = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "to:"))
|
|
|
+ {
|
|
|
+ m_receiver = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "subject:"))
|
|
|
+ {
|
|
|
+ m_subject = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "date"))
|
|
|
+ {
|
|
|
+ m_date = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "content-type:"))
|
|
|
+ {
|
|
|
+ m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "boundary") || boost::istarts_with(line, "\tboundary") || boost::istarts_with(line, " boundary"))
|
|
|
+ {
|
|
|
+ m_mimeBoundary = std::string("--").append(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "content-transfer-encoding:"))
|
|
|
+ {
|
|
|
+ m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::header;
|
|
|
+ }
|
|
|
+
|
|
|
+ return message::state::header;
|
|
|
+}
|
|
|
+
|
|
|
+message::state::type message::processDataLine(const std::string& line)
|
|
|
+{
|
|
|
+ if (boost::istarts_with(line, m_mimeBoundary))
|
|
|
+ {
|
|
|
+ m_contentType = "";
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+ }
|
|
|
+
|
|
|
+ return message::state::data;
|
|
|
+}
|
|
|
+
|
|
|
+message::state::type message::processMimeBoundary(const std::string& line)
|
|
|
+{
|
|
|
+ if (line.empty())
|
|
|
+ {
|
|
|
+ if (boost::istarts_with(m_contentType, "image/jpeg") || boost::istarts_with(m_contentType, "image/jpg"))
|
|
|
+ {
|
|
|
+ m_mimeImages.push_back(mimeImage(m_imageName));
|
|
|
+ m_imageName = "";
|
|
|
+ return message::state::image;
|
|
|
+ }
|
|
|
+ return message::state::data;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "content-type:"))
|
|
|
+ {
|
|
|
+ m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "name") || boost::istarts_with(line, "\tname"))
|
|
|
+ {
|
|
|
+ m_imageName = "image.jpg";
|
|
|
+ //m_imageName = Decode(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+ }
|
|
|
+ if (boost::istarts_with(line, "content-transfer-encoding:"))
|
|
|
+ {
|
|
|
+ m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+ }
|
|
|
+
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+}
|
|
|
+
|
|
|
+message::state::type message::processImage(const std::string& line)
|
|
|
+{
|
|
|
+ if (boost::istarts_with(line, m_mimeBoundary))
|
|
|
+ {
|
|
|
+ m_images.push_back(m_mimeImages[m_currentImage].decodeImageData());
|
|
|
+ ++m_currentImage;
|
|
|
+ m_contentType = "";
|
|
|
+ return message::state::mimeBoundary;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_mimeImages[m_currentImage].appendData(line);
|
|
|
+
|
|
|
+ return message::state::image;
|
|
|
+}
|
|
|
+
|