message.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include <sstream>
  2. #include <boost/lexical_cast.hpp>
  3. #include <boost/algorithm/string/predicate.hpp>
  4. #include <boost/algorithm/string.hpp>
  5. #include <boost/filesystem.hpp>
  6. #include "outputImage.h"
  7. #include "base64.h"
  8. #include "message.h"
  9. message::message(const std::string& address, const context& context, const std::string& message) :
  10. m_address(address),
  11. m_context(context),
  12. m_mimeBoundary("-_-InvalidBoundary-_-"),
  13. m_contentEncoding("none"),
  14. m_currentImage(0)
  15. {
  16. processMessage(message);
  17. }
  18. std::string Decode(const std::string& data)
  19. {
  20. std::string result;
  21. if (boost::istarts_with(data, "=?utf-8?"))
  22. result = base64_decode(std::string(data.begin() + 10, data.begin() + data.find_last_of('?')));
  23. else
  24. result = base64_decode(data);
  25. return result;
  26. }
  27. void message::processMessage(const std::string& message)
  28. {
  29. message::state::type state = message::state::header;
  30. std::string line;
  31. std::istringstream stream(message);
  32. while (std::getline(stream, line, '\r'))
  33. {
  34. boost::erase_all(line, "\n");
  35. switch (state)
  36. {
  37. case state::header:
  38. state = processHeaderLine(line);
  39. break;
  40. case state::data:
  41. state = processDataLine(line);
  42. break;
  43. case state::mimeBoundary:
  44. state = processMimeBoundary(line);
  45. break;
  46. case state::image:
  47. state = processImage(line);
  48. break;
  49. }
  50. }
  51. if (boost::algorithm::contains(m_contentEncoding, "base64"))
  52. {
  53. std::string decoded = Decode(m_subject);
  54. if (decoded.size() > 0)
  55. m_subject = decoded;
  56. }
  57. outputImage image(m_images);
  58. boost::filesystem::path path(m_context.path);
  59. path = boost::filesystem::canonical(path);
  60. path /= m_address;
  61. if (!boost::filesystem::exists(path))
  62. boost::filesystem::create_directory(path);
  63. std::string fileName(getTimeString());
  64. fileName.append(".jpg");
  65. path /= fileName;
  66. image.save(path.string());
  67. if (!m_context.url.empty())
  68. {
  69. std::stringstream url;
  70. url << m_context.url << "?ip=" << m_address << "&file=" << fileName;
  71. m_context.client.GetUrlContents(url.str());
  72. }
  73. }
  74. message::state::type message::processHeaderLine(const std::string& line)
  75. {
  76. if (line.empty())
  77. return message::state::data;
  78. if (boost::istarts_with(line, "from:"))
  79. {
  80. m_sender = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  81. return message::state::header;
  82. }
  83. if (boost::istarts_with(line, "to:"))
  84. {
  85. m_receiver = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  86. return message::state::header;
  87. }
  88. if (boost::istarts_with(line, "subject:"))
  89. {
  90. m_subject = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  91. return message::state::header;
  92. }
  93. if (boost::istarts_with(line, "date"))
  94. {
  95. m_date = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  96. return message::state::header;
  97. }
  98. if (boost::istarts_with(line, "content-type:"))
  99. {
  100. m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  101. return message::state::header;
  102. }
  103. if (boost::istarts_with(line, "boundary") || boost::istarts_with(line, "\tboundary") || boost::istarts_with(line, " boundary"))
  104. {
  105. m_mimeBoundary = std::string("--").append(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
  106. return message::state::header;
  107. }
  108. if (boost::istarts_with(line, "content-transfer-encoding:"))
  109. {
  110. m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  111. return message::state::header;
  112. }
  113. return message::state::header;
  114. }
  115. message::state::type message::processDataLine(const std::string& line)
  116. {
  117. if (boost::istarts_with(line, m_mimeBoundary))
  118. {
  119. m_contentType = "";
  120. return message::state::mimeBoundary;
  121. }
  122. return message::state::data;
  123. }
  124. message::state::type message::processMimeBoundary(const std::string& line)
  125. {
  126. if (line.empty())
  127. {
  128. if (boost::istarts_with(m_contentType, "image/jpeg") || boost::istarts_with(m_contentType, "image/jpg"))
  129. {
  130. m_mimeImages.push_back(mimeImage(m_imageName));
  131. m_imageName = "";
  132. return message::state::image;
  133. }
  134. return message::state::data;
  135. }
  136. if (boost::istarts_with(line, "content-type:"))
  137. {
  138. m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  139. return message::state::mimeBoundary;
  140. }
  141. if (boost::istarts_with(line, "name") || boost::istarts_with(line, "\tname"))
  142. {
  143. m_imageName = "image.jpg";
  144. //m_imageName = Decode(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
  145. return message::state::mimeBoundary;
  146. }
  147. if (boost::istarts_with(line, "content-transfer-encoding:"))
  148. {
  149. m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  150. return message::state::mimeBoundary;
  151. }
  152. return message::state::mimeBoundary;
  153. }
  154. message::state::type message::processImage(const std::string& line)
  155. {
  156. if (boost::istarts_with(line, m_mimeBoundary))
  157. {
  158. m_images.push_back(m_mimeImages[m_currentImage].decodeImageData());
  159. ++m_currentImage;
  160. m_contentType = "";
  161. return message::state::mimeBoundary;
  162. }
  163. m_mimeImages[m_currentImage].appendData(line);
  164. return message::state::image;
  165. }