47 timestamp << std::setw(2) << std::setfill('0') << value->getMinute() << ":"; |
47 timestamp << std::setw(2) << std::setfill('0') << value->getMinute() << ":"; |
48 timestamp << std::setw(2) << std::setfill('0') << value->getSecond() << (tz >= 0 ? "+" : "-"); |
48 timestamp << std::setw(2) << std::setfill('0') << value->getSecond() << (tz >= 0 ? "+" : "-"); |
49 timestamp << std::setw(2) << std::setfill('0') << std::abs(tz / 60) << ":"; |
49 timestamp << std::setw(2) << std::setfill('0') << std::abs(tz / 60) << ":"; |
50 timestamp << std::setw(2) << std::setfill('0') << std::abs(tz % 60); |
50 timestamp << std::setw(2) << std::setfill('0') << std::abs(tz % 60); |
51 return timestamp.str(); |
51 return timestamp.str(); |
|
52 } |
|
53 |
|
54 std::string format(const vmime::mediaType& contentType) { |
|
55 return contentType.getType() + "/" + contentType.getSubType(); |
52 } |
56 } |
53 |
57 |
54 public: |
58 public: |
55 |
59 |
56 XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { |
60 XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { |
108 } else if (std::shared_ptr<vmime::mailboxGroup> mailbox = std::dynamic_pointer_cast<vmime::mailboxGroup> (address)) { |
112 } else if (std::shared_ptr<vmime::mailboxGroup> mailbox = std::dynamic_pointer_cast<vmime::mailboxGroup> (address)) { |
109 // TODO: mailboxGroup? |
113 // TODO: mailboxGroup? |
110 } |
114 } |
111 } |
115 } |
112 } else if (auto value = mimeField->getValue<vmime::datetime>()) { |
116 } else if (auto value = mimeField->getValue<vmime::datetime>()) { |
|
117 // TODO: keep particular timestamp bits attributes or not? |
113 field->set_attribute("year", std::to_string(value->getYear())); |
118 field->set_attribute("year", std::to_string(value->getYear())); |
114 field->set_attribute("month", std::to_string(value->getMonth())); |
119 field->set_attribute("month", std::to_string(value->getMonth())); |
115 field->set_attribute("day", std::to_string(value->getDay())); |
120 field->set_attribute("day", std::to_string(value->getDay())); |
116 field->set_attribute("hour", std::to_string(value->getHour())); |
121 field->set_attribute("hour", std::to_string(value->getHour())); |
117 field->set_attribute("minute", std::to_string(value->getMinute())); |
122 field->set_attribute("minute", std::to_string(value->getMinute())); |
118 field->set_attribute("second", std::to_string(value->getSecond())); |
123 field->set_attribute("second", std::to_string(value->getSecond())); |
119 field->set_attribute("zone", std::to_string(value->getZone())); // timezone is in minutes |
124 field->set_attribute("zone", std::to_string(value->getZone())); // timezone is in minutes |
120 field->add_child_text(format(value)); |
125 field->add_child_text(format(value)); |
121 } else if (auto value = mimeField->getValue<vmime::mediaType>()) { |
126 } else if (auto value = mimeField->getValue<vmime::mediaType>()) { |
122 std::string type = value->getType(); |
127 if (value) field->add_child_text(format(*value)); |
123 std::string subType = value->getSubType(); |
|
124 if (type.size()) field->set_attribute("type", type); |
|
125 if (subType.size()) field->set_attribute("subType", subType); |
|
126 if (type.size() && subType.size()) field->add_child_text(type + "/" + subType); |
|
127 // TODO: encoding from the "Content-Type: text/plain; charset=us-ascii" type header? |
128 // TODO: encoding from the "Content-Type: text/plain; charset=us-ascii" type header? |
128 } else if (auto value = mimeField->getValue<vmime::messageId>()) { |
129 } else if (auto value = mimeField->getValue<vmime::messageId>()) { |
129 field->set_attribute("left", value->getLeft()); |
|
130 field->set_attribute("right", value->getRight()); |
|
131 field->add_child_text(value->getId()); |
130 field->add_child_text(value->getId()); |
132 } else if (auto value = mimeField->getValue<vmime::messageIdSequence>()) { |
131 } else if (auto value = mimeField->getValue<vmime::messageIdSequence>()) { |
133 for (auto messageId : value->getMessageIdList()) { |
132 for (auto messageId : value->getMessageIdList()) { |
134 xmlpp::Element* messageIdField = field->add_child("Mssage-ID"); // TODO: lower case? |
133 xmlpp::Element* messageIdField = field->add_child("Mssage-ID"); // TODO: lower case? |
135 messageIdField->set_attribute("left", messageId->getLeft()); |
|
136 messageIdField->set_attribute("right", messageId->getRight()); |
|
137 messageIdField->add_child_text(messageId->getId()); |
134 messageIdField->add_child_text(messageId->getId()); |
138 } |
135 } |
139 } else if (auto value = mimeField->getValue<vmime::contentDisposition>()) { |
136 } else if (auto value = mimeField->getValue<vmime::contentDisposition>()) { |
140 field->add_child_text(value->getName()); |
137 field->add_child_text(value->getName()); |
141 } else if (auto value = mimeField->getValue<vmime::relay>()) { |
138 } else if (auto value = mimeField->getValue<vmime::relay>()) { |
147 // TODO: date of Received/relay |
144 // TODO: date of Received/relay |
148 // TODO: missing values or incomplete parsing of Received/relay in vmime |
145 // TODO: missing values or incomplete parsing of Received/relay in vmime |
149 } else if (auto value = mimeField->getValue<vmime::path>()) { |
146 } else if (auto value = mimeField->getValue<vmime::path>()) { |
150 std::string local = value->getLocalPart(); |
147 std::string local = value->getLocalPart(); |
151 std::string domain = value->getDomain(); |
148 std::string domain = value->getDomain(); |
152 if (local.size()) field->set_attribute("local", local); |
|
153 if (domain.size()) field->set_attribute("domain", domain); |
|
154 if (local.size() && domain.size()) field->add_child_text(local + "@" + domain); |
149 if (local.size() && domain.size()) field->add_child_text(local + "@" + domain); |
|
150 else field->add_child_text(local + domain); |
155 } else if (auto value = mimeField->getValue<vmime::encoding>()) { |
151 } else if (auto value = mimeField->getValue<vmime::encoding>()) { |
156 field->add_child_text(value->getName()); |
152 field->add_child_text(value->getName()); |
157 } else { |
153 } else { |
158 field->add_child_text("TODO: unknown header type"); // TODO: generic conversion as fallback? |
154 field->add_child_text("TODO: unknown header type"); // TODO: generic conversion as fallback? |
159 } |
155 } |
160 } |
156 } |
|
157 |
|
158 // TODO: check null pointers |
161 |
159 |
162 xmlpp::Element* body = root->add_child("body"); |
160 xmlpp::Element* body = root->add_child("body"); |
|
161 |
|
162 body->set_attribute("content-type", format(m.getBody()->getContentType())); |
|
163 |
|
164 for (auto part : m.getBody()->getPartList()) { |
|
165 xmlpp::Element* partElement = body->add_child("part"); |
|
166 partElement->set_attribute("content-type", format(part->getBody()->getContentType())); |
|
167 } |
|
168 |
163 } |
169 } |
164 }; |
170 }; |
165 |
171 |
166 } |
172 } |
167 } |
173 } |