/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* *+SNOTICE * * * $TOG: RFCEnvelope.C /main/7 1998/04/06 13:27:59 mgreess $ * * RESTRICTED CONFIDENTIAL INFORMATION: * * The information in this document is subject to special * restrictions in a confidential disclosure agreement bertween * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout * Sun's specific written approval. This documment and all copies * and derivative works thereof must be returned or destroyed at * Sun's request. * * Copyright 1993 Sun Microsystems, Inc. All rights reserved. * *+ENOTICE */ #ifndef I_HAVE_NO_IDENT #endif #include #include #include #include #include #include #include #include "RFCImpl.hh" #include #include #include "str_utils.h" unsigned long RFCEnvelopeSignature = 0x55fd23ef; // This constant defines how big the parsed header structure starts. // it will grow dynamically over time if need be. The guess here is // that most messages will have about 32 headers so we won't have // to grow very often, but we also aren't wasting a lot of space. // static const int INITIAL_HEADER_COUNT = 32; static const int NAME_MASK = 0x1; static const int VALUE_MASK = 0x2; RFCEnvelope::RFCEnvelope(DtMailEnv & error, DtMail::Message * parent, const char * start, const int len) : DtMail::Envelope(error, parent), _parsed_headers(INITIAL_HEADER_COUNT) { error.clear(); _header_text = start; _header_len = len; _dirty = 0; _header_lock = MutexInit(); if (_header_text) { parseHeaders(); } _object_signature = RFCEnvelopeSignature; //fix for the defect 177527 _use_reply_to=DTM_TRUE; } RFCEnvelope::~RFCEnvelope(void) { if (_object_signature == RFCEnvelopeSignature) { MutexLock lock_scope(_obj_mutex); if (_object_signature == RFCEnvelopeSignature) { for (int hdr = 0; hdr < _parsed_headers.length(); hdr++) { ParsedHeader * hdrp = _parsed_headers[hdr]; delete _parsed_headers[hdr]; } _object_signature = 0; } } } DtMailHeaderHandle RFCEnvelope::getFirstHeader(DtMailEnv & error, char ** name, DtMailValueSeq & value) { MutexLock lock_header(_header_lock); error.clear(); if (_parsed_headers.length() == 0) { return(NULL); // No headers. } DtMailHeaderHandle handle = _parsed_headers[0]; *name = (char *)malloc(_parsed_headers[0]->name_len + 1); strncpy(*name, _parsed_headers[0]->name_start, _parsed_headers[0]->name_len); (*name)[_parsed_headers[0]->name_len] = 0; makeValue(error, *_parsed_headers[0], value); return(handle); } DtMailHeaderHandle RFCEnvelope::getNextHeader(DtMailEnv & error, DtMailHeaderHandle last, char ** name, DtMailValueSeq & value) { MutexLock lock_header(_header_lock); error.clear(); if (!last) { error.setError(DTME_BadArg); return(NULL); } int slot = _parsed_headers.indexof((ParsedHeader *)last); if (slot < 0) { return(NULL); } slot += 1; if (slot >= _parsed_headers.length()) { return(NULL); } ParsedHeader * hdr = _parsed_headers[slot]; *name = (char *)malloc(hdr->name_len + 1); strncpy(*name, hdr->name_start, hdr->name_len); (*name)[hdr->name_len] = 0; makeValue(error, *hdr, value); return(hdr); } struct AbstractMap { const char * abstract; const char ** transports; }; static const char * DtMailMessageToMap[] = { "To", "Apparently-To", "Resent-To", NULL }; static const char * DtMailMessageSenderMap[] = { "Reply-To", "From", "Return-Path", "Resent-From", NULL }; static const char * DtMailMessageCcMap[] = { "Cc", NULL }; static const char * DtMailMessageBccMap[] = { "Bcc", NULL }; static const char * DtMailMessageReceivedTimeMap[] = { NULL }; static const char * DtMailMessageSentTimeMap[] = { "Date", NULL }; static const char * DtMailMessageIdMap[] = { "Message-Id", NULL }; static const char * DtMailMessageSubjectMap[] = { "Subject", NULL }; static const char * DtMailMessageContentLengthMap[] = { "Content-Length", NULL }; static const char * DtMailMessageStatusMap[] = { "Status", "X-Status", NULL }; static const char * DtMailMessageV3charsetMap[] = { "X-Sun-Charset", NULL }; static const char * DtMailMessageContentTypeMap[] = { "Content-Type", NULL }; static const AbstractMap abstract_map[] = { { DtMailMessageTo, DtMailMessageToMap }, { DtMailMessageSender, DtMailMessageSenderMap }, { DtMailMessageCc, DtMailMessageCcMap }, { DtMailMessageBcc, DtMailMessageBccMap }, { DtMailMessageReceivedTime, DtMailMessageReceivedTimeMap }, { DtMailMessageSentTime, DtMailMessageSentTimeMap }, { DtMailMessageMessageId, DtMailMessageIdMap }, { DtMailMessageSubject, DtMailMessageSubjectMap }, { DtMailMessageContentLength, DtMailMessageContentLengthMap }, { DtMailMessageStatus, DtMailMessageStatusMap }, { DtMailMessageV3charset, DtMailMessageV3charsetMap }, { DtMailMessageContentType, DtMailMessageContentTypeMap }, { NULL, NULL } }; void RFCEnvelope::getHeader(DtMailEnv & error, const char * name, const DtMailBoolean abstract, DtMailValueSeq & value) { MutexLock lock_header(_header_lock); error.clear(); // If we are not in the abstract space, then simply get the // transport header and return. // if (abstract == DTM_FALSE) { getTransportHeader(error, name, value); } else { // We need to handle reply to's with special care. We may // need to strip the sender from the list. // if (strcmp(name, DtMailMessageToReply) == 0) { makeReply(error, DtMailMessageTo, value); return; } if (strcmp(name, DtMailMessageCcReply) == 0) { makeReply(error, DtMailMessageCc, value); return; } // Okay, we need to work out what the transport name // might be. We do this by first finding the abstract // name in the abstract->transport mapping table. // int abs = 0; for (abs = 0; abstract_map[abs].abstract; abs++) { if (strcmp(abstract_map[abs].abstract, name) == 0) { break; } } // If we didn't find the abstract name, then feed it through // as a transport name. This is useful behavior so intermediates // like the RFCMailBox::getMessageSummary method can always // assume abstract names, but allow its client to specify transport // names. // if (!abstract_map[abs].abstract) { getTransportHeader(error, name, value); return; } // Now we need to go through the list of transport names until // we find a match. The first match is taken because the map // should be ordered based on preference. // for (int trans = 0; abstract_map[abs].transports[trans]; trans++) { getTransportHeader(error, abstract_map[abs].transports[trans], value); // If the abstract is DtMailMessageSender we need do something // special. If the request is for displaying the sender's // name or e-mail address in the msg list scrolled window in the // RMW, we should return the "From" value instead of the // "Reply-To" value. Otherwise, we should return the Reply-To // value (such as "Reply to sender") // if (error.isNotSet()) { // Found one! if(!getUseReplyTo() && strcmp(abstract_map[abs].transports[trans],"Reply-To") == 0) { value.clear(); continue; } else return; } error.clear(); } // If this isn't a request for the sender ("From"), then // we don't have a known value for the header. Bail! // if (strcmp(DtMailMessageSender, name) && strcmp(DtMailMessageReceivedTime, name)) { error.setError(DTME_NoObjectValue); return; } if (strncmp(_parsed_headers[0]->name_start, "From", 4) == 0) { if (strcmp(DtMailMessageSender, name) == 0) { parseUnixFrom(error, *_parsed_headers[0], value); } else if (strcmp(DtMailMessageReceivedTime, name) == 0) { parseUnixDate(error, *_parsed_headers[0], value); } } else { error.setError(DTME_NoObjectValue); return; } return; } return; } void RFCEnvelope::setHeader(DtMailEnv & error, const char * name, const DtMailBoolean replace, const char * val) { MutexLock lock_header(_header_lock); RFCMessage * msg = (RFCMessage *)_parent; error.clear(); // First we need to see if we have this header. We are // only interested in the first occurrence. // ParsedHeader * hdr; const char * real_name; // Find the header if it currently exists // int slot = lookupHeader(name); // Determine if the value is really empty (just blanks) // DtMailBoolean valueIsEmpty = DTM_TRUE; for (const char *cv = val; *cv; cv++) { if (!isspace((unsigned char)*cv)) { valueIsEmpty = DTM_FALSE; break; } } // If the value to be set is empty (only spaces), then treat this // set header request specially - either toss it if requesting to // append an empty header, or remove an existing header if requesting // to set an empty header // if (valueIsEmpty == DTM_TRUE) { if (slot < 0) { // The header was not found and the value is empty - // Just return as there was no header to set anyway return; } if (replace == DTM_TRUE) { // The header was found and replacement was requested // but the value is empty - request to replace existing // header with empty header - treat as a remove header request // removeHeader(error, name); return; } // The header was found, replacement is not requested, and the // value is empty - request to append empty header - toss // return; } if (slot < 0 || replace == DTM_FALSE) { // Need to create a new header entry for this one. // hdr = new ParsedHeader; slot = _parsed_headers.append(hdr); real_name = mapName(name); _dirty = 1; // new entry: header dirty } else { hdr = _parsed_headers[slot]; real_name = name; } // First, see if we need to do something about the name. // if (!hdr->name_start) { hdr->alloc_mask |= NAME_MASK; hdr->name_start = strdup(real_name); hdr->name_len = strlen(real_name); _header_len += hdr->name_len; _dirty = 1; // new name: header dirty } // Clean up the existing value if need be. // if (hdr->value_start) { if ( (strlen(val) != hdr->value_len) || (strncmp(hdr->value_start, val, hdr->value_len)!=0) ) // has value changed?? _dirty = 1; // yes: header dirty if (hdr->alloc_mask & VALUE_MASK) { free((char *)hdr->value_start); } hdr->value_start = NULL; _header_len -= hdr->value_len; hdr->value_len = 0; } else _dirty = 1; // new value: header dirty hdr->value_start = strdup(val); hdr->value_len = strlen(hdr->value_start); _header_len += hdr->value_len + 1; hdr->alloc_mask |= VALUE_MASK; if (msg) { msg->markDirty(_dirty); } } void RFCEnvelope::removeHeader(DtMailEnv & error, const char * name) { MutexLock lock_header(_header_lock); error.clear(); // Remove all versions of this header. // int slot = lookupHeader(name); while (slot >= 0) { _parsed_headers.remove(slot); slot = lookupHeader(name); } RFCMessage * msg = (RFCMessage *)_parent; if (msg) { msg->markDirty(1); } if (!_dirty) { _dirty += 1; } return; } void RFCEnvelope::adjustHeaderLocation(char * headerStart, int headerLength) { MutexLock lock_header(_header_lock); if (_dirty) { // reparse headers in their new location // destroy current headers // for (int hdr = 0; hdr < _parsed_headers.length(); hdr++) { ParsedHeader * hdrp = _parsed_headers[hdr]; delete _parsed_headers[hdr]; _parsed_headers.remove(hdr); hdr -=1; } // parse headers from scratch _header_text = headerStart; _header_len = headerLength; parseHeaders(); } else { // We must adjust the offset of every header in the parsed header // structure. For those headers values that have been malloc()ed // (e.g. NAME_MASK or VALUE_MASK are set), don't have to do anything // as they are deallocated only when the header is destroyed. // for (int hdr = 0; hdr < _parsed_headers.length(); hdr++) { ParsedHeader * h = _parsed_headers[hdr]; if (!(h->alloc_mask & NAME_MASK)) { h->name_start = (h->name_start - _header_text) + headerStart; } if (!(h->alloc_mask & VALUE_MASK)) { h->value_start = (h->value_start - _header_text) + headerStart; } } _header_text = headerStart; } _dirty = 0; return; } char * RFCEnvelope::writeHeaders(char * new_loc) { MutexLock lock_header(_header_lock); // Copy the headers to the new region // char * cur_loc = new_loc; int first = 1; for (int hdr = 0; hdr < _parsed_headers.length(); hdr++) { ParsedHeader * h = _parsed_headers[hdr]; const char * new_name = cur_loc; memcpy(cur_loc, h->name_start, h->name_len); cur_loc += h->name_len; if (!first || strncmp(h->name_start, "From", h->name_len) != 0) { *cur_loc++ = ':'; } *cur_loc++ = ' '; first = 0; // Copy the value // const char * new_value = cur_loc; memcpy(cur_loc, h->value_start, h->value_len); cur_loc += h->value_len; // Insert a trailing crlf if necessary. We need this so that when // we write into the file, the header lines are as in RFC822 format. if (*(cur_loc - 1) != '\n') { *cur_loc++ = '\n'; } } return(cur_loc - 1); } const char * RFCEnvelope::unixFrom(DtMailEnv & error, int & length) { ParsedHeader * hdr = _parsed_headers[0]; const char * ufrom = NULL; length = 0; error.clear(); if (strncmp(hdr->name_start, "From ", 5) == 0) { ufrom = hdr->name_start; length = (hdr->value_start + hdr->value_len) - hdr->name_start + 1; } else { error.setError(DTME_NoObjectValue); } return(ufrom); } void RFCEnvelope::parseHeaders(void) { // Now we actually parse the headers. Each header either ends with // a new line, or is continued if the next line begins with white // space. // ParsedHeader * hdr = new ParsedHeader; for (const char * scan = _header_text; scan < (_header_text + _header_len);) { if ((scan == _header_text) && (strncmp(scan, "From ", 5) == 0)) { // Unix "From" line. This header has a different structure. // It is "From user@host ". It does not have a colon // like all other RFC headers so we have to parse it specially. // hdr->name_start = scan; hdr->name_len = 4; // Look for the first non-blank after the "From ". // for (scan += 4; *scan && isspace((unsigned char)*scan); scan++) { continue; } hdr->value_start = scan; // Find the new line. for (; *scan && *scan != '\n'; scan++) { continue; } hdr->value_len = scan - hdr->value_start; if (*(scan - 1) == '\r') { hdr->value_len -= 1; } scan += 1; _parsed_headers.append(hdr); hdr = new ParsedHeader; continue; } // We should be at the start of a header. Let's look for a ":". If // we find any white space first, then we have a problem. // hdr->name_start = scan; for (;*scan && *scan != ':'; scan++) { if (isspace((unsigned char)*scan)) { break; } } if (*scan != ':') { // Find the next new line, and try again. // for (;*scan && *scan != '\n'; scan++) { continue; } scan += 1; continue; } hdr->name_len = scan - hdr->name_start; // Look for the first non-blank after the colon. // for (scan += 1; scan < (_header_text + _header_len) && *scan != '\n' && isspace((unsigned char)*scan); scan++) { continue; } if (*scan == '\n') { // Null value! hdr->value_start = scan; hdr->value_len = 0; _parsed_headers.append(hdr); hdr = new ParsedHeader; scan += 1; continue; } // Okay, now we want scan looking for a new line that is // not followed immediately by white space. That will give // us the end of the header. // hdr->value_start = scan; for (;scan < (_header_text + _header_len); scan++) { if (*scan == '\n' && !isspace((unsigned char)*(scan + 1))) { break; } } hdr->value_len = scan - hdr->value_start; if (*(scan - 1) == '\r') { hdr->value_len -= 1; } scan += 1; _parsed_headers.append(hdr); hdr = new ParsedHeader; } // Made one to many. // delete hdr; } void RFCEnvelope::getTransportHeader(DtMailEnv & error, const char * name, DtMailValueSeq & value) { error.clear(); // First, let's try to find out how many times the header // appears. It may appear 1, many, or not at all. // int appears = 0; for (int hdr = 0; hdr < _parsed_headers.length(); hdr++) { // We need to lock the object until we are done. // MutexLock lock_header(_parsed_headers[hdr]->mutex); // Make sure we have a header! // if (!_parsed_headers[hdr]->name_start || !_parsed_headers[hdr]->value_start) { continue; } // Unix From doesn't count. We only use it as a fall back. // It will always appear as the first header, if it appears // at all. // if (hdr == 0 && strncmp(_parsed_headers[hdr]->name_start, "From ", 5) == 0) { continue; } if (matchName(*_parsed_headers[hdr], name) == DTM_TRUE) { // If the header exists, make sure it has a value. if (_parsed_headers[hdr]->value_len > 0) appears += 1; } } if (appears == 0) { // Not here! error.setError(DTME_NoObjectValue); return; } // Second pass, find the headers and convert the values to the // appropriate type. // int ent = 0; for (int val = 0; val < _parsed_headers.length(); val++) { if (val == 0 && strncmp(_parsed_headers[val]->name_start, "From ", 5) == 0) { continue; } if (matchName(*_parsed_headers[val], name) == DTM_TRUE) { RFCValue * new_value = new RFCValue(_parsed_headers[val]->value_start, _parsed_headers[val]->value_len, _parent->session()); value.append(new_value); } } return; } void RFCEnvelope::parseUnixFrom(DtMailEnv & error, const ParsedHeader & hdr, DtMailValueSeq & value) { error.clear(); // The value_start will point to the beginning of the address. // The Unix From header doesn't maintain all of the strange // quoting behavior so spaces don't appear. // const char *end; for (end = hdr.value_start; *end && !isspace((unsigned char)*end); end++) { continue; } int size = end - hdr.value_start; RFCValue * new_value = new RFCValue(hdr.value_start, size, _parent->session()); value.append(new_value); return; } void RFCEnvelope::parseUnixDate(DtMailEnv & error, const ParsedHeader & hdr, DtMailValueSeq & value) { error.clear(); // The value_start will point to the beginning of the address. // The Unix From header doesn't maintain all of the strange // quoting behavior so spaces don't appear. // const char * end; for (end = hdr.value_start; end < (hdr.value_start + hdr.value_len) && !isspace((unsigned char)*end); end++) { continue; } // Now end points at the white space between the sender and // the date it arrived. // for (; end < (hdr.value_start + hdr.value_len) && isspace((unsigned char)*end); end++) { continue; } // Now we are at the start of the date. // int size = (hdr.value_start + hdr.value_len) - end; RFCValue * new_value = new RFCValue(end, size, _parent->session()); value.append(new_value); return; } void RFCEnvelope::makeValue(DtMailEnv & error, const ParsedHeader & hdr, DtMailValueSeq & value) { error.clear(); RFCValue * new_value = new RFCValue(hdr.value_start, hdr.value_len, _parent->session()); value.append(new_value); } DtMailBoolean RFCEnvelope::matchName(const ParsedHeader & hdr, const char * name) { if (hdr.name_len != strlen(name)) { return(DTM_FALSE); } if (strncasecmp(hdr.name_start, name, hdr.name_len) == 0) { return(DTM_TRUE); } return(DTM_FALSE); } int RFCEnvelope::lookupHeader(const char * name, DtMailBoolean real_only) { // Look for the name in real space. // int hdr; int len = strlen(name); for (hdr = 0; hdr < _parsed_headers.length(); hdr++) { if (_parsed_headers[hdr]->name_start && strncasecmp(_parsed_headers[hdr]->name_start, name, len) == 0) { return(hdr); } } if (real_only == DTM_TRUE) { return(-1); } for (const AbstractMap * abs = abstract_map; abs->abstract; abs++) { if (strcmp(abs->abstract, name) == 0) { for (int trans = 0; abs->transports[trans]; trans++) { int slot = lookupHeader(abs->transports[trans], DTM_TRUE); if (slot >= 0) { return(slot); } } } } return(-1); } void RFCEnvelope::makeReply(DtMailEnv & error, const char * name, DtMailValueSeq & value) { error.clear(); // We have an abstract name. We need to loop through the // transport headers, gathering up the values. // int abs = 0; for (abs = 0; abstract_map[abs].abstract; abs++) { if (strcmp(abstract_map[abs].abstract, name) == 0) { break; } } if (!abstract_map[abs].abstract) { error.setError(DTME_NoObjectValue); } // Now we need to go through the list of transport names until // we find a match. The first match is taken because the map // should be ordered based on preference. // DtMailBoolean found = DTM_FALSE; DtMailValueSeq lvalue; for (int trans = 0; abstract_map[abs].transports[trans]; trans++) { getTransportHeader(error, abstract_map[abs].transports[trans], lvalue); if (error.isNotSet()) { // Found one! found = DTM_TRUE; break; } error.clear(); } if (found == DTM_FALSE) { error.setError(DTME_NoObjectValue); return; } if (_parent == NULL) { // We're done. Copy the values from one to the other. // for (int nc = 0; nc < lvalue.length(); nc++) { RFCValue * new_value = new RFCValue(*(lvalue[nc]), strlen(*(lvalue[nc])), _parent->session()); value.append(new_value); } return; } DtMail::MailRc * mailrc = _parent->session()->mailRc(error); // If metoo is set, then we are also done. // const char * mval; DtMailEnv lerror; mailrc->getValue(lerror, "metoo", &mval); if (lerror.isNotSet()) { for (int nc = 0; nc < lvalue.length(); nc++) { RFCValue * new_value = new RFCValue(*(lvalue[nc]), strlen(*(lvalue[nc])), _parent->session()); value.append(new_value); } return; } // Finally, the point of being here! We need to build a new // value that has the user stripped from the reply list. This // includes any alternates the user has specified. // passwd pw; GetPasswordEntry(pw); struct utsname uname_val; uname(&uname_val); char * my_addr = new char[strlen(pw.pw_name) + strlen(uname_val.nodename) + 5]; strcpy(my_addr, pw.pw_name); strcat(my_addr, "@"); strcat(my_addr, uname_val.nodename); DtMailAddressSeq alts; DtMailValueAddress * me = new DtMailValueAddress(my_addr, pw.pw_gecos, DtMailAddressDefault); alts.append(me); // Fetch the alternates, if any and add them to the list to strip. // const char * others = mailrc->getAlternates(lerror); if (others) { RFCTransport::arpaPhrase(others, alts); } // Finally, we need to see if the user wants us to ignore the host // component of the address when stripping. // DtMailBoolean allnet = DTM_FALSE; mailrc->getValue(lerror, "allnet", &mval); if (lerror.isNotSet()) { allnet = DTM_TRUE; } DtMailAddressSeq keepers; for (int nc = 0; nc < lvalue.length(); nc++) { DtMailAddressSeq * cur_val = lvalue[nc]->toAddress(); for (int naddr = 0; naddr < cur_val->length(); naddr++) { if (metooAddr(*(*cur_val)[naddr], alts, allnet) == DTM_FALSE) { DtMailValueAddress * kaddr = new DtMailValueAddress(*(*cur_val)[naddr]); keepers.append(kaddr); } } } // Finally, let's build a single string from the remaining list and // set the value to that string. // int max_len = 0; for (int cstr = 0; cstr < keepers.length(); cstr++) { DtMailValueAddress * addr = keepers[cstr]; max_len += strlen(addr->dtm_address) + 3; } if (max_len > 0) { char * str_addr = new char[max_len]; str_addr[0] = 0; for (int copy = 0; copy < keepers.length(); copy++) { DtMailValueAddress * addr = keepers[copy]; strcat(str_addr, addr->dtm_address); if (copy != (keepers.length() - 1)) { strcat(str_addr, ", "); } } RFCValue * new_val = new RFCValue(str_addr, strlen(str_addr), _parent->session()); value.append(new_val); delete str_addr; } } char * striphosts(char * addr) { char *cp, *cp2; if ((cp = strrchr(addr,'!')) != NULL) cp++; else cp = addr; /* * Now strip off all Internet-type * hosts. */ if ((cp2 = strchr(cp, '%')) == NULL) cp2 = strchr(cp, '@'); if (cp2 != NULL) *cp2 = '\0'; return(cp); } DtMailBoolean RFCEnvelope::metooAddr(DtMailValueAddress & addr, DtMailAddressSeq & alts, DtMailBoolean allnet) { char * str_addr_buf = strdup(addr.dtm_address); char * str_addr = str_addr_buf; if (allnet) { str_addr = striphosts(str_addr_buf); } for (int nalt = 0; nalt < alts.length(); nalt++) { char * cmp_addr_buf = strdup(alts[nalt]->dtm_address); char * cmp_addr = cmp_addr_buf; if (allnet) { cmp_addr = striphosts(cmp_addr_buf); } if (strcasecmp(str_addr, cmp_addr) == 0) { free(str_addr_buf); free(cmp_addr_buf); return(DTM_TRUE); } free(cmp_addr_buf); } free(str_addr_buf); return(DTM_FALSE); } // This method attempts to map an abstract name to a transport name. // When multiple transport names exist, the first is always used. // const char * RFCEnvelope::mapName(const char * name) { for (const AbstractMap * abs = abstract_map; abs->abstract; abs++) { if (strcmp(name, abs->abstract) == 0) { return(abs->transports[0]); } } // Must be a real name. // return(name); } RFCEnvelope::ParsedHeader::ParsedHeader(void) { mutex = MutexInit(); alloc_mask = 0; name_start = NULL; name_len = 0; value_start = NULL; value_len = 0; } RFCEnvelope::ParsedHeader::~ParsedHeader(void) { MutexLock lock_scope(mutex); if (alloc_mask & NAME_MASK) { free((char *)name_start); } if (alloc_mask & VALUE_MASK) { free((char *)value_start); } lock_scope.unlock_and_destroy(); }