| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | #include "content_type.hh" |
|---|
| 21 | #include "entity.hh" |
|---|
| 22 | #include "lexutils.hh" |
|---|
| 23 | #include "message_entity.hh" |
|---|
| 24 | #include "multipart.hh" |
|---|
| 25 | #include "text_plain.hh" |
|---|
| 26 | #include "util.hh" |
|---|
| 27 | #include "raw_entity.hh" |
|---|
| 28 | |
|---|
| 29 | #include "../util.hh" |
|---|
| 30 | |
|---|
| 31 | #include <boost/algorithm/string/case_conv.hpp> |
|---|
| 32 | #include <boost/format.hpp> |
|---|
| 33 | #include <boost/nondet_random.hpp> |
|---|
| 34 | |
|---|
| 35 | #include "../assert.hh" |
|---|
| 36 | |
|---|
| 37 | namespace msg |
|---|
| 38 | { |
|---|
| 39 | size_t entity::get_size() const |
|---|
| 40 | { |
|---|
| 41 | std::string body = get_body(); |
|---|
| 42 | size_t n = 0; |
|---|
| 43 | for (field_iterator it = fields_begin(); |
|---|
| 44 | it != fields_end(); it++) |
|---|
| 45 | { |
|---|
| 46 | n += it->length(); |
|---|
| 47 | } |
|---|
| 48 | n += 2; |
|---|
| 49 | n += body.length(); |
|---|
| 50 | return n; |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | size_t entity::get_body_lines() const |
|---|
| 54 | { |
|---|
| 55 | std::string body = get_body(); |
|---|
| 56 | unsigned long lines = -1; |
|---|
| 57 | size_t inx = std::string::npos; |
|---|
| 58 | do |
|---|
| 59 | { |
|---|
| 60 | inx++; |
|---|
| 61 | lines++; |
|---|
| 62 | inx = body.find("\r\n", inx); |
|---|
| 63 | } while (inx != std::string::npos); |
|---|
| 64 | return lines; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | entity::ptr entity::mk(std::string ms, bool validate, std::string dct) |
|---|
| 68 | { |
|---|
| 69 | entity_header::ptr hdr(new entity_header(ms, validate, dct)); |
|---|
| 70 | |
|---|
| 71 | entity::ptr rv; |
|---|
| 72 | content_type ct = hdr->get_content_type(); |
|---|
| 73 | switch (ct.get_type()) |
|---|
| 74 | { |
|---|
| 75 | case content_type::MESSAGE: |
|---|
| 76 | rv.reset(new message_entity(hdr, ms)); |
|---|
| 77 | break; |
|---|
| 78 | case content_type::MULTIPART: |
|---|
| 79 | rv.reset(new multipart(hdr, ms)); |
|---|
| 80 | break; |
|---|
| 81 | case content_type::TEXT: |
|---|
| 82 | rv.reset(new text_plain(hdr, ms)); |
|---|
| 83 | break; |
|---|
| 84 | default: |
|---|
| 85 | rv.reset(new raw_entity(hdr, ms)); |
|---|
| 86 | break; |
|---|
| 87 | } |
|---|
| 88 | return rv; |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | multipart::ptr entity::clone_as_multipart() const |
|---|
| 92 | { |
|---|
| 93 | static const char content_[] = "content-"; |
|---|
| 94 | boost::random_device urand; |
|---|
| 95 | |
|---|
| 96 | entity_header::ptr envh(new entity_header(*hdr)); |
|---|
| 97 | entity_header::ptr subh(new entity_header(DEFAULT_CT)); |
|---|
| 98 | |
|---|
| 99 | for (field_iterator it = hdr->fields_begin(); |
|---|
| 100 | it != hdr->fields_end(); it++) |
|---|
| 101 | { |
|---|
| 102 | std::string fld = *it; |
|---|
| 103 | size_t colon = fld.find(':'); |
|---|
| 104 | if (colon == std::string::npos) colon = 0; |
|---|
| 105 | std::string name = fld.substr(0, colon); |
|---|
| 106 | size_t start = colon + 1 < fld.length() |
|---|
| 107 | ? (fld[colon+1] == ' ' ? colon + 1 : colon) |
|---|
| 108 | : colon; |
|---|
| 109 | std::string content = fld.substr(start); |
|---|
| 110 | util::strip_crlf(content); |
|---|
| 111 | boost::to_lower(name); |
|---|
| 112 | if (name.substr(0, sizeof content_ - 1) != content_) |
|---|
| 113 | continue; |
|---|
| 114 | subh->replace_field(name, content); |
|---|
| 115 | envh->delete_field(name); |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | std::string body = get_body(); |
|---|
| 119 | |
|---|
| 120 | std::string boundary; |
|---|
| 121 | redo: |
|---|
| 122 | { |
|---|
| 123 | std::ostringstream ss; |
|---|
| 124 | ss << urand() << urand() << urand() << urand(); |
|---|
| 125 | if (body.find(ss.str()) != std::string::npos) |
|---|
| 126 | goto redo; |
|---|
| 127 | boundary = ss.str(); |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | bool bit8 = false; |
|---|
| 131 | for (size_t i = 0; i < body.length(); i++) |
|---|
| 132 | { |
|---|
| 133 | if ((unsigned char)body[i] > 0x7f) |
|---|
| 134 | { |
|---|
| 135 | bit8 = true; |
|---|
| 136 | break; |
|---|
| 137 | } |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | envh->replace_field("MIME-Version", "1.0"); |
|---|
| 141 | envh->add_field("Content-Type", |
|---|
| 142 | std::string("multipart/mixed; boundary=") + |
|---|
| 143 | make_phrase(boundary)); |
|---|
| 144 | envh->add_field("Content-Transfer-Encoding", |
|---|
| 145 | bit8 ? "8bit" : "7bit"); |
|---|
| 146 | |
|---|
| 147 | std::ostringstream nbss; |
|---|
| 148 | nbss << "--" << boundary << "\r\n" |
|---|
| 149 | << subh->get_header() << "\r\n" |
|---|
| 150 | << body |
|---|
| 151 | << "\r\n--" << boundary << "--\r\n"; |
|---|
| 152 | |
|---|
| 153 | multipart::ptr rv(new multipart(envh, nbss.str())); |
|---|
| 154 | return rv; |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | } |
|---|