message.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. try
  30. {
  31. std::cout << "message::processMessage enter" << std::endl;
  32. message::state::type state = message::state::header;
  33. std::string line;
  34. std::istringstream stream(message);
  35. while (std::getline(stream, line, '\r'))
  36. {
  37. boost::erase_all(line, "\n");
  38. switch (state)
  39. {
  40. case state::header:
  41. state = processHeaderLine(line);
  42. break;
  43. case state::data:
  44. state = processDataLine(line);
  45. break;
  46. case state::mimeBoundary:
  47. state = processMimeBoundary(line);
  48. break;
  49. case state::image:
  50. state = processImage(line);
  51. break;
  52. }
  53. }
  54. if (boost::algorithm::contains(m_contentEncoding, "base64"))
  55. {
  56. std::string decoded = Decode(m_subject);
  57. if (decoded.size() > 0)
  58. m_subject = decoded;
  59. }
  60. outputImage image(m_images);
  61. boost::filesystem::path path(m_context.path);
  62. path = boost::filesystem::canonical(path);
  63. path /= m_address;
  64. if (!boost::filesystem::exists(path))
  65. boost::filesystem::create_directory(path);
  66. std::string fileName(getTimeString());
  67. fileName.append(".jpg");
  68. path /= fileName;
  69. image.save(path.string());
  70. if (!m_context.url.empty())
  71. {
  72. std::stringstream url;
  73. url << m_context.url << "?ip=" << m_address << "&file=" << fileName;
  74. m_context.client.GetUrlContents(url.str());
  75. }
  76. }
  77. catch (std::exception& e)
  78. {
  79. std::cout << "Exception: " << e.what() << std::endl;
  80. std::cerr << "Exception: " << e.what() << std::endl;
  81. }
  82. std::cout << "message::processMessage exit" << std::endl;
  83. }
  84. message::state::type message::processHeaderLine(const std::string& line)
  85. {
  86. if (line.empty())
  87. return message::state::data;
  88. if (boost::istarts_with(line, "from:"))
  89. {
  90. m_sender = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  91. return message::state::header;
  92. }
  93. if (boost::istarts_with(line, "to:"))
  94. {
  95. m_receiver = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  96. return message::state::header;
  97. }
  98. if (boost::istarts_with(line, "subject:"))
  99. {
  100. m_subject = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  101. return message::state::header;
  102. }
  103. if (boost::istarts_with(line, "date"))
  104. {
  105. m_date = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  106. return message::state::header;
  107. }
  108. if (boost::istarts_with(line, "content-type:"))
  109. {
  110. m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  111. return message::state::header;
  112. }
  113. if (boost::istarts_with(line, "boundary") || boost::istarts_with(line, "\tboundary") || boost::istarts_with(line, " boundary"))
  114. {
  115. m_mimeBoundary = std::string("--").append(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
  116. return message::state::header;
  117. }
  118. if (boost::istarts_with(line, "content-transfer-encoding:"))
  119. {
  120. m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  121. return message::state::header;
  122. }
  123. return message::state::header;
  124. }
  125. message::state::type message::processDataLine(const std::string& line)
  126. {
  127. if (boost::istarts_with(line, m_mimeBoundary))
  128. {
  129. m_contentType = "";
  130. return message::state::mimeBoundary;
  131. }
  132. return message::state::data;
  133. }
  134. message::state::type message::processMimeBoundary(const std::string& line)
  135. {
  136. if (line.empty())
  137. {
  138. if (boost::istarts_with(m_contentType, "image/jpeg") || boost::istarts_with(m_contentType, "image/jpg"))
  139. {
  140. m_mimeImages.push_back(mimeImage(m_imageName));
  141. m_imageName = "";
  142. return message::state::image;
  143. }
  144. return message::state::data;
  145. }
  146. if (boost::istarts_with(line, "content-type:"))
  147. {
  148. m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  149. return message::state::mimeBoundary;
  150. }
  151. if (boost::istarts_with(line, "name") || boost::istarts_with(line, "\tname"))
  152. {
  153. m_imageName = "image.jpg";
  154. //m_imageName = Decode(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
  155. return message::state::mimeBoundary;
  156. }
  157. if (boost::istarts_with(line, "content-transfer-encoding:"))
  158. {
  159. m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
  160. return message::state::mimeBoundary;
  161. }
  162. return message::state::mimeBoundary;
  163. }
  164. message::state::type message::processImage(const std::string& line)
  165. {
  166. if (boost::istarts_with(line, m_mimeBoundary))
  167. {
  168. m_images.push_back(m_mimeImages[m_currentImage].decodeImageData());
  169. ++m_currentImage;
  170. m_contentType = "";
  171. return message::state::mimeBoundary;
  172. }
  173. m_mimeImages[m_currentImage].appendData(line);
  174. return message::state::image;
  175. }