void MessageAttachmentStripper::_WriteToDisk(shared_ptr<Message> pMessage, MimeBody &oMainMessage, shared_ptr<MimeBody> pBody) { if (!pBody) return; AnsiString sHeader; vector<MimeField> oFieldList = oMainMessage.Fields(); vector<MimeField>::iterator iterField = oFieldList.begin(); while (iterField != oFieldList.end()) { MimeField oField = (*iterField); AnsiString sName = oField.GetName(); if (sName.CompareNoCase("subject") == 0) { String sTextVirusFound = Configuration::Instance()->GetServerMessages()->GetMessage("VIRUS_FOUND"); sHeader += sName; sHeader += ": " + sTextVirusFound +": "; sHeader += oField.GetValue(); sHeader += "\r\n"; } else if (sName.CompareNoCase("content-type") != 0) { sHeader += sName; sHeader += ": "; sHeader += oField.GetValue(); sHeader += "\r\n"; } iterField++; } String sBody = pBody->GetRawText(); String sNotification = Configuration::Instance()->GetServerMessages()->GetMessage("VIRUS_ATTACHMENT_REMOVED"); sBody = sNotification + sBody; String sData = sHeader; sData += "\r\n"; sData += sBody + "\r\n"; pMessage->SetSize(sData.GetLength()); String fileName = PersistentMessage::GetFileName(pMessage); FileUtilities::WriteToFile(fileName, sData, false); }
String MessageUtilities::GetSendersIP(boost::shared_ptr<Message> pMessage) { const String fileName = PersistentMessage::GetFileName(pMessage); AnsiString sHeader = PersistentMessage::LoadHeader(fileName); MimeHeader oHeader; oHeader.Load(sHeader, sHeader.GetLength(), true); // Locate the first Received header MimeField *pReceivedHeader = oHeader.GetField("Received"); if (pReceivedHeader == 0) return "127.0.0.1"; // Now we should try to find the IP in the received header. String sReceivedValue = pReceivedHeader->GetValue(); int iAddressStart = sReceivedValue.Find(_T("[")) +1; int iAddressEnd = sReceivedValue.Find(_T("]"), iAddressStart); int iAddressLen = iAddressEnd - iAddressStart; if (iAddressLen <= 0) return "127.0.0.1"; String sIPAddress = sReceivedValue.Mid(iAddressStart, iAddressLen); if (!StringParser::IsValidIPAddress(sIPAddress)) return "127.0.0.1"; return sIPAddress; }
// set 'boundary' parameter (for multipart) of Content-Type field void MimeHeader::SetBoundary(const char* pszBoundary/*=NULL*/) { static int s_nPartNumber = 0; char buf[80]; if (!pszBoundary) // generate a new boundary delimeter { ::srand(((unsigned)::time(NULL)) ^ (unsigned)this); ::sprintf(buf, "__=_Part_Boundary_%03d_%06d.%06d", ++s_nPartNumber, rand(), rand()); if (s_nPartNumber >= 9) s_nPartNumber = 0; pszBoundary = buf; } MimeField *pfd = GetField(CMimeConst::ContentType()); if (!pfd) { MimeField fd; fd.SetName(CMimeConst::ContentType()); fd.SetValue("multipart/mixed"); fd.SetParameter(CMimeConst::Boundary(), pszBoundary); m_listFields.push_back(fd); } else { if (::_memicmp(pfd->GetValue(), "multipart", 9) != 0) pfd->SetValue("multipart/mixed"); pfd->SetParameter(CMimeConst::Boundary(), pszBoundary); } }
// get the subtype string MimeHeader::GetSubType() const { string strSubType; MimeField *pfd = GetField(CMimeConst::ContentType()); if (pfd != NULL) { string strType; pfd->GetValue(strType); string::size_type nSlash = strType.find('/'); if (nSlash > 0) strSubType = strType.substr(nSlash+1); } else strSubType = "plain"; return strSubType; }
AnsiString RelaxedCanonicalization::CanonicalizeHeader(AnsiString header, const std::pair<AnsiString, AnsiString> &signatureField, const std::vector<AnsiString> &fieldsToInclude, AnsiString &fieldList) { MimeHeader mimeHeader; mimeHeader.Load(header, header.GetLength(), true); std::vector<MimeField> fields = mimeHeader.Fields(); String result; for(AnsiString headerField : fieldsToInclude) { headerField.Trim(); // locate this field, starting from the end. String value; for (size_t i = fields.size(); i > 0; i--) { size_t fieldIndex = i - 1; MimeField field = fields[fieldIndex]; if (headerField.CompareNoCase(field.GetName()) == 0) { // found fields.erase(fields.begin() + fieldIndex); value = field.GetValue(); break; } } if (value.GetLength() > 0) { /* Convert all header field names (not the header field values) to lowercase. For example, convert "SUBJect: AbC" to "subject: AbC". Delete any WSP characters remaining before and after the colon separating the header field name from the header field value. The colon separator MUST be retained. */ String relaxedFieldValue; String relaxedHeaderName = CanonicalizeHeaderName(headerField); relaxedFieldValue = CanonicalizeHeaderValue(value); result += relaxedHeaderName + ":" + relaxedFieldValue + "\r\n"; if (!fieldList.IsEmpty()) fieldList += ":"; fieldList += headerField; } } if (!signatureField.first.IsEmpty()) { // Don't pick the value from the actual header, use the header we're verifying instead // If there are more than one DKIM-signature fields in the header, this will be important. AnsiString relaxedHeaderName = CanonicalizeHeaderName(signatureField.first); AnsiString relaxedFieldValue = CanonicalizeHeaderValue(signatureField.second); //and without a trailing CRLF. result += relaxedHeaderName + ":" + GetDKIMWithoutSignature_(relaxedFieldValue); } return result; }