Initial import of the CDE 2.1.30 sources from the Open Group.

This commit is contained in:
Peter Howkins
2012-03-10 18:21:40 +00:00
commit 83b6996daa
18978 changed files with 3945623 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
/*
*+SNOTICE
*
* $TOG: APOPServer.C /main/5 1998/11/10 17:06:52 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
/*
* Common Desktop Environment
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
* (c) Copyright 1995 Digital Equipment Corp.
* (c) Copyright 1995 Fujitsu Limited
* (c) Copyright 1995 Hitachi, Ltd.
*
*
* RESTRICTED RIGHTS LEGEND
*
*Use, duplication, or disclosure by the U.S. Government is subject to
*restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
*Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
*for non-DOD U.S. Government Departments and Agencies are as set forth in
*FAR 52.227-19(c)(1,2).
*Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
*International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
*Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
*Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
*Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
*Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
*Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <DtMail/DtMailServer.hh>
#include "md5.h"
APOPServer::APOPServer(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
: POP3Server(folder, session, mailbox,
append_mailbox_cb, append_mailbox_cb_data)
{
}
APOPServer::~APOPServer()
{
}
//
// Apply for connection authorization.
//
DTMailError_t
APOPServer::ptrans_authorize(char *greeting)
{
static const char
*pname = "APOPServer::ptrans_authorize";
static char ascii_digest [33];
char *start,*end;
char *msg;
DTMailError_t ok;
// Build MD5 digest from greeting timestamp + password.
// Find start of timestamp.
for (start = greeting; *start != 0 && *start != '<'; start++)
continue;
if (*start == 0)
{
_logger.logError(
DTM_FALSE,
"%s: APOP timestamp not found in greeting",
pname);
return DTME_MailServerAccess_AuthorizationFailed;
}
// Find end of timestamp.
for (end = start; *end != 0 && *end != '>'; end++)
continue;
if (*end == 0 || end == start + 1)
{
_logger.logError(
DTM_FALSE,
"%s: APOP timestamp not found in greeting",
pname);
return DTME_MailServerAccess_AuthorizationFailed;
}
else
*++end = '\0';
{
int i;
MD5_CTX context;
unsigned char digest[16];
// Copy timestamp and password into digestion buffer.
msg = (char*) malloc((end-start+1) + strlen(_password) + 1);
strcpy(msg, start);
strcat(msg, _password);
MD5Init(&context);
MD5Update(&context, (unsigned char*) msg, strlen(msg));
for (i = 0; i < 16; i++)
sprintf(ascii_digest+2*i, "%02x", digest[i]);
free(msg);
}
ok = do_transaction("APOP %s %s", _username, ascii_digest);
if (DTME_NoError != ok) return DTME_MailServerAccess_AuthorizationFailed;
return DTME_NoError;
}

View File

@@ -0,0 +1,285 @@
/*
*+SNOTICE
*
* $TOG: AUTOServer.C /main/6 1998/11/10 17:07:17 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
/*
* Common Desktop Environment
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
* (c) Copyright 1995 Digital Equipment Corp.
* (c) Copyright 1995 Fujitsu Limited
* (c) Copyright 1995 Hitachi, Ltd.
*
*
* RESTRICTED RIGHTS LEGEND
*
*Use, duplication, or disclosure by the U.S. Government is subject to
*restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
*Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
*for non-DOD U.S. Government Departments and Agencies are as set forth in
*FAR 52.227-19(c)(1,2).
*Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
*International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
*Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
*Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
*Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
*Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
*Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <DtMail/DtMailServer.hh>
AUTOServer::AUTOServer(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
: DtMailServer(folder, session, mailbox,
append_mailbox_cb, append_mailbox_cb_data)
{
_server = NULL;
}
AUTOServer::~AUTOServer()
{
}
//
// Set delete flag for given message.
//
DTMailError_t
AUTOServer::ptrans_delete(int number)
{
static char *pname = "AUTOServer::ptrans_delete";
if (_server) return _server->ptrans_delete(number);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Apply for connection authorization
//
DTMailError_t
AUTOServer::ptrans_authorize(char *buf)
{
static char *pname = "AUTOServer::ptrans_authorize";
if (_server) return _server->ptrans_authorize(buf);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Expunge deleted messages
//
DTMailError_t
AUTOServer::ptrans_fldstate_expunge()
{
static char *pname = "AUTOServer::ptrans_fldstate_expunge";
if (_server) return _server->ptrans_fldstate_expunge();
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Get range of messages to be fetched
//
DTMailError_t
AUTOServer::ptrans_fldstate_read(int *countp, int *newp)
{
static char *pname = "AUTOServer::ptrans_fldstate_read";
if (_server) return _server->ptrans_fldstate_read(countp, newp);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Capture the sizes of all messages.
//
DTMailError_t
AUTOServer::ptrans_msgsizes(int count, int *sizes)
{
static char *pname = "AUTOServer::ptrans_msgsizes";
if (_server) return _server->ptrans_msgsizes(count, sizes);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Is the given message old?
//
int
AUTOServer::ptrans_msgisold(int num)
{
static char *pname = "AUTOServer::ptrans_msgisold";
if (_server) return _server->ptrans_msgisold(num);
return 0;
}
//
// Quit the server
//
DTMailError_t
AUTOServer::ptrans_quit()
{
static char *pname = "AUTOServer::ptrans_quit";
if (_server) return _server->ptrans_quit();
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// request nth message
//
DTMailError_t
AUTOServer::ptrans_retrieve_start(int number, int *lenp)
{
static char *pname = "AUTOServer::ptrans_retrieve_start";
if (_server) return _server->ptrans_retrieve_start(number, lenp);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Parse command response
//
DTMailError_t
AUTOServer::ptrans_parse_response(char *argbuf)
{
static char *pname = "AUTOServer::ptrans_parse_response";
if (_server) return _server->ptrans_parse_response(argbuf);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}
//
// Retrieve messages using IMAP Version 2bis or Version 4.
//
void
AUTOServer::retrieve_messages(DtMailEnv &error)
{
if (NULL != _server)
{
_server->retrieve_messages(error);
return;
}
//
// First time through
//
for (int i=0; i<AUTO_NPROTOCOLS; i++)
{
if (NULL != _server)
delete _server;
switch (i)
{
case AUTO_POP3:
_server = new POP3Server(
_folder,
_session,
_mailbox,
_append_mailbox_cb,
_append_mailbox_cb_data);
break;
case AUTO_APOP:
_server = new APOPServer(
_folder,
_session,
_mailbox,
_append_mailbox_cb,
_append_mailbox_cb_data);
break;
case AUTO_IMAP:
_server = new IMAPServer(
_folder,
_session,
_mailbox,
_append_mailbox_cb,
_append_mailbox_cb_data);
break;
case AUTO_POP2:
_server = new POP2Server(
_folder,
_session,
_mailbox,
_append_mailbox_cb,
_append_mailbox_cb_data);
break;
}
if (NULL != _server)
{
if (NULL != _password)
_server->set_password(_password);
_server->retrieve_messages(error);
if (DTME_MailServerAccess_MissingPassword == (DTMailError_t) error)
{
delete _server;
_server = NULL;
return;
}
else if (error.isNotSet())
return;
}
}
}
//
// Discard tail of FETCH response after reading message text.
//
DTMailError_t
AUTOServer::ptrans_retrieve_end(int number)
{
static char *pname = "AUTOServer::ptrans_retrieve_end";
if (_server)
return _server->ptrans_retrieve_end(number);
_logger.logError(DTM_FALSE, "%s: NULL server\n", pname);
return DTME_MailServerAccess_Error;
}

View File

@@ -0,0 +1,106 @@
/*
*+SNOTICE
*
*
* $XConsortium: BigMalloc.C /main/4 1996/04/21 19:47:03 drk $
*
* 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
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#if defined(NEED_MMAP_WRAPPER)
extern "C" {
#endif
#include <sys/mman.h>
#if defined(NEED_MMAP_WRAPPER)
}
#endif
#include "BigMalloc.hh"
BigMalloc::BigMalloc(unsigned int size)
{
_size = size;
#if defined(MMAP_NORESERVE)
_fd = open("/dev/zero", O_RDONLY);
_buffer = mmap(NULL, size * 4, (PROT_READ | PROT_WRITE),
MAP_PRIVATE | MAP_NORESERVE, _fd, 0);
#else
_buffer = malloc(size);
#endif
}
BigMalloc::~BigMalloc(void)
{
#if defined(MAP_NORESERVE)
if (_buffer) {
munmap((char *)_buffer, _size * 4);
}
if (_fd >= 0) {
close(_fd);
}
#else
free(_buffer);
#endif
}
void
BigMalloc::Realloc(unsigned int size)
{
#if defined(MAP_NORESERVE)
if (size < (_size * 4)) {
return;
}
unsigned int additional = (size * 4) - (_size * 4);
char * new_buf;
new_buf = mmap(((char *)_buffer) + (_size * 4), additional,
(PROT_READ | PROT_WRITE),
MAP_FIXED | MAP_PRIVATE | MAP_NORESERVE, _fd, (_size * 4));
if (new_buf == (char *)-1) {
// Fixed mapping failed. We will have to map a new region and copy.
//
new_buf = mmap(NULL, size * 4, (PROT_READ | PROT_WRITE),
MAP_PRIVATE | MAP_NORESERVE, _fd, 0);
memcpy(new_buf, _buffer, _size * 4);
munmap((char *)_buffer, _size * 4);
}
_buffer = new_buf;
_size = size;
#else
_size = size;
_buffer = realloc(_buffer, _size);
#endif
}
BigMalloc::operator char*(void)
{
return((char *)_buffer);
}

View File

@@ -0,0 +1,42 @@
/*
*+SNOTICE
*
*
* $XConsortium: BigMalloc.hh /main/4 1996/04/21 19:47:07 drk $
*
* 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 _BIGMALLOC_H
#define _BIGMALLOC_H
#include <DtMail/DtLanguages.hh>
class BigMalloc : public DtCPlusPlusAllocator {
public:
BigMalloc(unsigned int size);
~BigMalloc(void);
void Realloc(unsigned int new_size);
operator char*(void);
private:
void * _buffer;
size_t _size;
int _fd;
};
#endif

View File

@@ -0,0 +1,345 @@
/*
*+SNOTICE
*
*
* $XConsortium: Buffer.C /main/6 1996/04/21 19:47:10 drk $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <DtMail/Buffer.hh>
#include <string.h>
#ifdef __osf__
#include <stdlib.h>
#else
#if defined(USL) && (OSMAJORVERSION == 2)
extern "C" {
#endif
#include <malloc.h>
#if defined(USL) && (OSMAJORVERSION == 2)
};
#endif
#endif // __osf__
#include <stdio.h>
#include <stdlib.h>
#include <DtMail/Threads.hh>
const int Buffer::defaultchunksize = 16 * 1024;
// buffer.C -- implement buffer class
// initialization
void
BufferMemory::initBuffer(int chunksize)
{
_firstreader = NULL;
_firstchunk = NULL;
_lastchunk = NULL;
_totalsize = 0;
_chunksize = chunksize;
_mutex = MutexInit();
}
BufferMemory::BufferMemory()
{
initBuffer(defaultchunksize);
}
BufferMemory::BufferMemory(int chunksize)
{
initBuffer(chunksize);
}
BufferMemory::~BufferMemory()
{
MutexLock mutex(_mutex);
// free the data in the buffer
Chunk *c = _firstchunk;
while (c) {
Chunk *next;
next = c->_nextchunk;
free(c->_buffer);
free(c);
c = next;
}
// disassociate us from all the readers
BufReaderMemory *r = _firstreader;
while (r) {
r->_buffer = NULL;
r = r->_nextreader;
}
// free the mutex
mutex.unlock_and_destroy();
}
Buffer::Buffer() { }
Buffer::~Buffer() { }
BufReader::~BufReader() { }
// buffer memory class functions
int
BufferMemory::appendData(const char *user_buffer, int length)
{
int numwritten = 0;
int numbytes;
MutexLock mutex(_mutex);
while (numwritten < length) {
if (! _lastchunk || _lastchunk->_chunksize <= _lastchunk->_currentend) {
// we need to get a new data chunk
if (newChunk(length - numwritten) < 0) {
// we had an allocation error
return (numwritten);
}
}
// number of free bytes in data chunk
numbytes = _lastchunk->_chunksize - _lastchunk->_currentend;
// don't write more than remaining bytes in user's request
if (numbytes > length - numwritten) {
numbytes = length - numwritten;
}
// do the copy
(void) memcpy(&_lastchunk->_buffer[_lastchunk->_currentend],
user_buffer, numbytes);
// update the counters
numwritten += numbytes;
_totalsize += numbytes;
_lastchunk->_currentend += numbytes;
user_buffer += numbytes;
}
return (numwritten);
}
// add a new data chunk to the buffer
int
BufferMemory::newChunk(int size)
{
// make sure we get at least the default chunksize
if (size < _chunksize) size = _chunksize;
// allocate the data regions
Chunk *d = (Chunk *) malloc(sizeof (Chunk));
if (! d) return (-1);
d->_buffer = (char *) malloc(size);
if (! d->_buffer) {
free (d);
return (-1);
}
d->_chunksize = size;
d->_currentend = 0;
// now splice it into the list
// lock should already have been called
d->_nextchunk = NULL;
if (_firstchunk == NULL) _firstchunk = d;
if (_lastchunk) {
_lastchunk->_nextchunk = d;
}
_lastchunk = d;
return (0);
}
BufReader *
BufferMemory::getReader(void)
{
BufReader *r;
MutexLock mutex(_mutex);
r = new BufReaderMemory(this);
return (r);
}
unsigned long
BufferMemory::iterate(Buffer::CallBack callback, ...)
{
va_list va;
MutexLock mutex(_mutex);
Chunk *c;
unsigned long ret = 0;
va_start(va, callback);
// walk through the chunk list, calling the callback for each one
for (c = _firstchunk; c; c = c->_nextchunk) {
// don't bother with null length chunks
if (c->_currentend == 0) continue;
// do the callback
ret = (*callback)(c->_buffer, c->_currentend, va);
// check for problems
if (ret) break;
}
return (ret);
}
//------------- beginning of bufreader code
BufReader::BufReader() {}
BufReaderMemory::BufReaderMemory(BufferMemory *b)
{
MutexLock mutex(b->_mutex);
_buffer = b;
_nextreader = b->_firstreader;
_prevreader = NULL;
if (b->_firstreader) {
b->_firstreader->_prevreader = this;
}
b->_firstreader = this;
_currentoffset = 0;
_currentchunk = NULL;
}
int
BufferMemory::getSize()
{
return (_totalsize);
}
int
BufReaderMemory::getData(char *user_buffer, int length)
{
int numread = 0;
int numbytes;
if (! _buffer) {
// the buffer has already been freed
return (0);
}
MutexLock mutex(_buffer->_mutex);
// handle starup case
if (_currentchunk == NULL) {
_currentchunk = _buffer->_firstchunk;
// see if buffer is still empty
if (!_currentchunk) {
return (0);
}
}
do {
// space in buffer
numbytes = _currentchunk->_currentend - _currentoffset;
if (numbytes <= 0) {
// we are at the end of this data chunk
if (_currentchunk->_nextchunk == NULL) {
// we are at the end of the valid data
break;
}
// advance to the next chunk
_currentchunk = _currentchunk->_nextchunk;
_currentoffset = 0;
}
// don't read more than user requested
if (numbytes > length - numread) {
numbytes = length - numread;
}
// copy the data
memcpy(user_buffer, &_currentchunk->_buffer[_currentoffset], numbytes);
// update all the pointers
numread += numbytes;
user_buffer += numbytes;
_currentoffset += numbytes;
} while (numread < length);
return (numread);
}
BufReaderMemory::~BufReaderMemory()
{
if (! _buffer) return;
MutexLock mutex(_buffer->_mutex);
// unlink us from the buffer's list
if (_nextreader) {
_nextreader->_prevreader = _prevreader;
}
if (_prevreader) {
_prevreader->_nextreader = _nextreader;
} else {
// ASSERT(_buffer->_firstreader == this);
_buffer->_firstreader = _nextreader;
}
}

View File

@@ -0,0 +1,558 @@
/*
*+SNOTICE
*
* $XConsortium: CAPIMethods.C /main/4 1996/04/21 19:47:13 drk $
*
* 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
*/
#include <DtMail/DtMail.h>
#include <DtMail/DtMail.hh>
extern "C" DtMailSession
DtMailCreateSession(CMEnv * error,
const char * app_name)
{
DtMailEnv err(error);
DtMail::Session * session = new DtMail::Session(err, app_name);
return((DtMailSession)session);
}
extern "C" void
DtMailCloseSession(CMEnv * error,
DtMailSession session,
DtMailBoolean)
{
DtMailEnv err(error);
DtMail::Session * _session = (DtMail::Session *)session;
err.clear();
delete _session;
}
extern "C" int
DtMailGetMinorCode(CMEnv * error)
{
DtMailEnv err(error);
return(DtMail::getMinorCode(err));
}
extern "C" const char *
DtMailGetErrorString(CMEnv * error)
{
DtMailEnv err(error);
return(DtMail::getErrorString(err));
}
extern "C" const char **
DtMailEnumerateImpls(DtMailSession session, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Session * _session = (DtMail::Session *)session;
return(_session->enumerateImpls(err));
}
extern "C" void
DtMailSetDefaultImpl(DtMailSession session,
CMEnv * error,
const char * impl)
{
DtMailEnv err(error);
DtMail::Session * _session = (DtMail::Session *)session;
_session->setDefaultImpl(err, impl);
return;
}
extern "C" const char *
DtMailGetDefaultImpl(DtMailSession session, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Session * _session = (DtMail::Session *)session;
return(_session->getDefaultImpl(err));
}
extern "C" void
DtMailQueryImpl(DtMailSession session,
CMEnv * error,
const char * impl,
const char * capability,
...)
{
DtMailEnv err(error);
va_list args;
DtMail::Session * _session = (DtMail::Session *)session;
va_start(args, capability);
_session->queryImplV(err, impl, capability, args);
va_end(args);
}
extern "C" DtMailMailBox
DtMailMailBoxConstruct(DtMailSession session,
CMEnv * error,
DtMailObjectSpace space,
void * path,
DtMailCallback cb_func,
void * client_data)
{
DtMailEnv err(error);
DtMail::Session * _session = (DtMail::Session *)session;
return((DtMailMailBox)_session->mailBoxConstruct(err,
space,
path,
cb_func,
client_data));
}
extern "C" void
DtMailMailBoxDestruct(DtMailMailBox mbox)
{
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
delete mb;
}
extern "C" void
DtMailMailBoxCreate(DtMailMailBox mbox, CMEnv * error)
{
DtMailEnv err(error);
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
mb->create(err);
}
extern "C" void
DtMailMailBoxOpen(DtMailMailBox mbox, CMEnv * error, DtMailBoolean auto_create)
{
DtMailEnv err(error);
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
mb->open(err, auto_create);
}
extern "C" DtMailMessage
DtMailMailBoxGetFirstMessage(DtMailMailBox mbox, CMEnv * error)
{
DtMailEnv err(error);
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
return((DtMailMessage)mb->getFirstMessage(err));
}
extern "C" DtMailMessage
DtMailMailBoxGetNextMessage(DtMailMailBox mbox, CMEnv * error, DtMailMessage last)
{
DtMailEnv err(error);
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
DtMail::Message *ml = (DtMail::Message *)last;
return((DtMailMessage)mb->getNextMessage(err, ml));
}
extern "C" DtMailMessage
DtMailMailBoxNewMessage(DtMailMailBox mbox, CMEnv * error)
{
DtMailEnv err(error);
DtMail::MailBox *mb = (DtMail::MailBox *)mbox;
return((DtMailMessage)mb->newMessage(err));
}
/*
extern "C" DtMailHeaderHandle
DtMailEnvelopeGetFirstHeader(DtMailEnvelope ev,
CMEnv * error,
char ** name,
DtMailValueSeq ** value,
CMBoolean translate_name)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
return(env->getFirstHeader(*err, name, value, translate_name));
}
extern "C" DtMailHeaderHandle
DtMailEnvelopeGetNextHeader(DtMailEnvelope ev,
CMEnv * error,
DtMailHeaderHandle last,
char ** name,
DtMailValueSeq ** value,
CMBoolean translate_name)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
return(env->getNextHeader(*err, last, name, value, translate_name));
}
extern "C" void
DtMailEnvelopeGetHeader(DtMailEnvelope ev,
CMEnv * error,
const CMGlobalName name,
DtMailValueSeq ** value)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
env->getHeader(*err, name, value);
}
extern "C" void
DtMailEnvelopeSetHeaderSeq(DtMailEnvelope ev,
CMEnv * error,
const CMGlobalName name,
const DtMailValueSeq * value)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
env->setHeaderSeq(*err, name, value);
}
extern "C" void
DtMailEnvelopeSetHeader(DtMailEnvelope ev,
CMEnv * error,
const CMGlobalName name,
const DtMailValue * value,
CMBoolean replace)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
env->setHeader(*err, name, value, replace);
}
extern "C" void
DtMailEnvelopeTransportName(DtMailEnvelope ev,
CMEnv * error,
CMGlobalName name,
char ** trans_name)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
env->transportName(*err, name, trans_name);
}
extern "C" CMObject
DtMailEnvelopeObject(DtMailEnvelope ev, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Envelope *env = (DtMail::Envelope *)ev;
return(env->object(err));
}
extern "C" void
DtMailEnvelopeDestroy(DtMailEnvelope ev)
{
DtMail::Envelope *env = (DtMail::Envelope *)ev;
delete env;
return;
}
extern "C" DtMailHeaderHandle
DtMailBodyPartGetFirstHeader(DtMailBodyPart bp,
CMEnv * error,
char ** name,
DtMailValueSeq ** value,
CMBoolean trans)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
return(bpp->getFirstHeader(*err, name, value, trans));
}
extern "C" DtMailHeaderHandle
DtMailBodyPartGetNextHeader(DtMailBodyPart bp,
CMEnv * error,
DtMailHeaderHandle hd,
char ** name,
DtMailValueSeq ** value,
CMBoolean trans)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
return(bpp->getNextHeader(*err, hd, name, value, trans));
}
extern "C" void
DtMailBodyPartGetHeader(DtMailBodyPart bp,
CMEnv * error,
const CMGlobalName name,
DtMailValueSeq ** value)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->getHeader(*err, name, value);
}
extern "C" void
DtMailBodyPartSetHeaderSeq(DtMailBodyPart bp,
CMEnv * error,
const CMGlobalName name,
const DtMailValueSeq * value)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->setHeaderSeq(*err, name, value);
}
extern "C" void
DtMailBodyPartSetHeader(DtMailBodyPart bp,
CMEnv * error,
const CMGlobalName name,
const DtMailValue * value,
CMBoolean replace)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->setHeader(*err, name, value, replace);
}
extern "C" void
DtMailBodyPartTransportName(DtMailBodyPart bp,
CMEnv * error,
CMGlobalName name,
char ** trans_name)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->transportName(*err, name, trans_name);
}
extern "C" CMObject
DtMailBodyPartObject(DtMailBodyPart bp, CMEnv * error)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
return(bpp->object(err));
}
extern "C" CMBoolean
DtMailBodyPartIsContainer(DtMailBodyPart bp, CMEnv *error)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
return(bpp->isContainer(err));
}
extern "C" DtMailMessage *
DtMailBodyPartGetEmbeddedMessage(DtMailBodyPart bp, CMEnv *error)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
return((DtMailMessage *)bpp->getEmbeddedMessage(err));
}
extern "C" void
DtMailBodyPartGetContents(DtMailBodyPart bp, CMEnv * error, void ** contents, unsigned long * length,
CMGlobalName * type)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->getContents(*err, contents, *length, type);
}
extern "C" void
DtMailBodyPartSetContents(DtMailBodyPart bp, CMEnv * error, const void * contents, const unsigned long length,
const CMGlobalName type)
{
DtMailEnv err(error);
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
bpp->setContents(*err, contents, length, type);
}
extern "C" void
DtMailBodyPartDestroy(DtMailBodyPart bp)
{
DtMail::BodyPart *bpp = (DtMail::BodyPart *)bp;
delete bpp;
}
extern "C" DtMailMessage
DtMailFileMessageConstruct(CMEnv * error,
CMSession session,
const char * path,
FileCallback cb_func,
void * client_data)
{
DtMailEnv err(error);
return((DtMailMessage)new DtMail::FileMessage(*err,
session,
path,
cb_func,
client_data));
}
extern "C" void
DtMailFileMessageDestruct(DtMailMessage msg)
{
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
delete fm;
}
extern "C" CMBoolean
DtMailFileMessageIsModified(DtMailMessage msg, CMEnv * error)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
return(fm->isModified(err));
}
extern "C" void
DtMailFileMessageRequestSave(DtMailMessage msg, CMEnv * error)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
fm->requestSave(err);
}
extern "C" void
DtMailFileMessageRequestRevert(DtMailMessage msg, CMEnv * error)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
fm->requestRevert(err);
}
extern "C" void
DtMailFileMessageRequestOpen(DtMailMessage msg, CMEnv * error)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
fm->requestOpen(err);
}
extern "C" void
DtMailFileMessageCreate(DtMailMessage msg, CMEnv * error)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
fm->create(err);
}
extern "C" void
DtMailFileMessageOpen(DtMailMessage msg, CMEnv * error, CMBoolean auto_create)
{
DtMailEnv err(error);
DtMail::FileMessage * fm = (DtMail::FileMessage *)msg;
fm->open(*err, auto_create);
}
extern "C" DtMailMessage
DtMailEmbeddedMessageCreate(CMEnv * error, DtMailMailBox owner)
{
DtMailEnv err(error);
DtMail::MailBox * mb = (DtMail::MailBox *)owner;
return((DtMailMessage)new DtMail::EmbeddedMessage(*err, *mb));
}
extern "C" void
DtMailEmbeddedMessageDestroy(DtMailMessage msg)
{
DtMailEnv err(error);
DtMail::EmbeddedMessage * em = (DtMail::EmbeddedMessage *)msg;
delete em;
}
extern "C" DtMailEnvelope
DtMailMessageGetEnvelope(DtMailMessage bmm, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
return((DtMailEnvelope)msg->getEnvelope(err));
}
extern "C" int
DtMailMessageGetBodyCount(DtMailMessage bmm, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
return(msg->getBodyCount(err));
}
extern "C" DtMailBodyPart *
DtMailMessageGetFirstBodyPart(DtMailMessage bmm, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
return((DtMailBodyPart *)msg->getFirstBodyPart(err));
}
extern "C" DtMailBodyPart *
DtMailMessageGetNextBodyPart(DtMailMessage bmm, CMEnv * error, DtMailBodyPart * bml)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
DtMail::BodyPart * last = (DtMail::BodyPart *)bml;
return((DtMailBodyPart *)msg->getNextBodyPart(*err, last));
}
extern "C" DtMailBodyPart *
DtMailMessageNewBodyPart(DtMailMessage bmm, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
return((DtMailBodyPart *)msg->newBodyPart(err));
}
extern "C" CMContainer
DtMailMessageContainer(DtMailMessage bmm, CMEnv * error)
{
DtMailEnv err(error);
DtMail::Message * msg = (DtMail::Message *)bmm;
return(msg->message(err));
}
*/

View File

@@ -0,0 +1,170 @@
/*
*+SNOTICE
*
* $TOG: DetermineFileLocality.C /main/9 1997/12/22 16:30:59 bill $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document 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
*/
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#if defined(SVR4)
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <sys/param.h>
#endif
#include <DtMail/DtMail.hh>
/*
* Returns: length of second argument if it is a prefix of the
* first argument, otherwise zero.
*/
static int
preflen(char * str, char * pref)
{
int len;
assert(str != NULL);
assert(pref != NULL);
len = strlen(pref);
if (strncmp(str, pref, len) == 0)
return (len);
return (0);
}
// DetermineFileLocality -- determine if specified path object is local
// or remote to the current system
// Arguments:
// const char * path -- -> path to object whose locality is to be determined
// Outputs:
// None.
// Returns:
// (DtmFileLocality) -- determined locality of the specified path object:
// FL_UNKNOWN -- locality of object cannot be determined
// FL_LOCAL -- the path object is local to this system
// FL_REMOTE -- the path object is remote to this system
// -- (such as an NFS mounted file system object)
// FL_LOCAL_AND_REMOTE -- the path object is locally available, yet
// -- it resides remotely (such as a CACHEFS object)
//
enum DtmFileLocality
DtMail::DetermineFileLocality(const char * path)
{
#if defined(SVR4)
FILE *mfp;
struct mnttab *mnt;
struct mnttab sysvmnt;
int fsTypeLen = 0;
int len;
char realPath[MAXPATHLEN]; // resolved symbolic link
char linkname[MAXPATHLEN]; // for symbolic link chasing
char fsType[MAXPATHLEN]; // fs type for name put here
struct statvfs statbuf;
int statvfs_successful = 0;
// Make sure the inputs to this function are correct
//
assert(path); // path must be specified
assert(strlen(path)); // cannot have a zero length
// Resolve all symbolic links in path so that we have a handle
// on the name of the actual file to check up on
//
(void) strncpy(realPath, path, MAXPATHLEN-1);
while (1) {
if ((len = readlink(realPath, linkname, sizeof (linkname)-1)) < 0)
break;
linkname[len] = '\0';
(void) strncpy(realPath, linkname, MAXPATHLEN-1);
}
// Try and determine where this file is located relative to here
//
for (int i = 0; ; i++)
{
fsTypeLen = 0;
switch (i)
{
case 0: // first instance -- try statvfs
statbuf.f_files = 0;
if (statvfs (realPath, &statbuf) == -1)
continue;
statvfs_successful++;
fsTypeLen = strlen(statbuf.f_basetype);
(void) strncpy(fsType, statbuf.f_basetype, MAXPATHLEN-1);
break;
case 1: // second instance -- scan mount table
if ( (mfp = fopen(MNTTAB, "r")) == NULL )
continue;
mnt = &sysvmnt;
while ((getmntent(mfp, mnt)) >= 0) {
len = preflen(realPath, mnt->mnt_mountp);
if (len >= fsTypeLen) {
fsTypeLen = len;
(void) strncpy(
fsType,
mnt->mnt_fstype ? mnt->mnt_fstype : "unknown-fstype",
MAXPATHLEN-1);
}
}
fclose(mfp);
break;
default: // run out of major options
if (statvfs_successful) // if statvfs successful, infer results
return(statbuf.f_files == -1 ? Dtm_FL_REMOTE : Dtm_FL_LOCAL);
return(Dtm_FL_UNKNOWN);
}
// At this point, if fsTypeLen > 0 then we have found a match.
// Return the proper Dtm_FL_xxx code according to the type of file system
// path object is located on
//
if (fsTypeLen == 0) // nothing found??
continue; // nope - try next pass
if (!strcmp(fsType, "cachefs")) // cached from anonymous source?
return(Dtm_FL_LOCAL_AND_REMOTE); // yes: file is local and remote
else if (!strcmp(fsType, "nfs")) // nfs resource?
return (Dtm_FL_REMOTE); // yes: file is remote only
else if (!strcmp(fsType, "ufs")) // ufs type file system?
return (Dtm_FL_LOCAL); // yes: file is local only
else if (!strcmp(fsType, "tmpfs")) // tmpfs local but transient file?
return (Dtm_FL_LOCAL); // yes: file is local
else if (!strcmp(fsType, "autofs")) // automounter mounting point??
return (Dtm_FL_REMOTE); // yes: file is remote
// no type that we recognize - try next pass
//
}
#else
int len = (int) strlen(path);
return(Dtm_FL_UNKNOWN);
#endif
}

View File

@@ -0,0 +1,167 @@
/*
*+SNOTICE
*
*
* $TOG: Dictionary.C /main/5 1997/12/22 16:32:11 bill $
*
* 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
*/
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <DtMail/Threads.hh>
#include <DtMail/Dictionary.hh>
DtMailDictionaryImpl::DtMailDictionaryImpl(int size)
{
_hash_size = size;
_hash_table = (HashTable_t *)malloc(sizeof(HashTable_t) * _hash_size);
for (int h = 0; h < _hash_size; h++) {
_hash_table[h] = NULL;
}
_obj_mutex = MutexInit();
}
DtMailDictionaryImpl::~DtMailDictionaryImpl(void)
{
MutexLock lock_scope(_obj_mutex);
if (_hash_table) {
for (int h = 0; h < _hash_size; h++) {
if (_hash_table[h]) {
delete _hash_table[h];
}
}
free(_hash_table);
_hash_table = NULL;
}
lock_scope.unlock_and_destroy();
}
void
DtMailDictionaryImpl::set(const char * key, const void * value)
{
MutexLock lock_scope(_obj_mutex);
int hash = hashValue(key);
// See if this key is already there. If so, simply update the value.
//
Entry * ent;
locate(hash, key, &ent);
if (ent) {
ent->value = value;
return;
}
// New key/value. Add it to the appropriate slot.
//
if (_hash_table[hash] == NULL) {
_hash_table[hash] = new DtVirtArray<Entry *>(16);
}
DtVirtArray<Entry *> * slot = _hash_table[hash];
ent = new Entry;
ent->key = strdup(key);
ent->value = value;
slot->append(ent);
return;
}
const void *
DtMailDictionaryImpl::lookup(const char * key)
{
MutexLock lock_scope(_obj_mutex);
int hash = hashValue(key);
Entry * ent;
locate(hash, key, &ent);
const void * value = NULL;
if (ent) {
value = ent->value;
}
return(value);
}
void
DtMailDictionaryImpl::remove(const char * key)
{
MutexLock lock_scope(_obj_mutex);
int hash = hashValue(key);
// Locate the entry. This approach will cause us to search
// the hash list twice, but that should be cheap enough that
// we can afford to do it.
//
Entry * ent;
locate(hash, key, &ent);
if (ent == NULL) {
// Not here, just return.
return;
}
DtVirtArray<Entry *> * slot = _hash_table[hash];
int loc = slot->indexof(ent);
slot->remove(loc);
return;
}
int
DtMailDictionaryImpl::hashValue(const char * key)
{
int hash = 0;
for (const char * cur = key; *cur; cur++) {
hash ^= *cur;
}
hash %= _hash_size;
return(hash);
}
void
DtMailDictionaryImpl::locate(int hash, const char * key, Entry ** ent)
{
*ent = NULL;
DtVirtArray<Entry *> * slot = _hash_table[hash];
if (slot == NULL) {
return;
}
for (int col = 0; col < slot->length(); col++) {
Entry * t_ent = (*slot)[col];
if (strcmp(t_ent->key, key) == 0) {
*ent = t_ent;
break;
}
}
return;
}

View File

@@ -0,0 +1,47 @@
/*
*+SNOTICE
*
*
* $XConsortium: DlDynamicLib.C /main/4 1996/04/21 19:47:23 drk $
*
* 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
*/
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include "DynamicLib.hh"
#include "DlDynamicLib.hh"
DlDynamicLib::DlDynamicLib(const char * path)
: DynamicLib(path)
{
_lib_handle = dlopen(path, RTLD_LAZY);
return;
}
DlDynamicLib::~DlDynamicLib(void)
{
if (_lib_handle) {
dlclose(_lib_handle);
}
}
void *
DlDynamicLib::getSym(const char * sym)
{
return(dlsym(_lib_handle, sym));
}

View File

@@ -0,0 +1,42 @@
/*
*+SNOTICE
*
*
* $XConsortium: DlDynamicLib.hh /main/4 1996/04/21 19:47:26 drk $
*
* 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
*/
// This implementation is for platforms that use dlopen/dlsym/dlclose.
//
#if !defined(_DLDYNAMICLIB_HH) && defined(DL_DYNAMIC_LIBS)
#define _DLDYNAMICLIB_HH
#include "DynamicLib.hh"
#include <dlfcn.h>
class DlDynamicLib : public DynamicLib {
public:
DlDynamicLib(const char * path);
virtual ~DlDynamicLib(void);
void * getSym(const char * symbol);
private:
void *_lib_handle;
};
#endif

View File

@@ -0,0 +1,34 @@
/*
*+SNOTICE
*
*
* $XConsortium: DtMailBodyPart.C /main/4 1996/04/21 19:47:29 drk $
*
* 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
*/
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
DtMail::BodyPart::BodyPart(DtMailEnv &, DtMail::Message * parent)
{
_parent = parent;
_obj_mutex = MutexInit();
}
DtMail::BodyPart::~BodyPart(void)
{
MutexDestroy(_obj_mutex);
}

View File

@@ -0,0 +1,43 @@
/*
*+SNOTICE
*
*
* $XConsortium: DtMailEnvelope.C /main/4 1996/04/21 19:47:32 drk $
*
* 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
*/
#include <string.h>
#include <stdlib.h>
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
DtMail::Envelope::Envelope(DtMailEnv & error, Message * parent)
{
_parent = parent;
_obj_mutex = MutexInit();
error.clear();
}
DtMail::Envelope::~Envelope(void)
{
if (_obj_mutex) {
MutexLock lock_scope(_obj_mutex);
if (_obj_mutex) {
lock_scope.unlock_and_destroy();
_obj_mutex = NULL;
}
}
}

View File

@@ -0,0 +1,606 @@
/*
*+SNOTICE
*
* $TOG: DtMailError.C /main/18 1999/02/08 09:32:25 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document 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
*/
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <errno.h>
#include <DtMail/DtMail.hh>
#include <DtMail/DtMailError.hh>
#include <DtMail/Common.h>
#include <Dt/MsgCatP.h>
#include <syslog.h>
#if defined(HPUX) && !defined(hpV4)
// HP-UX 9.* syslog.h does not define these.
//
extern "C" int syslog(int, const char *, ...);
extern "C" int openlog(const char *, int, int);
#endif
#include <EUSDebug.hh>
// Provide interface to the DtSvc function DtSimpleError
// When this interface is better defined, this can be removed
// and replaced with the appropriate include file
typedef enum {
DtIgnore,
DtInformation,
DtWarning,
DtError,
DtFatalError,
DtInternalError
} DtSeverity;
extern "C" void _DtSimpleError(
char *progName,
DtSeverity severity,
char *help,
char *format,
...) ;
int DtMailDebugLevel = 0;
DtMailBoolean DtMailEnv::_syslog_open = DTM_FALSE;
nl_catd DtMailEnv::_errorCatalog = (nl_catd) -1;
const char * DtMailEnv::DtMailCatalogDataFile = "libDtMail";
nl_catd DtMailMsgCat = DtMailEnv::_errorCatalog;// COMPATIBILITY
//
// NOTE - IMPORTANT -- READ ME
//
// The order of the strings below must match the
// entries in DtMail/MailError.h.
//
static const char * error_strings[] = {
// - DTME_NoError
"No error occurred.",
// - DTME_AlreadyLocked
"The mailbox is locked by another session.",
// - DTME_BadArg
"A bad argument was passed as a parameter to the operation.",
// - DTME_BadMailAddress
"The specified mail address could not be processed.",
// - DTME_BadRunGroup
"The dtmail program is not running as group \"mail\".",
// - DTME_FileCreateFailed
"The requested file could not be created.",
// - DTME_FolderNotSet
"The mailbox to incorporate was not set.",
// - DTME_GetLockRefused
"The user refused to take the lock of a locked mailbox.",
// - DTME_ImplFailure
"The specified implementation could not perform the requested operation.",
// - DTME_InitializationFailed
"The instance could not be initialized.",
// - DTME_InternalFailure
"An internal failure occurred while performing the operation.",
// - DTME_InvalidError
"The error structure is invalid.",
// - DTME_InvalidOperationSequence
"An operation was attempted before the instance was initialized.",
// - DTME_MD5ChecksumFailed
"The MD5 signature did not match the message contents.",
// - DTME_MailTransportFailed
"Unable to communicate with the mail transport.",
// - DTME_NoDataType
"There is no data type that matches the transport type.",
// - DTME_NoImplementations
"No implementations were found for the mail library.",
// - DTME_NoMailBox
"The mailbox was uninitialized at load time.",
// - DTME_NoMemory
"No memory available for operation.",
// - DTME_NoMsgCat
"No message catalog exists for DtMail.",
// - DTME_NoNewMail
"There is no new mail to incorporate.",
// - DTME_NoObjectValue
"No value for the object could be found.",
// - DTME_NoSuchFile
"The mailbox does not exist and creation was not requested.",
// - DTME_NoSuchImplementation
"The specified implementation does not exist.",
// - DTME_NoSuchType
"The data type is not known to the library.",
// - DTME_NoUser
"The user for this session could not be identified.",
// - DTME_NotInbox
"The file specified is not a mailbox.",
// - DTME_NotLocked
"The mailbox is not locked for access.",
// - DTME_NotMailBox
"The requested file is not a mailbox in any format recognized by this implementation.",
// - DTME_NotSupported
"The operation is not supported by the current implementation.",
// - DTME_ObjectAccessFailed
"Unable to access an object required to complete the operation.",
// - DTME_ObjectCreationFailed
"Unable to create an object required to complete the operation.",
// - DTME_ObjectInUse
"An attempt was made to initialize an object that was already initialized.",
// - DTME_ObjectInvalid
"An invalid object was referenced.",
// - DTME_OpenContainerInterrupted
"The user interrupted the process of opening a mailbox.",
// - DTME_OperationInvalid
"An internal error occurred while performing the operation.",
// - DTME_OtherOwnsWrite
"Another mail program owns the write access to the mailbox.",
// - DTME_RequestDenied
"The other session denied the request for lock or copy.",
// - DTME_TTFailure
"A ToolTalk message could not be processed.",
// - DTME_TransportFailed
"The mail delivery transport failed.",
// - DTME_UnknownFormat
"The message is not in one of the supported formats.",
// - DTME_UnknownOpenError
"An unknown error occurred when opening a mailbox.",
// - DTME_UserAbort
"The user aborted the operation.",
// - DTME_UserInterrupted
"The user interrupted the operation.",
// - DTME_ObjectReadOnly
"The mailbox permissions only allow read access.",
// - DTME_NoPermission,
"The user does not have access to the mailbox.",
// - DTME_IsDirectory,
"The specified path is a directory.",
// - DTME_CannotRemoveStaleMailboxLockFile
"Cannot lock mailbox (could not remove stale lock file).\nStale lock file: %s\nReason: %s",
// - DTME_CannotCreateMailboxLockFile
"Cannot lock mailbox (could not create lock file).\nMailbox lock file: %s\nReason: %s",
// - DTME_CannotCreateMailboxLockFile_NoPermission
"Cannot create lock file and lock mailbox because the user does not have\naccess to either the mailbox or the directory containing the mailbox.",
// - DTME_CannotCreateMailboxLockFile_IsDirectory
"Cannot create lock file and lock mailbox because the name for the\nmailbox lock file already exists and is a directory.",
// - DTME_CannotCreateMailboxLockFile_NoSuchFile
"Cannot create lock file and lock mailbox because a component of the\npath name of the lock file is not a directory.",
// - DTME_CannotCreateMailboxLockFile_RemoteAccessLost
"Cannot create lock file and lock mailbox because the remote system on\nwhich the lock file was to be created is no longer accessible.",
// - DTME_CannotObtainInformationOnOpenMailboxFile
"Cannot obtain information on current mailbox file.\nMailbox file: %s\nReason: %s",
// - DTME_CannotCreateTemporaryMailboxFile
"Cannot create temporary mailbox file.\nTemporary Mailbox file: %s\nReason: %s",
// - DTME_CannotCreateTemporaryMailboxFile_NoPermission
"Cannot create temporary mailbox file because the user does not have\naccess to either the mailbox or the directory containing the mailbox.",
// - DTME_CannotCreateTemporaryMailboxFile_IsDirectory
"Cannot create temporary mailbox file because the name for the\ntemporary mailbox already exists and is a directory.",
// - DTME_CannotCreateTemporaryMailboxFile_NoSuchFile
"Cannot create temporary mailbox file because a component of the\npath name of the temporary file is not a directory.",
// - DTME_CannotCreateTemporaryMailboxFile_RemoteAccessLost
"Cannot create temporary mailbox file because the remote system on\nwhich the file was to be created is no longer accessible.",
// - DTME_CannotSetPermissionsOfTemporaryMailboxFile
"Cannot set permissions on temporary mailbox file.\nTemporary Mailbox file: %s\nPermissions requested: %o\nReason: %s",
// - DTME_CannotSetOwnerOfTemporaryMailboxFile
"Cannot set owner of temporary mailbox file.\nTemporary Mailbox file: %s\nOwner uid requested: %d\nReason: %s",
// - DTME_CannotSetGroupOfTemporaryMailboxFile
"Cannot set group of temporary mailbox file.\nTemporary Mailbox file: %s\nGroup gid requested: %d\nReason: %s",
// - DTME_CannotWriteToTemporaryMailboxFile
"Cannot write to temporary mailbox file.\nTemporary Mailbox file: %s\nReason: %s",
// - DTME_CannotWriteToTemporaryMailboxFile_ProcessLimitsExceeded
"Cannot write to temporary mailbox file because the process's file\nsize limit or the maximum file size has been reached.",
// - DTME_CannotWriteToTemporaryMailboxFile_RemoteAccessLost
"Cannot write to temporary mailbox file because the remote system on\nwhich the file was created is no longer accessible.",
// - DTME_CannotWriteToTemporaryMailboxFile_NoFreeSpaceLeft
"Cannot write to temporary mailbox file because there is no free\nspace left on the device on which the file was created.",
// - DTME_CannotReadNewMailboxFile
"Cannot read new mailbox file\nReason: %s",
// - DTME_CannotReadNewMailboxFile_OutOfMemory
"Cannot read new mailbox file because no memory is available for the operation.",
// - DTME_CannotRemoveMailboxLockFile
"Cannot unlock mailbox (could not remove lock file).\nMailbox lock file: %s\nReason: %s",
// - DTME_CannotRenameNewMailboxFileOverOld
"Cannot rename new mailbox file over old mailbox file.\nOld mailbox file still exists but complete and correct contents\nof mailbox contents have been saved in the new mailbox file.\nThis problem must be corrected manually as soon as possible.\nOld Mailbox file: %s\nNew Mailbox file: %s\nReason: %s",
// - DTME_InternalAssertionFailure
"An internal error has occurred within this application.\nThere is no way to recover and continue from this error.\nError condition: %s\n",
// - DTME_ResourceParsingNoEndif
"An error occurred while parsing the .mailrc resource file.\nThere is a conditional if statement that does not have a corresponding endif statement.\n",
// - DTME_AlreadyOpened,
"This mail folder is already opened.",
// - DTME_OutOfSpace,
"No Space on Temporary Filesystem.",
// - DTME_CannotCreateMailboxDotDtmailLockFile
"Mailer has detected a mailbox lockfile:\n%s",
// - DTME_MailboxInodeChanged
"Mailer can no longer access this mailbox.\nIt would be best to close and reopen it.",
// - DTME_MailServerAccess_AuthorizationFailed
"Cannot retrieve mail for '%s@%s' using '%s'.\nAuthorization failed.",
// - DTME_MailServerAccess_Error
"Cannot retrieve mail for '%s@%s' using '%s'.\nThe server returned:\n %s",
// - DTME_MailServerAccess_MissingPassword
"Please enter a password for '%s@%s' using '%s'",
// - DTME_MailServerAccess_ProtocolViolation
"Cannot retrieve mail for '%s@%s' using '%s'.\nClient/server protocol error.",
// - DTME_MailServerAccess_ServerTimeoutError
"Cannot retrieve mail for '%s@%s' using '%s'.\nTimed out waiting for server.",
// - DTME_MailServerAccess_SocketIOError
"Cannot retrieve mail for '%s@%s' using '%s'.\n%s.",
// - DTME_AppendMailboxFile_Error
"Cannot append to mailbox",
// - DTME_AppendMailboxFile_FileTooBig
"Cannot append to mailbox: %s\nSYSERROR(%d): %s.",
// - DTME_AppendMailboxFile_LinkLost
"Cannot append to mailbox: %s\nSYSERROR(%d): %s.",
// - DTME_AppendMailboxFile_NoSpaceLeft
"Cannot append to mailbox: %s\nSYSERROR(%d): %s.",
// - DTME_AppendMailboxFile_SystemError
"Cannot append to mailbox: %s\nSYSERROR(%d): %s.",
// - DTME_GetmailCommandRetrieval_SystemError
"Getmail command failed: %s\nSYSERROR(%d): %s.",
// - DTME_GetmailCommandRetrieval_AbnormalExit
"Getmail command exited abnormally: %s.",
// - DTME_PathElementPermissions
"Search permission denied on a component of the path prefix,\n'%s'.",
// - DTME_PathElementNotDirectory
"A component of the path prefix is not a directory,\n'%s'.",
// - DTME_PathElementDoesNotExist
"A component of the path prefix does not exist,\n'%s'.",
// - DTME_MailServerAccessInfo_SocketOpen
"Opening connection for '%s@%s'.",
// - DTME_MailServerAccessInfo_NoMessages
"No messages for '%s@%s'.",
// - DTME_MailServerAccessInfo_RetrievingMessage
"Retrieving message %d of %d for '%s@%s'.",
// - DTME_MailServerAccessInfo_MessageTooLarge
"Skipping oversized message (%d bytes).",
// - DTME_MAXDTME
NULL
};
DtMailEnv::DtMailEnv()
{
setCPP(NULL,NULL,NULL);
_error = DTME_NoError;
_message = NULL;
_tt_message = NULL;
_client = NULL;
_implClearFunc = NULL;
_fatal = DTM_FALSE;
}
#ifdef hpV4
#define GETMSG(catd, set, msg, dft) _DtCatgetsCached(catd, set, msg, dft)
#else
#define GETMSG(catd, set, msg, dft) catgets(catd, set, msg, dft)
#endif
char *
DtMailEnv::getMessageText(int set, int msg, char *dft)
{
static int oneTimeFlag = 0; // Only attempt to open message catalog once
char *message;
if ((oneTimeFlag == 0) && (_errorCatalog == (nl_catd) -1))
{
oneTimeFlag++;
_errorCatalog = catopen((char*) DtMailCatalogDataFile, NL_CAT_LOCALE);
}
if (_errorCatalog != (nl_catd) -1)
message = GETMSG(_errorCatalog, set, msg, dft);
return message;
}
void
DtMailEnv::getErrorMessageText()
{
if (_message == NULL)
{
if (_error_minor_code >= DTME_MAXDTME)
_error_minor_code = DTME_InvalidError;
_message = getMessageText(
MailErrorSet, _error_minor_code + 1,
(char*) error_strings[_error_minor_code]);
}
if (_message == NULL)
{
_error = DTME_NoMemory;
_message = strdup(error_strings[_error_minor_code]);
}
else
_message = strdup(_message);
}
void
DtMailEnv::clear()
{
_error = DTME_NoError;
if (_message != NULL) {
free((char *)_message);
_message = NULL;
}
if (_tt_message != NULL) {
tt_message_destroy(_tt_message);
_tt_message = NULL;
}
if (_client != NULL && _implClearFunc != NULL) {
implClear();
}
_fatal = DTM_FALSE;
}
void
DtMailEnv::setError(const DTMailError_t minor_code,
DtMailBoolean fatal,
Tt_message msg)
{
clear(); // Clear out and free any old storage.
_error_minor_code = minor_code; // Remember original error number
if (minor_code != DTME_NoError ) {
_error = minor_code;
if (minor_code >= DTME_MAXDTME) {
_error = DTME_InvalidError;
}
}
_tt_message = msg; // Save the new one.
_fatal = fatal;
return;
}
// given system error number, include that string into the given message,
// which must have a %s embedded within it
//
// DtMailEnv::errnoMessage -- convert current system error number to readable text
// Description:
// Take the current system error number (in the global errno), and
// return a pointer to a readable string that describes the error.
// Arguments:
// <none>
// Outputs:
// <none>
// Returns:
// const char * -- pointer to ascii text describing current system error
// that is safe to refer to in an MT-hot environment
//
const char *
DtMailEnv::errnoMessage(void)
{
return(errnoMessage(errno));
}
// DtMailEnv::errnoMessage -- convert system error number to readable text
// Description:
// Given a valid system error number (as returned in the global errno),
// return a pointer to a readable string that describes the error.
// Arguments:
// systemErrorNumber - errno value
// Outputs:
// <none>
// Returns:
// const char * -- pointer to ascii text describing system error
// that is safe to refer to in an MT-hot environment
//
const char *
DtMailEnv::errnoMessage(int systemErrorNumber)
{
// Get the system error message for the given system error
//
const char *syserrstr = strerror(systemErrorNumber);
if (!syserrstr)
syserrstr = (const char *)"?";
return(syserrstr);
}
// allow variable arguments at end and call vsprintf to process the
// error message string
//
void
DtMailEnv::vSetError(const DTMailError_t minor_code,
DtMailBoolean fatal,
Tt_message msg,
... )
{
const int MessageBufferSize = 4096;
char *messageBuffer = new char[MessageBufferSize+1];
// allow error to come up with the final translated error message
//
setError(minor_code, fatal, msg);
if (_message == NULL)
getErrorMessageText();
// Use the current error message as a format to vsprintf to
// construct the final message
//
va_list var_args;
va_start(var_args, msg);
(void) vsprintf(messageBuffer, _message, var_args);
assert(strlen(messageBuffer) < MessageBufferSize);
va_end(var_args);
free((char *)_message);
_message = (const char *)strdup(messageBuffer);
delete [] messageBuffer;
}
#ifdef DEAD_WOOD
const char *
DtMailEnv::implGetMessage()
{
if (_client != NULL && _implMessageFunc != NULL) {
return((*_implMessageFunc)(_client));
}
return(NULL);
}
int
DtMailEnv::implGetError()
{
if (_client != NULL && _implErrorFunc != NULL) {
return((*_implErrorFunc)(_client));
}
return(0);
}
#endif /* DEAD_WOOD */
void
DtMailEnv::logError(DtMailBoolean criticalError, const char *format, ...) const
{
const int MessageBufferSize = 8192;
char *messageBuffer = new char[MessageBufferSize+1];
if (!_syslog_open) {
//
// Open the log device and:
// LOG_PIG - log the pid number of process.
// LOG_CONS - log to the console, if the log device can not be opened.
// LOG_NOWAIT - Do not wait for syslog to finish, avoids the use of SIGCHLD
//
openlog("libDtMail", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_MAIL);
}
va_list var_args;
va_start(var_args, format);
(void) vsprintf(messageBuffer, format, var_args);
assert(strlen(messageBuffer) < MessageBufferSize);
va_end(var_args);
syslog(criticalError == DTM_TRUE ? LOG_CRIT|LOG_ERR : LOG_ERR,
messageBuffer);
_DtSimpleError("libDtMail", criticalError == DTM_TRUE ? DtError : DtWarning,
NULL, messageBuffer);
delete [] messageBuffer;
}
#ifdef DEAD_WOOD
void
DtMailEnv::logFatalError(DtMailBoolean criticalError, const char *format, ...)
{
_fatal = DTM_TRUE;
va_list var_args;
va_start(var_args, format);
logError(criticalError, format, var_args);
va_end(var_args);
}
#endif /* DEAD_WOOD */

View File

@@ -0,0 +1,107 @@
/*
*+SNOTICE
*
*
* $TOG: DtMailMailBox.C /main/6 1997/09/26 09:07:17 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 <string.h>
#include <stdlib.h>
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
#include <DtMail/IO.hh>
DtMail::MailBox::MailBox(DtMailEnv & error,
Session * session,
DtMailObjectSpace space,
void * arg,
DtMailCallback cb,
void * clientData)
{
_hide_access_events = DTM_FALSE;
_key = session->newObjectKey();
_session = session;
error.clear();
_space = space;
_arg = arg;
_errmsg_func = NULL;
_err_data = NULL;
_callback = cb;
_cb_data = clientData;
_obj_mutex = MutexInit();
}
DtMail::MailBox::~MailBox(void)
{
if (_obj_mutex) {
MutexDestroy(_obj_mutex);
_obj_mutex = NULL;
_session->removeObjectKey(_key);
}
}
void
DtMail::MailBox::appendCB(
DtMailEnv &error,
char *buf,
int len,
void *clientData)
{
DtMail::MailBox *obj = (DtMail::MailBox*) clientData;
if (NULL == obj) return;
obj->append(error, buf, len);
}
DtMail::Session *
DtMail::MailBox::session(void)
{
return(_session);
}
DtMailBoolean
DtMail::MailBox::mailBoxWritable(DtMailEnv & error)
{
error.clear();
return(_mail_box_writable);
}
void
DtMail::MailBox::registerErrMsgFunc(err_func errmsg_func, void * err_data)
{
_errmsg_func = errmsg_func;
_err_data = err_data;
}
void
DtMail::MailBox::unregisterErrMsgFunc(DtMailEnv&)
{
_errmsg_func = NULL;
_err_data = NULL;
}
void
DtMail::MailBox::showError(char *fsnam)
{
if (_errmsg_func && _err_data) {
_errmsg_func(fsnam,FALSE,_err_data);
}
}

View File

@@ -0,0 +1,62 @@
/*
*+SNOTICE
*
*
* $XConsortium: DtMailMessage.C /main/4 1996/04/21 19:47:38 drk $
*
* 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
*/
#include <string.h>
#include <stdlib.h>
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
DtMail::Message::Message(DtMailEnv & error, MailBox * parent)
{
_parent = parent;
_obj_mutex = MutexInit();
// TOGO _message = NULL;
_envelope = NULL;
_session = NULL;
error.clear();
}
DtMail::Message::~Message(void)
{
if (_obj_mutex) {
MutexLock lock_scope(_obj_mutex);
if (_obj_mutex) {
if (_envelope) {
delete _envelope;
}
lock_scope.unlock_and_destroy();
_obj_mutex = NULL;
}
}
}
DtMail::MailBox *
DtMail::Message::mailBox(void)
{
return(_parent);
}
DtMail::Session *
DtMail::Message::session(void)
{
return(_session);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,837 @@
/*
*+SNOTICE
*
* $TOG: DtMailServer.C /main/23 1999/01/29 14:46:18 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <DtMail/DtMailError.hh>
#include <DtMail/DtMailServer.hh>
#include <DtMail/IO.hh>
#if defined(USE_ITIMER_REAL)
#define SIGNAL_TYPE SIGALRM
#define ITIMER_TYPE ITIMER_REAL
#else
#define SIGNAL_TYPE SIGVTALRM
#define ITIMER_TYPE ITIMER_VIRTUAL
#endif
#define dtmasTAGCLR() *_transtag = '\0'; _transnum=0;
#define dtmasTAGGEN() (sprintf(_transtag, "a%04d", ++_transnum), _transtag)
#define dtmasTAGGET() (_transtag)
static jmp_buf restart;
DtMailServer::DtMailServer(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
{
struct passwd pw;
GetPasswordEntry(pw);
if (folder)
_folder = strdup(folder);
else
_folder = "INBOX";
_session = session;
_mailbox = mailbox;
_append_mailbox_cb = append_mailbox_cb;
_append_mailbox_cb_data
= append_mailbox_cb_data;
_protologging = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_PROTOLOGGING,
(Boolean) False);
_protologgingplus = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_PROTOLOGGINGPLUS,
(Boolean) False);
_errorstring = NULL;
_password = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_PASSWORD,
NULL, DTM_TRUE);
_removeafterdelivery
= get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_REMOVEAFTERDELIVERY,
True);
_retrieveold = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_RETRIEVEOLD,
True);
_retrieveerrors = 0;
_servername = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_SERVERNAME,
DTMAS_PROPDFLT_SERVERNAME);
_shroud = NULL;
_sizelimit = 0;
_sockfp = NULL;
dtmasTAGCLR();
_transnum = 0;
_timeout = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_TIMEOUT,
DTMAS_TIMEOUT);
_username = get_mailrc_value(
_session, _folder,
DTMAS_PROPKEY_USERNAME,
pw.pw_name);
}
DtMailServer::~DtMailServer()
{
if (_errorstring) free(_errorstring);
if (_folder) free(_folder);
if (_password) free(_password);
if (_servername) free(_servername);
if (_shroud) free(_shroud);
if (_username) free(_username);
}
void
DtMailServer::set_password(char *password)
{
if (NULL == password) return;
if (NULL != _password) free(_password);
_password = NULL;
if (NULL != password) _password = strdup(password);
}
//
// Read message content and append to mailbox
//
// len - Length of message.
//
#if defined(sun) || defined(USL)
#define SA_HANDLER_TYPE void (*)(void)
#else
#define SA_HANDLER_TYPE void (*)(int)
#endif
DTMailError_t
DtMailServer::ptrans_retrieve_readandappend(
DtMailEnv &error,
long len)
{
static char *pname = "DtMailServer::ptrans_retrieve_readandappend";
static char *from = "From ";
struct sigaction action, o_action;
int from_done = FALSE;
int done = FALSE;
size_t nread = 0;
char *s, *t;
memset((char*) &action, 0, sizeof(struct sigaction));
memset((char*) &o_action, 0, sizeof(struct sigaction));
action.sa_handler = (SA_HANDLER_TYPE) SIG_IGN;
sigaction(SIGINT, (const struct sigaction *) &action, &o_action);
while (! done)
{
size_t nbytes;
if (nread < len)
{
if (DTMAS_MSGBUFSIZE - 1 > len - nread)
nbytes = (size_t) len - nread;
else
nbytes = DTMAS_MSGBUFSIZE - 1;
if (0 == (nbytes=SockRead(_msgbuf, 1, nbytes, _sockfp)))
{
_logger.logError(
DTM_FALSE,
"Failed to retrieve %d bytes.",
len);
return DTME_MailServerAccess_SocketIOError;
}
_msgbuf[nbytes] = '\0';
}
else
{
if (NULL == SockGets(_msgbuf, DTMAS_MSGBUFSIZE, _sockfp))
{
_logger.logError(DTM_FALSE, "Failed to retrieve %d bytes", len);
return DTME_MailServerAccess_SocketIOError;
}
nbytes = strlen(_msgbuf);
}
nread += nbytes;
// Delete all carriage returns
for (s = t = _msgbuf; *s; s++)
if (*s != '\r') *t++ = *s;
*t = '\0';
if (_protologgingplus)
_logger.logError(
DTM_FALSE,
"INFO: read %d of %d octets %d remaining\n%s< %s\n",
nbytes, len, len-nread, proto_name(), _msgbuf);
// Determine if we are done with this message.
if (proto_is_delimited())
{
char *s = strrchr((const char *) _msgbuf, (int) '.');
if (s &&
(s == _msgbuf || *(s-1) == '\n') &&
(*s == '.') &&
(*(s+1) == '\n'))
{
*s = '\0';
done = TRUE;
}
}
else if (nread >= len)
done = TRUE;
if (0 < (nbytes = strlen(_msgbuf)))
{
if (! from_done && strncmp(_msgbuf, from, strlen(from)))
{
time_t clock;
char buffer[BUFSIZ];
clock = time(&clock);
sprintf(buffer, "%s %s %s",
from, _servername, ctime((const time_t *) &clock));
_append_mailbox_cb(
error, buffer, strlen(buffer),
_append_mailbox_cb_data);
}
from_done = TRUE;
_append_mailbox_cb(error, _msgbuf, nbytes, _append_mailbox_cb_data);
}
if (error.isSet())
{
error.logError(
DTM_TRUE,
"%s: Failed to append mailbox %s: %s.\n",
pname, _folder, error.errnoMessage());
return DTME_AppendMailboxFile_Error;
}
}
// Message separation.
_append_mailbox_cb(error, "\n", 1, _append_mailbox_cb_data);
// Sink the file pointer.
sigaction(SIGINT, (const struct sigaction *) &o_action, NULL);
return DTME_NoError;
}
//
// Assemble command in printf(3) style and send to the server.
//
DTMailError_t
DtMailServer::do_send(char *fmt, ... )
{
static char *pname = "DtMailServer::do_send";
char *buf = new char[DTMAS_POPBUFSIZE+1];
int nbytes;
va_list ap;
DtMailEnv error;
if (proto_is_tagged())
{
dtmasTAGGEN();
(void) sprintf(buf, "%s ", dtmasTAGGET());
}
else
{
dtmasTAGCLR();
buf[0] = '\0';
}
va_start(ap, fmt);
vsprintf(buf + strlen(buf), fmt, ap);
va_end(ap);
strcat(buf, "\r\n");
nbytes = SockWrite(buf, 1, strlen(buf), _sockfp);
if (nbytes != strlen(buf))
{
_logger.logError(DTM_FALSE, "Socket Error: writing '%s'", buf);
delete [] buf;
return DTME_MailServerAccess_SocketIOError;
}
if (_protologging)
{
char *cp;
if (_shroud && (cp = strstr(buf, _shroud)))
memset(cp, '*', strlen(_shroud));
buf[strlen(buf)-1] = '\0';
_logger.logError(DTM_FALSE, "%s> %s", proto_name(), buf);
}
delete [] buf;
return DTME_NoError;
}
//
// Assemble command in printf(3) style, send to server, accept a response.
//
#if defined(__hpux)
#define DTMAS_COMMAND_TERMINATOR "\n"
#else
#define DTMAS_COMMAND_TERMINATOR "\r\n"
#endif
DTMailError_t
DtMailServer::do_transaction(char *fmt, ... )
{
static char *pname = "DtMailServer::do_transaction";
DTMailError_t ok;
char *buf = new char[DTMAS_POPBUFSIZE+1];
int nbytes;
va_list ap;
if (proto_is_tagged())
{
dtmasTAGGEN();
(void) sprintf(buf, "%s ", dtmasTAGGET());
}
else
{
dtmasTAGCLR();
buf[0] = '\0';
}
va_start(ap, fmt);
vsprintf(buf + strlen(buf), fmt, ap);
va_end(ap);
strcat(buf, DTMAS_COMMAND_TERMINATOR);
nbytes = SockWrite(buf, 1, strlen(buf), _sockfp);
if (nbytes != strlen(buf))
{
_logger.logError(DTM_FALSE, "Socket Error: writing '%s'", buf);
delete [] buf;
return DTME_MailServerAccess_SocketIOError;
}
if (_protologging)
{
char *cp;
if (_shroud && (cp = strstr(buf, _shroud)))
memset(cp, '*', strlen(_shroud));
buf[strlen(buf)-1] = '\0';
_logger.logError(DTM_FALSE, "%s> %s", proto_name(), buf);
}
/* we presume this does its own response echoing */
ok = ptrans_parse_response(buf);
if (ok != DTME_NoError)
{
if (NULL == _errorstring)
_errorstring = strdup(buf);
}
delete [] buf;
return ok;
}
//
// Get the specified mailrc value interpreted as an integer
//
int
DtMailServer::get_mailrc_value(
DtMail::Session *ssn,
char *pfx,
char *id,
int dflt)
{
char *string = NULL;
int value = 0;
string = get_mailrc_value(ssn, pfx, id, (char*) NULL);
if (NULL == string)
return dflt;
value = atoi(string);
return value;
}
//
// Get the specified mailrc value interpreted as an string
//
char *
DtMailServer::get_mailrc_value(
DtMail::Session *ssn,
char *pfx,
char *id,
char *dflt,
DtMailBoolean decrypt)
{
DtMailEnv error;
DtMail::MailRc *mailrc = ssn->mailRc(error);
const char *value = NULL;
static char idbuf[DTMAS_IDSIZE+1];
char *charval = NULL;
DTMAS_CONCAT_MAILRC_KEY(idbuf, pfx, id);
mailrc->getValue(error, idbuf, &value, decrypt);
if (error.isSet())
{
if (NULL != dflt)
charval = strdup(dflt);
}
else
charval = strdup(value);
if (NULL != value) free((void*) value);
return charval;
}
//
// Get the specified mailrc value interpreted as an string
//
Boolean
DtMailServer::get_mailrc_value(
DtMail::Session *ssn,
char *pfx,
char *id,
Boolean dflt)
{
DtMailEnv error;
DtMail::MailRc *mailrc = ssn->mailRc(error);
const char *value = NULL;
static char idbuf[DTMAS_IDSIZE+1];
Boolean boolval = FALSE;
DTMAS_CONCAT_MAILRC_KEY(idbuf, pfx, id);
mailrc->getValue(error, idbuf, &value);
if (error.isSet())
boolval = dflt;
else
boolval = TRUE;
if (NULL != value) free((void*) value);
return boolval;
}
//
// Returns TRUE if the folder being accessed is the inbox.
//
Boolean
DtMailServer::is_inbox()
{
if (NULL==_folder || 0==strncmp(_folder, DTMAS_INBOX, strlen(DTMAS_INBOX)))
return TRUE;
return FALSE;
}
//
// Send message to the front end for display in the status line.
//
void
DtMailServer::send_info_message(DtMailCallbackOp op)
{
const char *errmsg = (const char *) _info;
#if defined(SEPARATE_FRONT_AND_BACK_END)
DtMailEnv error;
DtMailEventPacket event;
event.key = _mailbox->getObjectKey();
event.target = DTM_TARGET_MAILBOX;
event.target_object = _mailbox;
event.operation = (void*) op;
if (NULL != errmsg)
event.argument = strdup(errmsg);
else
event.argument = NULL;
event.event_time = time(NULL);
_session->writeEventData(error, &event, sizeof(event));
#else
_mailbox->callCallback(op, strdup(errmsg));
#endif
}
//
// Retrieve messages from server using given protocol method table
//
void
DtMailServer::retrieve_messages(DtMailEnv &error)
{
DTMailError_t ok = DTME_NoError;
int js;
struct sigaction action, o_action;
int *msgsizes = (int*) NULL;
int *msgisold = (int*) NULL;
_transnum = 0;
/* set up the server-nonresponse timeout */
memset((char*) &action, 0, sizeof(struct sigaction));
memset((char*) &o_action, 0, sizeof(struct sigaction));
action.sa_handler = (SA_HANDLER_TYPE) vtalarm_handler;
sigaction(SIGNAL_TYPE, (const struct sigaction *) &action, &o_action);
if ((js = setjmp(restart)) == 1)
{
_logger.logError(
DTM_TRUE,
"Timeout after %d seconds waiting for %s.\n",
_timeout, _servername);
ok = DTME_MailServerAccess_Error;
}
else if (js == 2)
{
/* error message printed at point of longjmp */
ok = DTME_MailServerAccess_Error;
}
else
{
char buf[DTMAS_POPBUFSIZE+1];
int len, num, count, numnew;
int deletions = 0;
int sockfd = -1;
if (proto_requires_password() && NULL == _password)
{
ok = DTME_MailServerAccess_MissingPassword;
goto restoreSignal;
}
vtalarm_setitimer(_timeout);
_info.vSetError(DTME_MailServerAccessInfo_SocketOpen,
DTM_FALSE, NULL, _username, _servername);
send_info_message(DTMC_SERVERACCESSINFO);
if (NULL != _errorstring)
{
free(_errorstring);
_errorstring = NULL;
}
_sockfp = SockOpen(_servername, proto_port(), &_errorstring);
if (NULL == _sockfp)
{
if (NULL == _errorstring)
_errorstring = strdup(_logger.errnoMessage());
ok = DTME_MailServerAccess_SocketIOError;
goto restoreSignal;
}
else if (_protologging)
{
_logger.logError(DTM_FALSE, "%s> %s", proto_name(), "SockOpen");
}
/* accept greeting message from mail server */
vtalarm_setitimer(_timeout);
ok = ptrans_parse_response(buf);
if (ok != DTME_NoError) goto closeServer;
/* try to get authorized to fetch mail */
vtalarm_setitimer(_timeout);
_shroud = _password;
ok = ptrans_authorize(buf);
_shroud = (char*) NULL;
if (ok != DTME_NoError) goto closeServer;
/* compute number of messages and number of new messages waiting */
vtalarm_setitimer(_timeout);
ok = ptrans_fldstate_read(&count, &numnew);
if (ok != DTME_NoError) goto closeServer;
/* show user how many messages we downloaded */
if (_protologging)
{
if (count == 0)
_logger.logError(
DTM_FALSE,
"INFO: No mail from %s@%s",
_username, _servername);
else
{
if (numnew != -1 && (count - numnew) > 0)
_logger.logError(
DTM_FALSE,
"INFO: %d message%s (%d seen) from %s@%s.",
count, count > 1 ? "s" : "", count-numnew,
_username, _servername);
else
_logger.logError(
DTM_FALSE,
"INFO: %d message%s from %s@%s.",
count, count > 1 ? "s" : "",
_username, _servername);
}
}
if (count > 0)
{
int nmsgtofetch = 0;
int fetched = 0;
/* we may need to get sizes in order to check message limits */
if (_sizelimit)
{
msgsizes = (int *)malloc(sizeof(int) * count);
vtalarm_setitimer(_timeout);
ok = ptrans_msgsizes(count, msgsizes);
if (ok != DTME_NoError) goto closeServer;
}
if (! _retrieveold)
{
msgisold = (int*) malloc(sizeof(int) * count);
for (num = 1; num <= count; num++)
{
vtalarm_setitimer(_timeout);
msgisold[num-1] = ptrans_msgisold(num);
}
}
for (num = 1; num <= count; num++)
{
int toolarge = msgsizes && (msgsizes[num-1] > _sizelimit);
int ignoreold = msgisold && msgisold[num-1];
if (! (toolarge || ignoreold)) nmsgtofetch++;
}
if (! nmsgtofetch)
{
_info.vSetError(DTME_MailServerAccessInfo_NoMessages,
DTM_FALSE, NULL, _username, _servername);
send_info_message(DTMC_SERVERACCESSINFO);
}
/*
* In IMAP4 you can retrieve a message without marking it as
* having been seen while in POP3 and IMAP2BIS this is NOT
* possible. The proto_is_peek_capable encapsulates this
* capability.
*
* The problem is when there is any kind of transient error
* (DNS lookup failure, or sendmail refusing delivery due to
* process-table limits) during retrieval, the message will
* be marked "seen" on the server without having been retrieved
* by dtmail.
*
* We need to keep track of any errors which take place in a
* given retrieval pass (_retrieveerrors). If there were any
* errors during the previous pass, all messages which were new
* at that time will be delivered.
*/
/* read, forward, and delete messages */
_retrieveerrors = 0;
for (num = 1, fetched = 0; nmsgtofetch && num <= count; num++)
{
int toolarge = msgsizes && (msgsizes[num-1] > _sizelimit);
int ignoreold = msgisold && msgisold[num-1];
/*
* We may want to reject this message if it is
* too large or old
*/
if (toolarge || ignoreold)
{
if (_protologging)
{
_logger.logError(DTM_FALSE,"skipping message %d",num);
if (toolarge)
_logger.logError(
DTM_FALSE,
" (oversized, %d bytes)",
msgsizes[num-1]);
}
if (toolarge)
{
_info.vSetError(
DTME_MailServerAccessInfo_MessageTooLarge,
DTM_FALSE, NULL, msgsizes[num-1]);
send_info_message(DTMC_SERVERACCESSINFOERROR);
}
}
else
{
vtalarm_setitimer(_timeout);
/*
* Fetch a message from the server.
*/
fetched++;
_info.vSetError(DTME_MailServerAccessInfo_RetrievingMessage,
DTM_FALSE, NULL,
fetched, nmsgtofetch,
_username, _servername);
send_info_message(DTMC_SERVERACCESSINFO);
ok = ptrans_retrieve_start(num, &len);
if (ok != DTME_NoError)
{
_retrieveerrors++;
goto closeServer;
}
if (_protologging)
_logger.logError(
DTM_FALSE,
"INFO: reading message %d (%d bytes)",
num, len);
/* Read the message and append it to the mailbox. */
vtalarm_setitimer(_timeout);
ok = ptrans_retrieve_readandappend(error, len);
if (ok != DTME_NoError)
{
_retrieveerrors++;
goto closeServer;
}
/* Tell the server we got it OK and resynchronize. */
vtalarm_setitimer(_timeout);
ok = ptrans_retrieve_end(num);
if (ok != DTME_NoError)
{
_retrieveerrors++;
goto closeServer;
}
/* Mark the message seen and remove it from the server. */
if (_removeafterdelivery)
{
deletions++;
if (_protologging)
_logger.logError(DTM_FALSE, " deleted\n");
vtalarm_setitimer(_timeout);
ok = ptrans_delete(num);
if (ok != DTME_NoError) goto closeServer;
}
else if (_protologging)
_logger.logError(DTM_FALSE, " not deleted\n");
}
}
/* Remove all messages flagged for deletion. */
if (deletions > 0)
{
vtalarm_setitimer(_timeout);
ok = ptrans_fldstate_expunge();
if (ok != DTME_NoError) goto closeServer;
}
}
else
{
_info.vSetError(DTME_MailServerAccessInfo_NoMessages,
DTM_FALSE, NULL, _username, _servername);
send_info_message(DTMC_SERVERACCESSINFO);
}
closeServer:
vtalarm_setitimer(_timeout);
if (ok != DTME_MailServerAccess_SocketIOError)
if (ok == DTME_NoError)
ok = ptrans_quit();
else
(void) ptrans_quit();
vtalarm_setitimer(0);
SockClose(_sockfp);
_sockfp = NULL;
dtmasTAGCLR();
}
restoreSignal:
_sockfp = NULL;
if (ok != DTME_NoError)
{
if (NULL == _errorstring)
_errorstring = strdup("");
error.vSetError(
ok, DTM_TRUE, NULL,
_username, _servername, proto_name(), _errorstring);
_logger.logError(
DTM_TRUE,
"Error while fetching from '%s': \n%s\n",
_servername, (const char*) error);
}
else
error.clear();
if (_errorstring)
{
free(_errorstring);
_errorstring = NULL;
}
if (msgsizes != NULL) free(msgsizes);
if (msgisold != NULL) free(msgisold);
sigaction(SIGNAL_TYPE, (const struct sigaction *) &o_action, NULL);
}
//
// Reset the nonresponse-timeout
//
#if defined(__hpux)
#define TV_USEC_TYPE long
#else
#define TV_USEC_TYPE int
#endif
void
DtMailServer::vtalarm_setitimer(int timeout_seconds)
{
struct itimerval ntimeout;
ntimeout.it_interval.tv_sec = (time_t) 0;
ntimeout.it_interval.tv_usec = (TV_USEC_TYPE) 0;
ntimeout.it_value.tv_sec = (time_t) timeout_seconds;
ntimeout.it_value.tv_usec = (TV_USEC_TYPE) 0;
setitimer(ITIMER_TYPE, &ntimeout, (struct itimerval*) NULL);
}
//
// Handle server-timeout ALARM signal
//
void
DtMailServer::vtalarm_handler(int)
{
longjmp(restart, 1);
}

View File

@@ -0,0 +1,49 @@
/*
*+SNOTICE
*
*
* $XConsortium: DtMailTransport.C /main/4 1996/04/21 19:47:48 drk $
*
* 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
*/
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
DtMail::Transport::Transport(DtMailEnv &,
Session * session,
DtMailStatusCallback cb,
void * client_data)
{
_key = session->newObjectKey();
_session = session;
_callback = cb;
_cb_data = client_data;
_obj_mutex = MutexInit();
}
DtMail::Transport::~Transport(void)
{
MutexDestroy(_obj_mutex);
_session->removeObjectKey(_key);
}
void
DtMail::Transport::callCallback(DtMailOperationId id, void * arg)
{
DtMailEnv * error = (DtMailEnv *)arg;
_callback(id, *error, _cb_data);
}

View File

@@ -0,0 +1,230 @@
/*
*+SNOTICE
*
*
* $TOG: DtMailValuesBuiltin.C /main/6 1999/01/29 14:44:21 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
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <DtMail/DtMailValues.hh>
#include <DtMail/IO.hh>
#include <DtMail/DtMailError.hh>
DtMailValueSeq::DtMailValueSeq(int size) : DtVirtArray<DtMailValue *>(size)
{
}
DtMailValueSeq::~DtMailValueSeq(void)
{
for (int ent = 0; ent < this->length(); ent++) {
delete (*this)[ent];
}
}
void
DtMailValueSeq::clear(void)
{
while(this->length()) {
delete (*this)[0];
this->remove(0);
}
}
DtMailValue::DtMailValue(const char * str)
{
_value = NULL;
if (str) {
_value = strdup(str);
}
}
DtMailValue::~DtMailValue(void)
{
if (_value) {
free(_value);
}
}
DtMailValue::operator const char *(void)
{
return(_value);
}
const char *
DtMailValue::operator= (const char * str)
{
if (_value) {
free(_value);
}
_value = strdup(str);
return(_value);
}
DtMailValueDate
DtMailValue::toDate(void)
{
DtMailValueDate date;
memset(&date, 0, sizeof(DtMailValueDate));
return(date);
}
#ifdef DEAD_WOOD
void
DtMailValue::fromDate(const DtMailValueDate & date)
{
if (_value) {
free(_value);
}
_value = (char *)malloc(64);
tm result;
SafeLocaltime(&date.dtm_date, result);
/* NL_COMMENT
* The %C is the time and date format, please refer to strftime man page for
* explanation of each format.
*/
SafeStrftime(_value, 64, DtMailError::getMessageText(2, 1, "%C"), &result);
}
#endif /* DEAD_WOOD */
DtMailAddressSeq *
DtMailValue::toAddress(void)
{
return(NULL);
}
#ifdef DEAD_WOOD
void
DtMailValue::fromAddress(const DtMailAddressSeq &)
{
}
#endif /* DEAD_WOOD */
const char *
DtMailValue::raw(void)
{
return(_value);
}
DtMailValueAddress::DtMailValueAddress(void)
{
dtm_address = NULL;
dtm_person = NULL;
dtm_namespace = NULL;
}
DtMailValueAddress::DtMailValueAddress(const DtMailValueAddress & other)
{
dtm_address = NULL;
dtm_person = NULL;
dtm_namespace = NULL;
if (other.dtm_address) {
dtm_address = strdup(other.dtm_address);
}
if (other.dtm_person) {
dtm_person = strdup(other.dtm_person);
}
if (other.dtm_namespace) {
dtm_namespace = strdup(other.dtm_namespace);
}
}
DtMailValueAddress::DtMailValueAddress(const char * address,
const char * person,
const char * nameSpace)
{
dtm_address = NULL;
dtm_person = NULL;
dtm_namespace = NULL;
if (address) {
dtm_address = strdup(address);
}
if (person) {
dtm_person = strdup(person);
}
if (nameSpace) {
dtm_namespace = strdup(nameSpace);
}
}
DtMailValueAddress::DtMailValueAddress(const char * address, const int addr_len,
const char * person, const int per_len,
const char * nameSpace)
{
dtm_address = NULL;
dtm_person = NULL;
dtm_namespace = NULL;
if (address) {
dtm_address = (char *)malloc(addr_len + 1);
memcpy(dtm_address, address, addr_len);
dtm_address[addr_len] = 0;
}
if (person) {
dtm_person = (char *)malloc(per_len + 1);
memcpy(dtm_person, person, per_len);
dtm_person[per_len] = 0;
}
if (nameSpace) {
dtm_namespace = strdup(nameSpace);
}
}
DtMailValueAddress::~DtMailValueAddress(void)
{
if (dtm_address) {
free(dtm_address);
}
if (dtm_person) {
free(dtm_person);
}
if (dtm_namespace) {
free(dtm_namespace);
}
}
DtMailAddressSeq::DtMailAddressSeq(int size) : DtVirtArray<DtMailValueAddress *>(size)
{
}
DtMailAddressSeq::~DtMailAddressSeq(void)
{
while(this->length()) {
delete (*this)[0];
this->remove(0);
}
}

View File

@@ -0,0 +1,82 @@
/*
*+SNOTICE
*
*
* $XConsortium: DtMailXtProc.C /main/4 1996/04/21 19:47:56 drk $
*
* 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
*/
#include <stdio.h>
#include <unistd.h>
#include <DtMail/DtMail.hh>
#include <DtMail/DtMailXtProc.h>
extern "C" void
DtMailXtInputProc(XtPointer client_data,
int * file_desc,
XtInputId *)
{
DtMail::Session *session = (DtMail::Session *)client_data;
// We read one event packet. The call back caller is then
// invoked to fire the appropriate callback.
//
DtMailEventPacket packet;
read(*file_desc, &packet, sizeof(DtMailEventPacket));
if (session->validObjectKey(packet.key) == DTM_FALSE) {
return;
}
switch(packet.target) {
case DTM_TARGET_MAILBOX:
{
DtMail::MailBox * self = (DtMail::MailBox *)packet.target_object;
self->callCallback((DtMailCallbackOp)((long)packet.operation),
packet.argument);
break;
}
case DTM_TARGET_TRANSPORT:
{
DtMail::Transport * self = (DtMail::Transport *)packet.target_object;
self->callCallback((DtMailOperationId)packet.operation,
packet.argument);
break;
}
default:
break;
}
return;
}
void
DtMailProcessClientEvents(void)
{
#if 0
// if (DtMailDamageContext) {
// XtInputMask events = XtAppPending(DtMailDamageContext);
// if (events & (XtIMXEvent | XtIMAlternateInput)) {
// XtAppProcessEvent(DtMailDamageContext, XtIMXEvent | XtIMAlternateInput);
// }
// }
#endif
}

View File

@@ -0,0 +1,147 @@
/*
*+SNOTICE
*
* $TOG: DtVirtArray.C /main/5 1997/12/22 16:32:52 bill $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <DtMail/DtVirtArray.hh>
#include <DtMail/Threads.hh>
#include <DtMail/IO.hh>
DtVirtArrayImpl::DtVirtArrayImpl(const int size)
{
_size = size;
_count = 0;
_elements = (void **)malloc(sizeof(void *) * _size);
_mutex = MutexInit();
}
DtVirtArrayImpl::~DtVirtArrayImpl(void)
{
if (_elements) {
MutexLock lock_scope(_mutex);
free(_elements);
_elements = NULL;
_size = 0;
_count = 0;
lock_scope.unlock_and_destroy();
}
}
int
DtVirtArrayImpl::length(void)
{
MutexLock lock_scope(_mutex);
return(_count);
}
void *
DtVirtArrayImpl::operator[](const int at)
{
MutexLock lock_scope(_mutex);
if (at < 0 || at >= _count) {
return(NULL);
}
return(_elements[at]);
}
int
DtVirtArrayImpl::indexof(void * handle)
{
MutexLock lock_scope(_mutex);
for (int i = 0; i < _count; i++) {
if (_elements[i] == handle) {
return(i);
}
}
return(-1);
}
int
DtVirtArrayImpl::append(void * handle)
{
MutexLock lock_scope(_mutex);
grow();
int new_pos = _count;
_elements[_count] = handle;
_count += 1;
return(new_pos);
}
void
DtVirtArrayImpl::insert(void * handle, const int at)
{
MutexLock lock_scope(_mutex);
make_slot(at);
_elements[at] = handle;
}
void
DtVirtArrayImpl::remove(const int at)
{
MutexLock lock_scope(_mutex);
for (int pos = at; pos < (_count - 1); pos++) {
_elements[pos] = _elements[pos + 1];
}
_count -= 1;
}
void
DtVirtArrayImpl::remove(void * handle)
{
MutexLock lock_scope(_mutex);
int pos = indexof(handle);
remove(pos);
}
void
DtVirtArrayImpl::make_slot(const int at)
{
grow();
_count += 1;
for (int pos = (_count - 1); pos > at; pos--) {
_elements[pos] = _elements[pos - 1];
}
_elements[at] = NULL;
}
void
DtVirtArrayImpl::grow(void)
{
if (_count == _size) {
// Grow by 50%, but grow by at least 1!
//
int new_size = _size + (_size >> 2) + 1;
_elements = (void **)realloc(_elements, new_size * sizeof(void *));
_size = new_size;
}
}

View File

@@ -0,0 +1,65 @@
/*
*+SNOTICE
*
*
* $XConsortium: DynamicLib.C /main/4 1996/04/21 19:48:04 drk $
*
* 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
*/
#include "DynamicLib.hh"
#include "DlDynamicLib.hh"
#include "NotDynamic.hh"
// The purpose of this function is to map the virtual DynamicLib object
// into a platform specific implementation at compile time. This is
// a fairly ugly process that requires lots of ifdef's based on the
// particular implementation of shared libraries.
//
// Adding a new dynamic library implementation for a platform involves
// two steps:
//
// 1) Create a new implementation of the DynamicLib object (see
// DlDynamicLib.C for an example).
//
// 2) Adding the appropriate ifdef construction step to this function.
//
DynamicLib *
CreatePlatformDl(const char * path)
{
#if defined(DL_DYNAMIC_LIBS)
DynamicLib * dl = new DlDynamicLib(path);
#endif
#if defined(DL_NOT_DYNAMIC)
DynamicLib * dl = new NotDynamic(path);
#endif
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING
// *******************************************************
// If you get a compile error because "dl" is not defined,
// then you have not specified your platforms dynamic library
// implementation. You MUST do this for this code to work!
// *******************************************************
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING
return(dl);
}
#ifndef CAN_INLINE_VIRTUALS
DynamicLib::~DynamicLib( void )
{
}
#endif /* ! CAN_INLINE_VIRTUALS */

View File

@@ -0,0 +1,38 @@
/*
*+SNOTICE
*
*
* $XConsortium: DynamicLib.hh /main/4 1996/04/21 19:48:08 drk $
*
* 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 _DYNAMICLIB_HH
#define _DYNAMICLIB_HH
#include <DtMail/DtLanguages.hh>
class DynamicLib : public DtCPlusPlusAllocator {
public:
virtual ~DynamicLib(void);
virtual void * getSym(const char * symbol) = 0;
protected:
DynamicLib(const char *) { }
};
DynamicLib * CreatePlatformDl(const char * lib);
#endif

View File

@@ -0,0 +1,553 @@
/*
*+SNOTICE
*
*
* $TOG: FileShare.C /main/6 1999/03/26 16:52:00 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <DtMail/FileShare.hh>
#include <DtMail/DtMailXtProc.h>
XtAppContext DtMailDamageContext = NULL;
static const int FileShareTimeout = 900000;
static int tlock_flag = 1;
static Tt_message msg_create(char *op, char *file, Tt_class tt_class, Tt_message_callback f)
{
Tt_message msg = tt_message_create();
// Create the tooltalk message
if (tt_ptr_error(msg) != TT_OK) {
return ((Tt_message) NULL);
}
/* Set the message class type */
if (tt_message_class_set (msg, tt_class) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
/* Set the message address */
if (tt_message_address_set (msg, TT_PROCEDURE) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
/* Set the disposition of the message */
if (tt_message_disposition_set (msg, TT_DISCARD) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
/* Set the message operation. */
if (tt_message_op_set (msg, op) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
/* Set the message scope */
if (tt_message_scope_set (msg, TT_FILE) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
if (tt_message_file_set (msg, file) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
if (tt_message_arg_add(msg, TT_IN, "DtMail", "lock") != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
if (f) {
if (tt_message_callback_add(msg, f) != TT_OK) {
tt_message_destroy(msg);
return ((Tt_message) NULL);
}
}
return (msg);
}
Tt_callback_action
FileShare::mt_lock_cb(Tt_message m, Tt_pattern p)
{
Tt_state state = tt_message_state(m);
char *op;
char *flag = NULL;
op = tt_message_op(m);
if (!op) {
return TT_CALLBACK_CONTINUE;
}
flag = tt_message_arg_val(m, 0);
if (!strcmp(op, "tlock")) {
// handle tlock request
if (state == TT_HANDLED) {
tlock_flag = -1;
tt_message_destroy(m);
} else if (state == TT_FAILED) {
tlock_flag = 0;
tt_message_destroy(m);
} else if (state == TT_SENT) {
if (tt_ptr_error(flag) == TT_OK) {
// this message is from another dtmail, ignore it
return TT_CALLBACK_CONTINUE;
}
tt_message_reply(m);
}
} else if (!strcmp(op, "rulock")) {
// handle rulock notice
if (state == TT_SENT) {
DtMailBoolean answer = DTM_FALSE; // default is to not give up the lock
FileShare *f = (FileShare *)tt_pattern_user(p, 1);
if (f->_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 5,
"Another user would like your lock.");
answer = f->_cb_func(DTMC_UNLOCK, f->_path, msg, f->_cb_data);
}
tt_message_destroy(m);
}
}
tt_free(op);
return TT_CALLBACK_PROCESSED;
}
FileShare::FileShare(DtMailEnv & error,
DtMail::Session * session,
const char * path,
DtMailCallback cb,
void * clientData)
{
DtMail::MailRc *mailrc = session->mailRc(error);
_key = session->newObjectKey();
_session = session;
_path = strdup(path);
_cb_func = cb;
_cb_data = clientData;
// For now, assume we can't write to the file.
//
_have_write_access = DTM_FALSE;
_other_modified = DTM_TRUE;
_mt_pattern = NULL;
error.clear();
// Register the file pattern.
//
_tt_handle = new TTHandle;
_tt_handle->session = _session;
_tt_handle->key = _key;
_tt_handle->self = this;
_file_pats = ttdt_file_join(_path, TT_FILE, 0, fileCB, _tt_handle);
if (tt_pointer_error(_file_pats) != TT_OK) {
error.setError(DTME_TTFailure);
_file_pats = NULL;
return;
}
// isModified(error);
}
FileShare::~FileShare(void)
{
if (_have_write_access == DTM_TRUE && _file_pats) {
_pending = PENDING_DESTROY;
// ttdt_file_event(NULL, TTDT_SAVED, _file_pats, 1);
_session->removeObjectKey(_key);
}
if (NULL != _tt_handle)
delete _tt_handle;
if (_file_pats) {
ttdt_file_quit(_file_pats, 1);
}
if (_mt_pattern) {
tt_pattern_destroy(_mt_pattern);
_mt_pattern = NULL;
}
if (_path) {
free(_path);
}
_have_write_access = DTM_FALSE;
_file_pats = NULL;
}
DtMailBoolean
FileShare::isModified(DtMailEnv & error)
{
error.clear();
if (!_path) {
return(DTM_FALSE);
}
DtMailBoolean answer = DTM_FALSE;
Tt_message mt_msg;
mt_msg = msg_create("tlock", _path, TT_REQUEST, mt_lock_cb);
if (mt_msg == NULL) {
error.setError(DTME_TTFailure);
return DTM_TRUE;
}
if (tt_message_send(mt_msg) != TT_OK) {
error.setError(DTME_TTFailure);
return DTM_TRUE;
}
tttk_block_while((XtAppContext)0, &tlock_flag, FileShareTimeout);
// mt_lock_cb sets tlock_flag to -1 if mbox is locked
if (tlock_flag == -1) {
tlock_flag = 1; // reset the tlock_flag
_other_modified = DTM_TRUE;
_mt_lock = DTM_TRUE;
return DTM_TRUE;
} else {
// else tlock_flag == 0, means no lock on this mbox
// or tlock_flag == 1, means time out
tlock_flag = 1; // reset the tlock_flag
_mt_lock = DTM_FALSE;
// now let's try the dtmail protocol
if (ttdt_Get_Modified(NULL, _path, TT_FILE, NULL, FileShareTimeout)) {
answer = DTM_TRUE;
_other_modified = DTM_TRUE;
} else {
answer = DTM_FALSE;
_other_modified = DTM_FALSE;
}
return(answer);
}
}
void
FileShare::lockFile(DtMailEnv & error)
{
int always;
error.clear();
// If we have the access, then we locked it before. Simply return.
//
if (_have_write_access == DTM_TRUE) {
return;
}
// First step in locking is determining if anyone else has the lock.
// If they do, then we need to ask them to save their changes and
// exit.
//
if (isModified(error) == DTM_TRUE) {
DtMailBoolean take_lock = DTM_FALSE; // default is to not request access
// calls syncViewAndStoreCallback which then calls syncViewAndStore
if (_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 6,
"Another session has this mailbox locked. Request access?");
take_lock = _cb_func(DTMC_QUERYLOCK, _path, msg, _cb_data);
}
if (take_lock == DTM_FALSE) {
error.setError(DTME_OtherOwnsWrite);
return;
}
// isModified sets _mt_lock to DTM_TRUE is the mailbox is locked
// by mailtool
if (_mt_lock == DTM_TRUE) {
// mailtool style locking
Tt_message mt_msg;
mt_msg = msg_create("rulock", _path, TT_NOTICE, NULL);
if (mt_msg == NULL) {
error.setError(DTME_TTFailure);
return;
}
if (tt_message_send(mt_msg) != TT_OK) {
error.setError(DTME_TTFailure);
return;
}
tt_message_destroy(mt_msg);
} else {
// ttdt style locking
ttdt_Save(NULL, _path, TT_FILE, DtMailDamageContext, FileShareTimeout);
}
// Give the other mailer FileShareTimeout seconds to give up the lock
time_t t_start;
time(&t_start);
while (1) {
sleep(5);
if (isModified(error) == DTM_FALSE) {
break;
} else {
if (time((time_t)NULL) - t_start > FileShareTimeout) {
// time out!
error.setError(DTME_OtherOwnsWrite);
return;
}
}
}
}
// Set this so we don't call our client during this handshake.
//
_pending = PENDING_LOCK;
_outstanding = DTM_TRUE;
// Now we are ready to lock the mailbox
// register this pattern so we can handle messages from mailtool
_mt_pattern = tt_pattern_create();
tt_pattern_category_set(_mt_pattern, TT_HANDLE);
tt_pattern_scope_add(_mt_pattern, TT_FILE);
tt_pattern_file_add(_mt_pattern, _path);
tt_pattern_op_add(_mt_pattern, "tlock");
tt_pattern_op_add(_mt_pattern, "rulock");
tt_pattern_callback_add(_mt_pattern, mt_lock_cb);
tt_pattern_user_set(_mt_pattern, 1, (void *)this);
if (tt_pattern_register(_mt_pattern) != TT_OK) {
error.setError(DTME_TTFailure);
return;
}
// Send the message saying we want to be the owner.
ttdt_file_event(NULL, TTDT_MODIFIED, _file_pats, 1);
// We need to process any messages that have arrived. We will get our own
// modified message, which is not terribly interesting. What is interesting
// is a modified message from someone else. That means that we have a race
// condition where two processes both asked if the file was being modified,
// and it wasn't. Then both said they were the owner, which is obviously
// wrong so we need to blow both off and make them try again. Hopefully
// there is enough randomness in our clients that the race condition will
// clear itself up and we won't get here very often.
//
always = 1;
while(_outstanding == DTM_TRUE) {
tttk_block_while((XtAppContext)0, &always, 0);
}
if (_other_modified == DTM_TRUE) {
// Well, we have a race. Fail this lock as will the other process,
// we hope.
error.setError(DTME_OtherOwnsWrite);
return;
}
// Okay, we now have the lock.
_have_write_access = DTM_TRUE;
}
DtMailBoolean
FileShare::readOnly(DtMailEnv & error)
{
DtMailBoolean answer = DTM_TRUE; // default is to accept read-only access
if (_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 7,
"Unable to obtain lock, open this mailbox as read only?");
answer = _cb_func(DTMC_READONLY, _path, msg, _cb_data);
}
if (answer)
error.clear();
return(answer);
}
DtMailBoolean
FileShare::readWriteOverride(DtMailEnv & error)
{
DtMailBoolean answer = DTM_FALSE; // default is to open for read-only access
if (_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 8,
"Unable to obtain lock because system not responding, open this mailbox as read only, read write, or cancel?");
answer = _cb_func(DTMC_READWRITEOVERRIDE, _path, msg, _cb_data);
}
if (answer == ((DtMailBoolean)((DTM_FALSE+DTM_TRUE)*2))) {
error.setError(DTME_UserInterrupted);
answer = DTM_FALSE;
}
else {
error.clear();
}
return(answer);
}
#ifdef DEAD_WOOD
DtMailBoolean
FileShare::locked(void)
{
return(_have_write_access);
}
#endif /* DEAD_WOOD */
Tt_message
FileShare::fileCB(Tt_message msg,
Tttk_op op,
char * path,
void *clientData,
int,
int same_proc)
{
TTHandle *tt_handle = (TTHandle *)clientData;
DtMailBoolean answer;
if (tt_handle->session->validObjectKey(tt_handle->key) == DTM_FALSE) {
// This object has been destroyed. We got here most likely because
// ToolTalk is responding to one of our clean up messages. In any
// case, fail the message and return.
//
tttk_message_fail(msg, TT_DESKTOP_ECANCELED, "Object destroyed", 1);
return(0);
}
FileShare * self = tt_handle->self;
switch(op) {
case TTDT_MODIFIED:
if (self->_outstanding == DTM_FALSE && !same_proc) {
if (self->_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 9,
"Another user has taken your lock.");
self->_cb_func(DTMC_LOSTLOCK, path, msg, self->_cb_data);
}
self->_other_modified = DTM_TRUE;
self->_have_write_access = DTM_FALSE;
break;
}
if (self->_outstanding == DTM_TRUE && self->_pending == PENDING_LOCK) {
// This could be one of 2 conditions. If the message is
// from us, then we have the lock, and we are done.
// If not, then someone else is asking for the lock. We
// reflect this by giving them the lock.
//
if (same_proc) {
self->_other_modified = DTM_FALSE;
self->_have_write_access = DTM_TRUE;
self->_outstanding = DTM_FALSE;
}
else {
self->_other_modified = DTM_TRUE;
self->_have_write_access = DTM_FALSE;
// We haven't seen our own request yet. Leave outstanding
// so we can process it before leaving.
}
}
break;
case TTDT_GET_MODIFIED:
tt_message_arg_ival_set(msg, 1, 1);
tt_message_reply(msg);
break;
case TTDT_SAVED:
case TTDT_REVERTED:
// The other process has saved their changes (or tossed them).
// At this point we should be able to start modifying the file.
//
self->_other_modified = DTM_FALSE;
if (self->_outstanding == DTM_TRUE && self->_pending == PENDING_SAVE) {
self->_outstanding = DTM_FALSE;
}
break;
case TTDT_REVERT:
case TTDT_SAVE:
// Someone is asking us to save our changes and close the file.
//
answer = DTM_FALSE; // default is to not give up the lock
if (self->_cb_func)
{
char *msg =
DtMailEnv::getMessageText(
FileShareMsgSet, 5,
"Another user would like your lock.");
answer = self->_cb_func(DTMC_UNLOCK, path, msg, self->_cb_data);
}
if (answer == DTM_TRUE) {
tt_message_reply(msg);
} else {
tttk_message_fail(msg, TT_DESKTOP_EACCES, 0, 0);
}
break;
default:
// Other messages, we simply smile and say thank you.:-)
//
tt_message_reply(msg);
break;
}
tt_message_destroy(msg);
return(0);
}

View File

@@ -0,0 +1,188 @@
/*
*+SNOTICE
*
*
* $XConsortium: HashTable.C /main/3 1995/11/06 16:37:14 rswiston $
*
* 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 <string.h>
#include <DtMail/HashTable.hh>
HashTableImpl::HashTableImpl(int table_size)
{
_table_size = table_size;
_hash_table = new HashEntry[table_size];
memset(_hash_table, 0, table_size * sizeof(HashEntry));
}
HashTableImpl::~HashTableImpl(void)
{
// Scan the entire hash table, deleting all keys and chains, and
// eventually delete the hash table itself
//
for (int slot = 0; slot < _table_size; slot++) {
if (_hash_table[slot].key != NULL) {
HashEntry * chain;
HashEntry * chainHead;
for (chainHead = chain = &_hash_table[slot]; chain; chain = chain->next) {
if (chain->key)
delete chain->key;
if (chain != chainHead)
delete chain;
}
}
}
delete _hash_table;
}
void *
HashTableImpl::lookup(ObjectKey & key)
{
short hash_key = key.hashValue();
int slot = hash_key % _table_size;
// Search the slot looking for the value. Return NULL if there
// are no objects matching this key.
//
for (HashEntry * chain = &_hash_table[slot]; chain; chain = chain->next) {
if (chain->key && key == *(chain->key)) {
break;
}
}
if (chain) {
return(chain->value);
}
return(NULL);
}
void
HashTableImpl::set(ObjectKey & key, void * value)
{
short hash_key = key.hashValue();
int slot = hash_key % _table_size;
// See if we have already filled the slot.
//
if (_hash_table[slot].key == NULL) {
// Simple, put it in the slot.
//
_hash_table[slot].key = &key;
_hash_table[slot].value = value;
return;
}
// We either have a collision or a duplicate. In the case of duplicates
// we simply replace the value.
//
for (HashEntry * chain = &_hash_table[slot]; chain->next; chain = chain->next) {
// If this item is already stored then update the value.
//
if (key == *(chain->key)) {
chain->value = value;
return;
}
}
HashEntry * new_ent = new HashEntry;
new_ent->key = &key;
new_ent->value = value;
new_ent->next = NULL;
chain->next = new_ent;
}
void *
HashTableImpl::remove(ObjectKey & key)
{
short hash_val = key.hashValue();
int slot = hash_val % _table_size;
void * removed_val = NULL;
// See if we even have this object.
//
if (!_hash_table[slot].key) {
// Obviously not.
//
return(removed_val);
}
// Try to find it in the chain.
//
HashEntry * last = NULL;
for (HashEntry * chain = &_hash_table[slot]; chain; chain = chain->next) {
if (key == *(chain->key)) {
break;
}
last = chain;
}
if (!chain) { // Not found
return(removed_val);
}
if (last) {
last->next = chain->next;
delete chain->key;
removed_val = chain->value;
delete chain;
}
else {
// This is the first entry. In this case we copy the next entry
// into this memory and through away the next item. If we have
// no next, then simply zero the slot.
//
removed_val = chain->value;
delete chain->key;
if (chain->next) {
*chain = *(chain->next);
delete chain->next;
}
else {
memset(chain, 0, sizeof(HashEntry));
}
}
return(removed_val);
}
#if !defined(HPUX) && !defined(__uxp__)
void
HashTableImpl::forEach(HashImplIterator iterator, void * client_data)
{
// Scan the entire hash table, passing valid entries to the
// iterator.
//
for (int slot = 0; slot < _table_size; slot++) {
if (_hash_table[slot].key == NULL) {
continue;
}
for (HashEntry * chain = &_hash_table[slot]; chain; chain = chain->next) {
int cont = 0;
cont = iterator(*chain->key, chain->value, client_data);
if (!cont) {
return;
}
}
}
}
#endif

View File

@@ -0,0 +1,333 @@
/*
*+SNOTICE
*
* $TOG: IMAPServer.C /main/7 1998/11/10 17:08:32 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
/*
* Common Desktop Environment
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
* (c) Copyright 1995 Digital Equipment Corp.
* (c) Copyright 1995 Fujitsu Limited
* (c) Copyright 1995 Hitachi, Ltd.
*
*
* RESTRICTED RIGHTS LEGEND
*
*Use, duplication, or disclosure by the U.S. Government is subject to
*restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
*Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
*for non-DOD U.S. Government Departments and Agencies are as set forth in
*FAR 52.227-19(c)(1,2).
*Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
*International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
*Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
*Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
*Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
*Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
*Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <DtMail/DtMailServer.hh>
#include <DtMail/IO.hh>
#define dtmasTAGGET() (_transtag)
IMAPServer::IMAPServer(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
: DtMailServer(folder, session, mailbox,
append_mailbox_cb, append_mailbox_cb_data)
{
_append_mailbox_cb = append_mailbox_cb;
_append_mailbox_cb_data = append_mailbox_cb_data;
_count = 0;
_imap4 = 0;
_recent = 0;
_seen = 0;
_unseen = 0;
}
IMAPServer::~IMAPServer()
{
}
//
// Set delete flag for given message.
//
DTMailError_t
IMAPServer::ptrans_delete(int msg)
{
// Use SILENT if possible as a minor throughput optimization.
if (_imap4)
return do_transaction("STORE %d +FLAGS.SILENT (\\Deleted)", msg);
else
return do_transaction("STORE %d +FLAGS (\\Deleted)", msg);
}
//
// Apply for connection authorization
//
DTMailError_t
IMAPServer::ptrans_authorize(char*)
{
/* try to get authorized */
DTMailError_t ok;
ok = do_transaction("LOGIN %s \"%s\"", _username, _password);
if (DTME_NoError != ok) return DTME_MailServerAccess_AuthorizationFailed;
// probe to see if we're running IMAP4 and can use RFC822.PEEK
_imap4 = ((do_transaction("CAPABILITY")) == 0);
return DTME_NoError;
}
//
// Get range of messages to be fetched
//
DTMailError_t
IMAPServer::ptrans_fldstate_read(int *countp, int *newp)
{
DTMailError_t ok;
/* find out how many messages are waiting */
_recent = _unseen = 0;
ok = do_transaction("SELECT %s", _folder);
if (DTME_NoError != ok) return ok;
*countp = _count;
if (_unseen) // Optional response, but better if we see it.
*newp = _unseen;
else if (_recent)
*newp = _recent; // Mandatory
else
*newp = -1; // Should never happen, RECENT is mandatory.
return DTME_NoError;
}
//
// Capture the sizes of all messages.
//
DTMailError_t
IMAPServer::ptrans_msgsizes(int count, int *sizes)
{
char buf[DTMAS_POPBUFSIZE+1];
DTMailError_t ok = DTME_NoError;
ok = do_send("FETCH 1:%d RFC822.SIZE", count);
if (DTME_NoError != ok) return ok;
while (SockGets(buf, sizeof(buf), _sockfp))
{
int num, size;
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
if (strstr(buf, "OK"))
break;
else if (sscanf(buf, "* %d FETCH (RFC822.SIZE %d)", &num, &size) == 2)
sizes[num - 1] = size;
else
sizes[num - 1] = -1;
}
return DTME_NoError;
}
//
// Is the given message old?
//
int
IMAPServer::ptrans_msgisold(int num)
{
DTMailError_t ok;
ok = do_transaction("FETCH %d FLAGS", num);
if (DTME_NoError != ok) return 0;
return _seen;
}
//
// request nth message
//
DTMailError_t
IMAPServer::ptrans_retrieve_start(int msg, int *lenp)
{
char buf[DTMAS_POPBUFSIZE+1];
DTMailError_t ok = DTME_NoError;
int num;
//
// If we're using IMAP4, we can fetch the message without setting its
// seen flag. This is good! It means that if the protocol exchange
// craps out during the message, it will still be marked `unseen' on
// the server.
//
// However...*don't* do this if we're using keep to suppress deletion!
// In that case, marking the seen flag is the only way to prevent the
// message from being re-fetched on subsequent runs.
//
if (_imap4 && _removeafterdelivery)
ok = do_send("FETCH %d RFC822.PEEK", msg);
else
ok = do_send("FETCH %d RFC822", msg);
if (DTME_NoError != ok) return ok;
// looking for FETCH response
do
{
if (! SockGets(buf, sizeof(buf), _sockfp))
{
_logger.logError(DTM_FALSE, "Socket Error fetching message");
return DTME_MailServerAccess_SocketIOError;
}
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
} while (sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
if (num != msg)
{
_logger.logError(DTM_FALSE, "Protocol Error fetching message");
return DTME_MailServerAccess_Error;
}
else
{
return DTME_NoError;
}
}
//
// Parse command response
//
DTMailError_t
IMAPServer::ptrans_parse_response(char *argbuf)
{
char buf[DTMAS_POPBUFSIZE+1];
_seen = 0;
do
{
if (! SockGets(buf, sizeof(buf), _sockfp))
{
_logger.logError(DTM_FALSE, "Socket Error reading response");
return DTME_MailServerAccess_SocketIOError;
}
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
/* interpret untagged status responses */
if (strstr(buf, "EXISTS"))
_count = atoi(buf+2);
if (strstr(buf, "RECENT"))
_recent = atoi(buf+2);
if (strstr(buf, "UNSEEN"))
_unseen = atoi(buf+2);
if (strstr(buf, "FLAGS"))
_seen = (strstr(buf, "Seen") != (char *)NULL);
} while (strlen(dtmasTAGGET()) &&
strncmp(buf, dtmasTAGGET(), strlen(dtmasTAGGET())));
if (! strlen(dtmasTAGGET()))
{
strcpy(argbuf, buf);
return DTME_NoError;
}
else
{
char *cp;
/* skip the tag */
for (cp = buf; !isspace(*cp); cp++)
continue;
while (isspace(*cp))
cp++;
if (strncmp(cp, "OK", 2) == 0)
{
strcpy(argbuf, cp);
return DTME_NoError;
}
else if (strncmp(cp, "BAD", 2) == 0)
{
_logger.logError(DTM_FALSE, "Protocol Error reading response");
return DTME_MailServerAccess_Error;
}
else
{
_logger.logError(DTM_FALSE, "Protocol Violation reading response");
return DTME_MailServerAccess_ProtocolViolation;
}
}
}
//
// Retrieve messages using IMAP Version 2bis or Version 4.
//
void
IMAPServer::retrieve_messages(DtMailEnv &error)
{
DtMailServer::retrieve_messages(error);
}
//
// Discard tail of FETCH response after reading message text.
//
DTMailError_t
IMAPServer::ptrans_retrieve_end(int)
{
char buf [DTMAS_POPBUFSIZE+1];
if (! SockGets(buf, sizeof(buf), _sockfp))
{
_logger.logError(DTM_FALSE, "Socket Error reading trail");
return DTME_MailServerAccess_SocketIOError;
}
return DTME_NoError;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
XCOMM $TOG: Imakefile /main/10 1998/11/09 18:30:37 mgreess $
#define DoNormalLib YES
#define DoSharedLib NO
#define DoDebugLib NO
#define DoProfileLib NO
#define LibName DtMail
#define LibHeaders NO
#define LibCreate NO
#define CplusplusSource YES
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
#include <Threads.tmpl>
INCLUDES = -I. -I../../include -I../../include/utils -I$(CDELIBSRC)
#if HasVFork
VFORK_DEFINES = -DHAS_VFORK
#else
VFORK_DEFINES =
#endif
#if defined(DtMailDynamicLinking) && DtMailDynamicLinking
DYNLIB_SRCS = DlDynamicLib.C
DYNLIB_OBJS = DlDynamicLib.o
DYNLIB_DEFINES = -DDL_DYNAMIC_LIBS
#else
DYNLIB_SRCS = NotDynamic.C
DYNLIB_OBJS = NotDynamic.o
DYNLIB_DEFINES = -DDL_NOT_DYNAMIC
#endif
#ifndef DtMailDefines
# define DtMailDefines
#endif
#ifndef HPArchitecture
MAILSERVER_DEFINES = -DUSE_SOCKSTREAM
#endif
DEFINES = $(VFORK_DEFINES) $(DYNLIB_DEFINES) $(MAILSERVER_DEFINES) DtMailDefines
SRCS = \
$(DYNLIB_SRCS) \
APOPServer.C \
AUTOServer.C \
Buffer.C \
DetermineFileLocality.C \
DtMailBodyPart.C \
DtMailEnvelope.C \
DtMailError.C \
DtMailMailBox.C \
DtMailMessage.C \
DtMailRc.C \
DtMailServer.C \
DtMailTransport.C \
DtMailValuesBuiltin.C \
DtMailXtProc.C \
DtVirtArray.C \
DynamicLib.C \
FileShare.C \
HashTable.C \
IMAPServer.C \
IO.C \
LanguagePortability.C \
ObjectKey.C \
POP2Server.C \
POP3Server.C \
Process.C \
Session.C \
Threads.C \
md5.C \
str_utils.C
/*
* NOTE: All changes here must be mirrored in ../Imakefile's COMMON_OBJS
*/
OBJS = \
$(DYNLIB_OBJS) \
APOPServer.o \
AUTOServer.o \
Buffer.o \
DetermineFileLocality.o \
DtMailBodyPart.o \
DtMailEnvelope.o \
DtMailError.o \
DtMailMailBox.o \
DtMailMessage.o \
DtMailRc.o \
DtMailServer.o \
DtMailTransport.o \
DtMailValuesBuiltin.o \
DtMailXtProc.o \
DtVirtArray.o \
DynamicLib.o \
FileShare.o \
HashTable.o \
IMAPServer.o \
IO.o \
LanguagePortability.o \
ObjectKey.o \
POP2Server.o \
POP3Server.o \
Process.o \
Session.o \
Threads.o \
md5.o \
str_utils.o
#include <Library.tmpl>
SubdirLibraryRule($(OBJS))
DependTarget()

View File

@@ -0,0 +1,41 @@
/*
*+SNOTICE
*
*
* $XConsortium: ImplConfigTable.hh /main/5 1996/07/22 13:49:15 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 _IMPLCONFIGTABLE_HH
#define _IMPLCONFIGTABLE_HH
#include <DtMail/DtMailValues.hh>
struct ImplConfigTable {
char *impl_name;
char *lib_name;
char *meta_entry_point;
};
static const ImplConfigTable initial_impls[] = {
{ "Internet MIME", NULL, "RFCMetaFactory" },
#if defined(sun)
{ "Sun Mail Tool", NULL, "V3MetaFactory" },
#endif
{ NULL, NULL, NULL }
};
#endif

View File

@@ -0,0 +1,35 @@
/*
*+SNOTICE
*
*
* $XConsortium: LanguagePortability.C /main/4 1996/04/21 19:48:27 drk $
*
* 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
*/
#include <stdlib.h>
#include <DtMail/DtLanguages.hh>
void *
DtCPlusPlusAllocator::operator new(size_t size)
{
return(malloc(size));
}
void
DtCPlusPlusAllocator::operator delete(void * ptr)
{
free(ptr);
}

View File

@@ -0,0 +1,228 @@
/*
*+SNOTICE
*
* $TOG: MailRc.C /main/5 1998/07/23 18:02:46 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document 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
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <EUSCompat.h>
#include <unistd.h>
#include <pwd.h>
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
#include <DtMail/IO.hh>
#define MAXIMUM_PATH_LENGTH 2048
DtMail::MailRc::MailRc(DtMailEnv & error, Session * session)
: _vars(20)
{
_session = session;
error.clear();
passwd pw;
GetPasswordEntry(pw);
char *rc_name = new char[MAXIMUM_PATH_LENGTH];
strcpy(rc_name, pw.pw_dir);
strcat(rc_name, "/.mailrc");
_obj_mutex = MutexInit();
_rc_file = fopen(rc_name, "r");
if (!_rc_file) { // No rc file. This will be easy!
delete [] rc_name;
return;
}
parse_file();
delete [] rc_name;
}
DtMail::MailRc::~MailRc(void)
{
if (_rc_file) {
fclose(_rc_file);
}
MutexLock lock_scope(_obj_mutex);
if (_vars.length()) {
for (int i = 0; i < _vars.length(); i++) {
delete _vars[i]->variable;
delete _vars[i]->value;
delete _vars[i];
}
}
}
void
DtMail::MailRc::getValue(DtMailEnv & error, const char * var, const char ** value)
{
MutexLock lock_scope(_obj_mutex);
error.clear();
char * table_val;
if (_vars.length()) {
table_val = getVar(var);
}
else {
table_val = NULL;
}
if (!table_val) {
// Check the environment.
table_val = getenv(var);
if (!table_val) {
error.setError(DTME_NoObjectValue);
return;
}
}
*value = table_val;
}
void
DtMail::MailRc::setVar(const char * variable, const char * value)
{
MutexLock lock_scope(_obj_mutex);
// See if we can find this variable.
for (int i = 0; i < _vars.length(); i++) {
if (strcmp(variable, _vars[i]->variable) == 0) {
break;
}
}
// Create only if necessary.
if (i == _vars.length()) {
Variable * var = new Variable;
var->variable = strdup(variable);
var->value = strdup(value);
_vars.append(var);
return;
}
free(_vars[i]->value);
_vars[i]->value = strdup(value);
}
char *
DtMail::MailRc::getVar(const char * var)
{
for (int i = 0; i < _vars.length(); i++) {
if (strcmp(var, _vars[i]->variable) == 0) {
return(_vars[i]->value);
}
}
return(NULL);
}
void
DtMail::MailRc::parse_file(void)
{
char line[2000]; // Big enough, I think.
// Loop through each line in the file.
while(fgets(line, sizeof(line), _rc_file)) {
// If the first character is a #, then ignore it and go on.
if (line[0] == '#') {
continue;
}
// If this starts with "set", then parse it as a variable.
if (strncmp(line, "set ", 4) == 0) {
parse_var(line);
}
// There are lot's more options, but we don't do them yet.
}
}
void
DtMail::MailRc::parse_var(const char * line)
{
const char *cur_c;
char *variable = new char[100];
char *value = new char[2000];
// Find the start of the variable.
for (cur_c = &line[3]; isspace(*cur_c); cur_c++) {
continue;
}
const char * var_start = cur_c;
// The rules say the variable name ends at = or the end of the line.
for (;*cur_c && *cur_c != '=' && (!isspace(*cur_c)); cur_c++) {
continue;
}
memcpy(variable, var_start, (cur_c - var_start));
variable[cur_c - var_start] = 0;
// If there is no equal, then we are done.
if (*cur_c != '=') {
value[0] = 0;
setVar(variable, value);
delete [] variable;
delete [] value;
return;
}
// Oh well, more work to do. It is easy though. The value is the next character
// after the = to the end of the line.
strcpy(value, (cur_c + 1));
value[strlen(value) - 1] = 0; // Strip newline.
// Okay, finally, if we have quotes, remove those too.
if (*value == '\'' || *value == '"') {
memmove(value, &value[1], strlen(value));
value[strlen(value) - 1] = 0;
}
setVar(variable, value);
delete [] variable;
delete [] value;
}
const char *
DtMail::MailRc::getAlias(DtMailEnv & error, const char * name)
{
error.clear();
return(NULL);
}
const char *
DtMail::MailRc::getAlternates(DtMailEnv & error)
{
error.clear();
return(NULL);
}

View File

@@ -0,0 +1,62 @@
/*
*+SNOTICE
*
*
* $XConsortium: NotDynamic.C /main/4 1996/04/21 19:48:35 drk $
*
* 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
*/
#include <stdio.h>
#include <unistd.h>
#include "NotDynamic.hh"
NotDynamic::NotDynamic(const char * path)
: DynamicLib(path)
{
}
NotDynamic::~NotDynamic(void)
{
}
struct SymTable {
const char * symbol;
void * entry;
};
#include <DtMail/DtMail.hh>
extern "C" void * RFCMetaFactory(const char * op);
extern "C" void * V3MetaFactory(const char * op);
static const SymTable symbol_table[] = {
{ "RFCMetaFactory", RFCMetaFactory },
{ "V3MetaFactory", V3MetaFactory },
{ NULL, NULL }
};
void *
NotDynamic::getSym(const char * sym)
{
for (int i = 0; symbol_table[i].symbol; i++) {
if (strcmp(symbol_table[i].symbol, sym) == 0) {
return(symbol_table[i].entry);
}
}
return(NULL);
}

View File

@@ -0,0 +1,34 @@
/*
*+SNOTICE
*
*
* $XConsortium: NotDynamic.hh /main/4 1996/04/21 19:48:39 drk $
*
* 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 _NOTDYNAMIC_HH
#define _NOTDYNAMIC_HH
#include "DynamicLib.hh"
class NotDynamic : public DynamicLib {
public:
NotDynamic(const char * path);
virtual ~NotDynamic(void);
void * getSym(const char * symbol);
};
#endif

View File

@@ -0,0 +1,116 @@
/*
*+SNOTICE
*
*
* $XConsortium: ObjectKey.C /main/4 1996/04/21 19:48:43 drk $
*
* 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
*/
#include <assert.h>
#include <string.h>
#include <DtMail/ObjectKey.hh>
ObjectKey::ObjectKey(ObjectKeyType type)
{
_type = strdup(type);
return;
}
ObjectKey::ObjectKey(ObjectKey & key)
{
_type = strdup(key._type);
}
ObjectKey::~ObjectKey(void)
{
delete _type;
}
#ifdef DEAD_WOOD
int
ObjectKey::operator==(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator== called");
return(0);
}
int
ObjectKey::operator!=(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator!= called\n");
return(0);
}
int
ObjectKey::operator<(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator< called\n");
return(0);
}
int
ObjectKey::operator<=(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator<= called\n");
return(0);
}
int
ObjectKey::operator>(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator> called\n");
return(0);
}
int
ObjectKey::operator>=(ObjectKey &)
{
assert(!"Pure virtual ObjectKey::operator>= called\n");
return(0);
}
HashVal
ObjectKey::hashValue(void)
{
assert(!"Pure virtual ObjectKey::hashValue called\n");
return(0);
}
#endif /* DEAD_WOOD */
HashVal
ObjectKey::genericHashValue(void * buf, int len)
{
short * sbuf = (short *)buf;
int slen = len / 2;
HashVal hash = 0;
// Sum the bytes, 2 at a time. We will deal with fractional
// stuff after we do the main buffer.
//
for (int cur = 0; cur < slen; cur++) {
hash ^= sbuf[cur];
}
// If the length is not even, then we need to add the last
// byte to the high order bits of the hash value.
//
if ((len % 2)) {
hash ^= ((char *)buf)[len - 1] << 8;
}
if (hash < 0) hash = -hash;
return(hash);
}

View File

@@ -0,0 +1,224 @@
/*
*+SNOTICE
*
* $TOG: POP2Server.C /main/6 1998/11/10 17:08:56 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
/*
* Common Desktop Environment
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
* (c) Copyright 1995 Digital Equipment Corp.
* (c) Copyright 1995 Fujitsu Limited
* (c) Copyright 1995 Hitachi, Ltd.
*
*
* RESTRICTED RIGHTS LEGEND
*
*Use, duplication, or disclosure by the U.S. Government is subject to
*restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
*Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
*for non-DOD U.S. Government Departments and Agencies are as set forth in
*FAR 52.227-19(c)(1,2).
*Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
*International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
*Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
*Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
*Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
*Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
*Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
*/
#include <stdio.h>
#include <stdlib.h>
#include <DtMail/DtMailServer.hh>
#include <DtMail/IO.hh>
POP2Server::POP2Server(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
: DtMailServer(folder, session, mailbox,
append_mailbox_cb, append_mailbox_cb_data)
{
_pound_arg = 0;
_equal_arg = 0;
}
POP2Server::~POP2Server()
{
}
//
// Request nth message.
//
DTMailError_t
POP2Server::ptrans_retrieve_start(int msg, int *lenp)
{
DTMailError_t ok;
*lenp = 0;
ok = do_transaction("READ %d", msg);
if (DTME_NoError != ok) return ok;
*lenp = _equal_arg;
ok = do_send("RETR");
return ok;
}
//
// Apply for connection authorization.
//
DTMailError_t
POP2Server::ptrans_authorize(char*)
{
DTMailError_t ok;
ok = do_transaction("HELO %s %s", _username, _password);
if (DTME_NoError != ok) return DTME_MailServerAccess_AuthorizationFailed;
return DTME_NoError;
}
//
// Get range of messages to be fetched.
//
DTMailError_t
POP2Server::ptrans_fldstate_read(int *countp, int *newp)
{
//
// We should have picked up a count of messages in the user's
// default inbox from the pop2_getauth() response.
//
if (_pound_arg == -1)
return DTME_MailServerAccess_Error;
// Maybe the user wanted a non-default folder.
if (! is_inbox())
{
DTMailError_t ok;
ok = do_transaction("FOLD %s", _folder);
if (DTME_NoError != ok) return ok;
if (_pound_arg == -1) return DTME_MailServerAccess_Error;
}
*countp = _pound_arg;
*newp = -1;
return DTME_NoError;
}
//
// Capture the sizes of all messages.
//
DTMailError_t
POP2Server::ptrans_msgsizes(int countp, int *sizes)
{
memset((char*) sizes, 0, countp * sizeof(int));
return DTME_NoError;
}
//
// Is the given message old?
//
int
POP2Server::ptrans_msgisold(int)
{
return 0;
}
//
// Parse POP2 command response.
//
DTMailError_t
POP2Server::ptrans_parse_response (char *argbuf)
{
DTMailError_t ok;
char buf[DTMAS_POPBUFSIZE+1];
_pound_arg = _equal_arg = -1;
if (SockGets(buf, sizeof(buf), _sockfp))
{
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
if (buf[0] == '+')
ok = DTME_NoError;
else if (buf[0] == '#')
{
_pound_arg = atoi(buf+1);
ok = DTME_NoError;
}
else if (buf[0] == '=')
{
_equal_arg = atoi(buf+1);
ok = DTME_NoError;
}
else if (buf[0] == '-')
{
_logger.logError(DTM_FALSE, "Protocol Error reading response");
ok = DTME_MailServerAccess_Error;
}
else
{
_logger.logError(DTM_FALSE, "Protocol Violation reading response");
ok = DTME_MailServerAccess_ProtocolViolation;
}
if (argbuf != NULL)
strcpy(argbuf,buf);
}
else
{
_logger.logError(DTM_FALSE, "Socket Error reading response");
ok = DTME_MailServerAccess_SocketIOError;
}
return ok;
}
//
// retrieve messages using POP2.
//
void
POP2Server::retrieve_messages(DtMailEnv &error)
{
DtMailServer::retrieve_messages(error);
}
//
// Send acknowledgement for message data.
//
DTMailError_t
POP2Server::ptrans_retrieve_end(int)
{
if (_removeafterdelivery)
return do_transaction("ACKD");
else
return do_transaction("ACKS");
}

View File

@@ -0,0 +1,490 @@
/*
*+SNOTICE
*
* $TOG: POP3Server.C /main/8 1998/11/10 17:09:21 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993, 1995, 1995 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
/*
* Common Desktop Environment
*
* (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1995 Novell, Inc.
* (c) Copyright 1995 Digital Equipment Corp.
* (c) Copyright 1995 Fujitsu Limited
* (c) Copyright 1995 Hitachi, Ltd.
*
*
* RESTRICTED RIGHTS LEGEND
*
*Use, duplication, or disclosure by the U.S. Government is subject to
*restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
*Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
*for non-DOD U.S. Government Departments and Agencies are as set forth in
*FAR 52.227-19(c)(1,2).
*Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
*International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
*Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
*Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
*Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
*Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
*Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/param.h>
#include <unistd.h>
#include <DtMail/DtMail.hh>
#include <DtMail/DtMailError.hh>
#include <DtMail/DtMailServer.hh>
#include <DtMail/DtVirtArray.hh>
#include <DtMail/IO.hh>
POP3Server::POP3Server(
char *folder,
DtMail::Session *session,
DtMail::MailBox *mailbox,
DtMailAppendCallback append_mailbox_cb,
void *append_mailbox_cb_data)
: DtMailServer(folder, session, mailbox,
append_mailbox_cb, append_mailbox_cb_data)
{
_lastretrieved = 0;
_uidlist_old = NULL;
_uidlist_current = NULL;
_uidlist_file = NULL;
}
POP3Server::~POP3Server()
{
if (_uidlist_old)
uidlist_destroy(_uidlist_old);
_uidlist_old = NULL;
if (_uidlist_current)
uidlist_destroy(_uidlist_current);
_uidlist_current = NULL;
if (_uidlist_file)
free(_uidlist_file);
}
//
// Delete a given message.
//
DTMailError_t
POP3Server::ptrans_delete(int msg)
{
if (_uidlist_current)
{
char *uidliststr;
uidliststr = uidlist_find(_uidlist_current, msg, NULL);
_uidlist_current->remove(uidliststr);
free(uidliststr);
}
return do_transaction("DELE %d", msg);
}
//
// Request nth message.
//
DTMailError_t
POP3Server::ptrans_retrieve_start(int msg, int *lenp)
{
DTMailError_t ok;
char buf[DTMAS_POPBUFSIZE+1];
char *cp;
ok = do_send("RETR %d", msg);
if (DTME_NoError != ok) return ok;
ok = ptrans_parse_response(buf);
if (DTME_NoError != ok) return ok;
// Look for "nnn octets" -- there may or may not be preceding cruft.
if ((cp = strstr(buf, " octets")) == (char *)NULL)
*lenp = 0;
else
{
while (--cp > buf && isdigit(*cp))
continue;
*lenp = atoi(cp);
}
return DTME_NoError;
}
//
// Apply for connection authorization.
//
DTMailError_t
POP3Server::ptrans_authorize(char*)
{
static char *pname = "POP3Server::ptrans_authorize";
DTMailError_t ok;
ok = do_transaction("USER %s", _username);
if (DTME_NoError != ok) return DTME_MailServerAccess_AuthorizationFailed;
ok = do_transaction("PASS %s", _password);
if (DTME_NoError != ok) return DTME_MailServerAccess_AuthorizationFailed;
// We're approved.
return DTME_NoError;
}
//
// Get range of messages to be fetched.
//
DTMailError_t
POP3Server::ptrans_fldstate_read(int *countp, int *newp)
{
static char *pname = "POP3Server::ptrans_fldstate_read";
DTMailError_t ok;
char buf[DTMAS_POPBUFSIZE+1];
/* get the total message count */
ok = do_send("STAT");
if (DTME_NoError != ok) return ok;
ok = ptrans_parse_response(buf);
if (DTME_NoError != ok) return ok;
sscanf(buf, "%d %*d", countp);
/*
* Newer, RFC-1725-conformant POP servers may not have the LAST command.
* We work as hard as possible to hide this ugliness, but it makes
* counting new messages intrinsically quadratic in the worst case.
*/
*newp = -1;
if (*countp > 0)
{
ok = do_send("LAST");
if (DTME_NoError != ok) return ok;
ok = ptrans_parse_response(buf);
if (DTME_NoError == ok)
{
int last = 0;
if (sscanf(buf, "%d", &last) == 0)
_logger.logError(DTM_FALSE, "Protocol Error getting range");
if (0 == _retrieveerrors) _lastretrieved = last;
*newp = (*countp - _lastretrieved);
}
else
{
if (NULL == _uidlist_old)
{
_uidlist_old = uidlist_create();
uidlist_read(_uidlist_old);
}
if (NULL == _uidlist_current)
_uidlist_current = uidlist_create();
/* grab the mailbox's UID list */
ok = do_transaction("UIDL");
if (DTME_NoError != ok)
return ok;
else
{
int curmsg;
char curuidstr[DTMAS_IDSIZE+1];
*newp = 0;
while (SockGets(buf, sizeof(buf), _sockfp))
{
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
if (buf[0] == '.')
break;
else if (sscanf(buf, "%d %s", &curmsg, curuidstr) == 2)
{
char *uidliststr = NULL;
_uidlist_current->append(strdup(buf));
uidliststr = uidlist_find(_uidlist_old, -1, curuidstr);
if (uidliststr)
(*newp)++;
}
}
}
}
}
return DTME_NoError;
}
//
// Capture the sizes of all messages.
//
DTMailError_t
POP3Server::ptrans_msgsizes(int, int *sizes)
{
static char *pname = "POP3Server::ptrans_msgsizes";
char buf[DTMAS_POPBUFSIZE+1];
DTMailError_t ok;
ok = do_transaction("LIST");
if (DTME_NoError != ok) return ok;
while (SockGets(buf, sizeof(buf), _sockfp))
{
int curmsg, cursize;
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
if (buf[0] == '.')
break;
else if (sscanf(buf, "%d %d", &curmsg, &cursize) == 2)
sizes[curmsg-1] = cursize;
else
sizes[curmsg-1] = -1;
}
return DTME_NoError;
}
//
// Is the given message old?
//
int
POP3Server::ptrans_msgisold(int msg)
{
if (NULL == _uidlist_old)
return (msg <= _lastretrieved);
else
{
char curuidstr[DTMAS_IDSIZE+1];
int curmsg;
char *uidliststr = NULL;
uidliststr = uidlist_find(_uidlist_current, msg, NULL);
if (sscanf(uidliststr, "%d %s", &curmsg, curuidstr) == 2)
uidliststr = uidlist_find(_uidlist_old, -1, curuidstr);
else
uidliststr = NULL;
if (NULL != uidliststr)
return 1;
else
return 0;
}
}
//
// parse command response.
//
DTMailError_t
POP3Server::ptrans_parse_response (char *argbuf)
{
DTMailError_t ok;
char buf[DTMAS_POPBUFSIZE+1];
char *bufp;
if (SockGets(buf, sizeof(buf), _sockfp))
{
if (buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
if (buf[strlen(buf)-1] == '\r')
buf[strlen(buf)-1] = '\r';
if (_protologging)
_logger.logError(DTM_FALSE, "%s< %s", proto_name(), buf);
bufp = buf;
if (*bufp == '+' || *bufp == '-')
bufp++;
else
return DTME_MailServerAccess_ProtocolViolation;
while (isalpha(*bufp)) bufp++;
*(bufp++) = '\0';
if (strcmp(buf,"+OK") == 0)
{
ok = DTME_NoError;
}
else if (strcmp(buf,"-ERR") == 0)
{
_logger.logError(DTM_FALSE, "Protocol Error reading response");
ok = DTME_MailServerAccess_Error;
}
else
{
_logger.logError(DTM_FALSE, "Protocol Violation reading response");
ok = DTME_MailServerAccess_ProtocolViolation;
}
if (argbuf != NULL)
strcpy(argbuf,bufp);
}
else
{
_logger.logError(DTM_FALSE, "Socket Error reading response");
ok = DTME_MailServerAccess_SocketIOError;
}
return ok;
}
//
// Retrieve messages using POP3.
//
void
POP3Server::retrieve_messages(DtMailEnv &error)
{
DtMailServer::retrieve_messages(error);
uidlist_destroy(_uidlist_old);
_uidlist_old = _uidlist_current;
uidlist_write(_uidlist_old);
_uidlist_current = NULL;
}
DtVirtArray<char*>*
POP3Server::uidlist_create()
{
DtVirtArray<char*> *uidlist = new DtVirtArray<char*>(25);
return uidlist;
}
void
POP3Server::uidlist_destroy(DtVirtArray<char*> *uidlist)
{
int i, nuidliststr;
char *uidliststr;
if (NULL == uidlist) return;
for (i=0, nuidliststr=uidlist->length(); i<nuidliststr; i++)
{
uidliststr = (*uidlist)[i];
if (NULL != uidliststr)
free(uidliststr);
}
delete uidlist;
}
char*
POP3Server::uidlist_find(
DtVirtArray<char*> *uidlist,
int msg,
char *uidstr)
{
char *uidliststr;
int i, nuidliststr;
if (msg < 0 && NULL == uidstr) return NULL;
for (i=0, nuidliststr=uidlist->length(); i<nuidliststr; i++)
{
int curmsg;
char curuidstr[DTMAS_IDSIZE+1];
uidliststr = (*uidlist)[i];
if (sscanf(uidliststr, "%d %s", &curmsg, curuidstr) == 2)
{
if ((msg < 0 || msg == curmsg) &&
(uidstr == NULL || 0 == strcasecmp(uidstr, curuidstr)))
return uidliststr;
}
}
return NULL;
}
void
POP3Server::uidlist_read(DtVirtArray<char*> *uidlist)
{
static char *pname = "POP3Server::uidlist_read";
DtMailEnv error;
FILE *fp;
if (NULL == uidlist) return;
if (NULL == _uidlist_file)
{
char *path = new char[MAXPATHLEN+1];
sprintf(path, "+/.%s@%s.uidlist", _folder, _servername);
_uidlist_file = _session->expandPath(error, (const char*) path);
if (NULL == _uidlist_file && error.isSet())
{
_logger.logError(
DTM_FALSE,
"%s: Failed to find uidlist file %s\n",
pname, path);
delete [] path;
return;
}
delete [] path;
}
if (NULL != (fp = fopen(_uidlist_file, "r")))
{
char uidliststr[DTMAS_POPBUFSIZE+1];
char curuidstr[DTMAS_IDSIZE+1];
int curmsg;
while (NULL != fgets(uidliststr, DTMAS_POPBUFSIZE, fp))
if (sscanf(uidliststr, "%d %s", &curmsg, curuidstr) == 2)
uidlist->append(strdup(uidliststr));
}
fclose(fp);
}
void
POP3Server::uidlist_write(DtVirtArray<char*> *uidlist)
{
FILE *fp;
char *uidliststr;
int i, nuidliststr;
if (NULL == uidlist || NULL == _uidlist_file) return;
if (NULL != (fp = fopen(_uidlist_file, "w")))
{
for (i=0, nuidliststr=uidlist->length(); i<nuidliststr; i++)
{
uidliststr = (*uidlist)[i];
fprintf(fp, "%s\n", uidliststr);
}
}
fclose(fp);
}

View File

@@ -0,0 +1,275 @@
/*
*+SNOTICE
*
*
* $TOG: Process.C /main/6 1998/04/06 13:26:21 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
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
/*
** file included for INFTIM
*/
#if defined(SunOS) || defined(USL) || defined(__uxp__)
#include <stropts.h>
#elif defined(HPUX)
#include <sys/poll.h>
#elif defined(_AIX) || defined(linux)
#define INFTIM (-1) /* Infinite timeout */
#endif
#include <sys/wait.h>
#include "Process.hh"
#include <DtMail/Threads.hh>
#include <DtMail/IO.hh>
static const int DEFAULT_SIZE = 64 << 10;
void
SetNoBlock(int fd)
{
int flags;
do {
flags = fcntl(fd, F_GETFL);
} while(flags < 0 && errno == EINTR);
if (flags < 0) {
return;
}
flags |= O_NONBLOCK;
int status;
do {
status = fcntl(fd, F_SETFL, flags);
} while (status < 0 && errno == EINTR);
return;
}
int
RunProg(const char * program,
char *const * argv,
const char * stdin_data,
const unsigned long stdin_size,
char ** stdout_data,
unsigned long & stdout_size,
char ** stderr_data,
unsigned long & stderr_size)
{
// See if we are supposed to do I/O with the child.
//
int stdin_fd[2];
int stdout_fd[2];
int stderr_fd[2];
size_t stdout_bufsize = 0;
unsigned long stderr_bufsize = 0;
if (stdin_data) {
pipe(stdin_fd);
SetNoBlock(stdin_fd[1]);
}
if (stdout_data) {
pipe(stdout_fd);
SetNoBlock(stdout_fd[0]);
}
if (stderr_data) {
pipe(stderr_fd);
SetNoBlock(stderr_fd[0]);
}
// We will fork and set up the file descriptors in the
// child.
//
#if defined(POSIX_THREADS)
pid_t child = fork1();
#else
pid_t child = fork();
#endif
if (child < 0) {
return(child);
}
if (child == 0) { // The real child process.
if (stdin_data) {
SafeDup2(stdin_fd[0], STDIN_FILENO);
close(stdin_fd[0]);
close(stdin_fd[1]);
}
if (stdout_data) {
SafeDup2(stdout_fd[1], STDOUT_FILENO);
close(stdout_fd[0]);
close(stdout_fd[1]);
}
if (stderr_data) {
SafeDup2(stderr_fd[1], STDERR_FILENO);
close(stderr_fd[0]);
close(stderr_fd[1]);
}
SafeExecvp(program, argv);
return(child);
}
else { // This is still us.
int stdin_written = 0;
int nfds = 1;
pollfd fds[3];
memset(fds, 0, sizeof(fds));
fds[0].fd = stdin_fd[1];
fds[0].events = POLLOUT;
close(stdin_fd[0]);
if (stdout_data) {
fds[1].fd = stdout_fd[0];
fds[1].events = POLLIN;
nfds = 2;
*stdout_data = (char *)malloc(DEFAULT_SIZE);
stdout_bufsize = DEFAULT_SIZE;
stdout_size = 0;
close(stdout_fd[1]);
} else {
fds[1].fd = -1;
}
if (stderr_data) {
fds[2].fd = stderr_fd[0];
fds[2].events = POLLIN;
nfds = 3;
*stderr_data = (char *)malloc(DEFAULT_SIZE);
stderr_bufsize = DEFAULT_SIZE;
stderr_size = 0;
close(stderr_fd[1]);
} else {
fds[2].fd = -1;
}
// set up the initial events we way we care about. Note that
// fds[1] and fds[2] may not be used -- nfds may be less than 3
while (1) {
int result;
int i;
// check to make sure there is really some work to do
// walk through the fds structure. If we get to the end
// without finding anything to do, i will be == nfds
for (i = 0; i < nfds; i++) {
if (fds[i].fd >= 0) break;
}
if (i == nfds) {
// there was no work to do
break;
}
// we probably don't want to wait forever, so we can try
// and reap the child here, just in case it exits...
result = poll(fds, nfds, INFTIM);
if (result < 0) {
// poll error -- what do we do?
if (errno == EINTR) continue;
// not much else to do -- poll really shouldn't fail...
break;
}
if ((fds[0].revents & POLLOUT) &&
stdin_data && stdin_written < stdin_size) {
int status = SafeWrite(stdin_fd[1], stdin_data + stdin_written,
(size_t) stdin_size - stdin_written);
if (status > 0) {
stdin_written += status;
}
if (stdin_written >= stdin_size) {
// we're done with the input
close(stdin_fd[1]);
fds[0].fd = -1;
fds[0].events = 0;
}
}
// We will now try to read 4K from each requested file
// descriptor.
//
if (stdout_data && (fds[1].revents & POLLIN)) {
int status = SafeRead(stdout_fd[0], *stdout_data + stdout_size,
4096);
if (status < 0 && errno != EAGAIN) {
break;
}
if (status > 0) {
stdout_size += status;
if ((stdout_size + 4096) > stdout_bufsize) {
stdout_bufsize += DEFAULT_SIZE;
*stdout_data = (char *)realloc(*stdout_data, stdout_bufsize);
}
}
}
if (stderr_data && (fds[2].revents & POLLIN)) {
int status = SafeRead(stderr_fd[0], *stderr_data + stderr_size,
4096);
if (status < 0 && errno != EAGAIN) {
break;
}
if (status > 0) {
stderr_size += status;
}
if ((stderr_size + 4096) > stderr_bufsize) {
stderr_bufsize += DEFAULT_SIZE;
*stderr_data =
(char*) realloc(*stderr_data, (size_t) stderr_bufsize);
}
}
if ((fds[0].revents & POLLHUP) ||
(fds[1].revents & POLLHUP) ||
(fds[2].revents & POLLHUP)) {
break;
}
}
int child_stat;
SafeWaitpid(child, &child_stat, 0);
return(child_stat);
}
return(child);
}

View File

@@ -0,0 +1,34 @@
/*
*+SNOTICE
*
*
* $XConsortium: Process.hh /main/4 1996/04/21 19:48:50 drk $
*
* 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 _PROCESS_HH
#define _PROCESS_HH
int RunProg(const char * program,
char *const * argv,
const char * stdin_data,
const unsigned long stdin_size,
char ** stdout_data,
unsigned long & stdout_size,
char ** stderr_data,
unsigned long & stderr_size);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
/*
*+SNOTICE
*
*
* $XConsortium: SigChldImpl.hh /main/4 1996/04/21 19:49:01 drk $
*
* 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 _SIGCHLDIMPL_HH
#define _SIGCHLDIMPL_HH
#include <DtMail/DtVirtArray.hh>
#include <DtMail/Threads.hh>
struct SigChldInfo : public DtCPlusPlusAllocator {
int pid;
Condition cond;
};
extern DtVirtArray<SigChldInfo *> *DtMailSigChldList;
#endif

View File

@@ -0,0 +1,548 @@
/*
*+SNOTICE
*
*
* $TOG: Threads.C /main/5 1997/09/03 17:26:05 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
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if defined(I_HAVE_SELECT_H)
#include <sys/select.h>
#endif
#if defined(POSIX_THREADS)
#include <thread.h>
#include <synch.h>
#endif
#include <DtMail/DtMail.hh>
#include <DtMail/Threads.hh>
#include <DtMail/IO.hh>
static long DUMMY_MUTEX;
void *
MutexInit(void)
{
#if defined(POSIX_THREADS)
mutex_t *mutex = (mutex_t *)malloc(sizeof(mutex_t));
mutex_init(mutex, USYNC_THREAD, NULL);
return(mutex);
#else
return(&DUMMY_MUTEX);
#endif
}
void
MutexDestroy(void * mutex)
{
#if defined(POSIX_THREADS)
mutex_destroy((mutex_t *)mutex);
free(mutex);
#else
mutex = NULL;
#endif
return;
}
MutexLock::MutexLock(void * mutex)
{
#if defined(POSIX_THREADS)
mutex_lock((mutex_t *)mutex);
#endif
_mutex = mutex;
_locked = 1;
}
MutexLock::~MutexLock(void)
{
#if defined(POSIX_THREADS)
if (_locked) {
mutex_unlock((mutex_t *)_mutex);
}
#endif
}
void
MutexLock::unlock(void)
{
#if defined(POSIX_THREADS)
if (_locked) {
mutex_unlock((mutex_t *)_mutex);
}
_locked = 0;
#endif
}
void
MutexLock::unlock_and_destroy(void)
{
#if defined(POSIX_THREADS)
if (_locked) {
mutex_unlock((mutex_t *)_mutex);
}
_locked = 0;
MutexDestroy(_mutex);
#endif
}
SafeScalarImpl::SafeScalarImpl(void)
{
_mutex = MutexInit();
_value = 0;
}
SafeScalarImpl::~SafeScalarImpl(void)
{
MutexDestroy(_mutex);
}
long
SafeScalarImpl::operator = (const long val)
{
MutexLock lock_scope(_mutex);
_value = val;
return(_value);
}
long
SafeScalarImpl::operator += (const long val)
{
MutexLock lock_scope(_mutex);
_value += val;
return(_value);
}
long
SafeScalarImpl::operator -= (const long val)
{
MutexLock lock_scope(_mutex);
_value -= val;
return(_value);
}
long
SafeScalarImpl::operator *= (const long val)
{
MutexLock lock_scope(_mutex);
_value *= val;
return(_value);
}
long
SafeScalarImpl::operator /= (const long val)
{
MutexLock lock_scope(_mutex);
_value /= val;
return(_value);
}
int
SafeScalarImpl::operator == (const long val)
{
MutexLock lock_scope(_mutex);
return(_value == val);
}
int
SafeScalarImpl::operator <= (const long val)
{
MutexLock lock_scope(_mutex);
return(_value <= val);
}
int
SafeScalarImpl::operator < (const long val)
{
MutexLock lock_scope(_mutex);
return(_value < val);
}
int
SafeScalarImpl::operator >= (const long val)
{
MutexLock lock_scope(_mutex);
return(_value >= val);
}
int
SafeScalarImpl::operator > (const long val)
{
MutexLock lock_scope(_mutex);
return(_value > val);
}
int
SafeScalarImpl::operator != (const long val)
{
MutexLock lock_scope(_mutex);
return(_value != val);
}
SafeScalarImpl::operator long(void)
{
MutexLock lock_scope(_mutex);
return(_value);
}
Condition::Condition(void)
{
_mutex = MutexInit();
#if defined(POSIX_THREADS)
_condition = malloc(sizeof(cond_t));
cond_init((cond_t *)_condition, USYNC_THREAD, NULL);
#endif
}
Condition::~Condition(void)
{
MutexDestroy(_mutex);
#if defined(POSIX_THREADS)
cond_destroy((cond_t *)_condition);
free(_condition);
#endif
}
void
Condition::setTrue(void)
{
MutexLock lock_scope(_mutex);
_state = 1;
#if defined(POSIX_THREADS)
cond_broadcast((cond_t *)_condition); // Wake all sleepers.
#endif
}
void
Condition::setFalse(void)
{
MutexLock lock_scope(_mutex);
_state = 0;
#if defined(POSIX_THREADS)
cond_broadcast((cond_t *)_condition); // Wake all sleepers.
#endif
}
int
Condition::operator=(int new_state)
{
MutexLock lock_scope(_mutex);
_state = new_state;
#if defined(POSIX_THREADS)
cond_broadcast((cond_t *)_condition); // Wake all sleepers.
#endif
return(new_state);
}
int
Condition::operator+=(int new_state)
{
MutexLock lock_scope(_mutex);
_state += new_state;
#if defined(POSIX_THREADS)
cond_broadcast((cond_t *)_condition); // Wake all sleepers.
#endif
return(_state);
}
Condition::operator int(void)
{
return(state());
}
int
Condition::state(void)
{
MutexLock lock_scope(_mutex);
int save_state = _state;
return(save_state);
}
void
Condition::wait(void)
{
// Wait for anything to change.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
timestruc_t abstime;
abstime.tv_sec = time(NULL) + 1; // Wait for 1 second.
abstime.tv_nsec = 0;
cond_timedwait((cond_t *)_condition, (mutex_t *)_mutex, &abstime);
#endif
return;
}
void
Condition::waitTrue(void)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(!_state) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#else
_state = 1; // Must set of single threaded apps.
#endif
return;
}
#ifdef DEAD_WOOD
void
Condition::waitFalse(void)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(_state) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#else
_state = 0;
#endif
return;
}
void
Condition::waitFor(int new_state)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(_state != new_state) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#endif
return;
}
void
Condition::waitGT(int new_state)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(_state > new_state) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#endif
return;
}
void
Condition::waitLT(int new_state)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(_state < new_state) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#endif
return;
}
void
Condition::waitProcStatus(void)
{
// Wait for the condition to become true.
//
#if defined(POSIX_THREADS)
MutexLock lock_scope(_mutex);
while(_state < 0) {
cond_wait((cond_t *)_condition, (mutex_t *)_mutex);
}
#else
_state = 0;
#endif
return;
}
#endif /* DEAD_WOOD */
Thread
ThreadCreate(
#if defined(POSIX_THREADS)
ThreadEntryPoint entry, void * client_data)
{
thread_t id;
thr_create(NULL, 0, entry, client_data, THR_BOUND | THR_NEW_LWP, &id);
thr_continue(id);
return(id);
}
#else
ThreadEntryPoint, void*)
{
return(NULL);
}
#endif
Thread
ThreadSelf(void)
{
#if defined(POSIX_THREADS)
return(thr_self());
#else
return(NULL);
#endif
}
void
ThreadPrio(
#if defined(POSIX_THREADS)
Thread thread, const int prio)
{
thr_setprio((thread_t)thread, prio);
}
#else
Thread, const int)
{
}
#endif
void
ThreadKill(
#if defined(POSIX_THREADS)
Thread thread, const int sig)
{
thr_kill((thread_t)thread, sig);
}
#else
Thread, const int)
{
}
#endif
void
ThreadExit(
#if defined(POSIX_THREADS)
const int status)
{
thr_exit((void *)status);
}
#else
const int)
{
}
#endif
void
ThreadJoin(
#if defined(POSIX_THREADS)
Thread thread)
{
thr_join((thread_t)thread, NULL, NULL);
}
#else
Thread)
{
}
#endif
// The ThreadSleep function mimics the behavior of sleep(3), but
// uses select to prevent SIGALRM from being sent. This is bad
// on MT because often the main thread gets the signal and exits.
//
time_t
ThreadSleep(time_t secs)
{
time_t now = time(NULL);
timeval interval;
interval.tv_sec = secs;
interval.tv_usec = 0;
select(0, NULL, NULL, NULL, &interval);
time_t slept = time(NULL) - now;
if (slept < secs) {
return(secs - slept);
}
return(0);
}
#if defined(SPRO_V2)
void * operator new(size_t size)
{
return(malloc(size));
}
void operator delete(void * ptr)
{
free(ptr);
}
#endif

View File

@@ -0,0 +1,70 @@
/*
*+SNOTICE
*
* $TOG: VirtArray.hh /main/5 1997/12/22 16:35:24 bill $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document 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 _VIRTARRAY_HH
#define _VIRTARRAY_HH
#include <DtMail/DtLanguages.hh>
class DtVirtArrayImpl : public DtCPlusPlusAllocator {
public:
DtVirtArrayImpl(const int size);
~DtVirtArrayImpl(void);
int length(void);
void * operator[](const int at);
int indexof(void * handle);
void append(void * handle);
void insert(void * handle, const int at);
void remove(const int at);
private:
void make_slot(const int at);
void grow(void);
void **_elements;
int _size;
int _count;
void *_mutex;
};
template <class Element>
class DtVirtArray : public DtCPlusPlusAllocator {
public:
DtVirtArray(const int size)
: my_array(size) {}
~DtVirtArray(void) {}
int length(void) { return(my_array.length()); }
Element operator[](const int at) { return((Element)my_array[at]); }
int indexof(Element handle) { return(my_array.indexof(handle)); }
void append(Element handle) { my_array.append(handle); }
void insert(Element handle, const int at) { my_array.insert(handle, at); }
void remove(const int at) { my_array.remove(at); }
private:
DtVirtArrayImpl my_array;
};
#endif

View File

@@ -0,0 +1,380 @@
$ +SNOTICE
$
$ $TOG: libDtMail.msg /main/17 1999/03/26 16:52:56 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, 1994, 1995 Sun Microsystems, Inc. All rights reserved.
$
$ +ENOTICE
$ @(#)libDtMail.msg 1.9 23 May 1995
$quote "
$set 1 libDtMail API set
$ // DTME_NoError
1 "No error occured."
$ // DTME_AlreadyLocked
2 "The folder is locked by another session."
$ // DTME_BadArg
3 "A bad argument was passed as a parameter to the operation."
$ // DTME_BadMailAddress
4 "The specified mail address could not be processed."
$ // DTME_BadRunGroup
5 "The dtmail program is not running as group \"mail\"."
$ // DTME_FileCreateFailed
6 "The requested file could not be created."
$ // DTME_FolderNotSet
7 "The mailbox to incorporate was not set."
$ // DTME_GetLockRefused
8 "The user refused to take the lock of a locked mailbox."
$ // DTME_ImplFailure
9 "The specified implementation could not perform the requested operation."
$ // DTME_InitializationFailed
10 "The instance could not be initialized."
$ // DTME_InternalFailure
11 "An internal failure occurred while performing the operation."
$ // DTME_InvalidError
12 "The error structure is invalid."
$ // DTME_InvalidOperationSequence
13 "An operation was attempted before the instance was initialized."
$ // DTME_MD5ChecksumFailed
14 "The MD5 signature did not match the message contents."
$ // DTME_MailTransportFailed
15 "Unable to communicate with the mail transport."
$ // DTME_NoDataType
16 "There is no data type that matches the transport type."
$ // DTME_NoImplementations
17 "No implementations were found for the mail library."
$ // DTME_NoMailBox
18 "The mailbox was uninitialized at load time."
$ // DTME_NoMemory
19 "No memory available for operation."
$ // DTME_NoMsgCat
20 "No message catalog exists for DtMail."
$ // DTME_NoNewMail
21 "There is no new mail to incorporate."
$ // DTME_NoObjectValue
22 "No value for the object could be found."
$ // DTME_NoSuchFile
23 "The mailbox does not exist and creation was not requested."
$ // DTME_NoSuchImplementation
24 "The specified implementation does not exist."
$ // DTME_NoSuchType
25 "The data type is not known to the library."
$ // DTME_NoUser
26 "The user for this session could not be identified."
$ // DTME_NotInbox
27 "The file specified is not a mailbox."
$ // DTME_NotLocked
28 "The mailbox is not locked for access."
$ // DTME_NotMailBox
29 "The requested file is not a mailbox in any format recognized by this implementation."
$ // DTME_NotSupported
30 "The operation is not supported by the current implementation."
$ // DTME_ObjectAccessFailed
31 "Unable to access an object required to complete the operation."
$ // DTME_ObjectCreationFailed
32 "Unable to create an object required to complete the operation."
$ // DTME_ObjectInUse
33 "An attempt was made to initialize an object that was already initialized."
$ // DTME_ObjectInvalid
34 "An invalid object was referenced."
$ // DTME_OpenContainerInterrupted
35 "The user interrupted the process of opening a mailbox."
$ // DTME_OperationInvalid
36 "An internal error occurred while performing the operation."
$ // DTME_OtherOwnsWrite
37 "Another mail program owns the write access to the mailbox."
$ // DTME_RequestDenied
38 "The other session denied the request for lock or copy."
$ // DTME_TTFailure
39 "A ToolTalk message could not be processed."
$ // DTME_TransportFailed
40 "The mail delivery transport failed."
$ // DTME_UnknownFormat
41 "The message is not in one of the supported formats."
$ // DTME_UnknownOpenError
42 "An unknown error occurred when opening a mailbox."
$ // DTME_UserAbort
43 "The user aborted the operation."
$ // DTME_UserInterrupted
44 "The user interrupted the operation."
$ // DTME_ObjectReadOnly
45 "The mailbox permissions only allow read access."
$ // DTME_NoPermission
46 "The user does not have access to the mailbox."
$ // DTME_IsDirectory
47 "The specified path is a directory."
$ // DTME_CannotRemoveStaleMailboxLockFile
48 "Cannot lock mailbox (could not remove stale lock file).\nStale lock file: %s\nReason: %s"
$ // DTME_CannotCreateMailboxLockFile
49 "Cannot lock mailbox (could not create lock file).\nMailbox lock file: %s\nReason: %s"
$ // DTME_CannotCreateMailboxLockFile_NoPermission
50 "Cannot create lock file and lock mailbox because the user does not have\naccess to either the mailbox or the directory containing the mailbox."
$ // DTME_CannotCreateMailboxLockFile_IsDirectory
51 "Cannot create lock file and lock mailbox because the name for the\nmailbox lock file already exists and is a directory."
$ // DTME_CannotCreateMailboxLockFile_NoSuchFile
52 "Cannot create lock file and lock mailbox because a component of the\npath name of the lock file is not a directory."
$ // DTME_CannotCreateMailboxLockFile_RemoteAccessLost
53 "Cannot create lock file and lock mailbox because the remote system on\nwhich the lock file was to be created is no longer accessible."
$ // DTME_CannotObtainInformationOnOpenMailboxFile
54 "Cannot obtain information on current mailbox file.\nMailbox file: %s\nReason: %s"
$ // DTME_CannotCreateTemporaryMailboxFile
55 "Cannot create temporary mailbox file.\nTemporary Mailbox file: %s\nReason: %s"
$ // DTME_CannotCreateTemporaryMailboxFile_NoPermission
56 "Cannot create temporary mailbox file because the user does not have\naccess to either the mailbox or the directory containing the mailbox."
$ // DTME_CannotCreateTemporaryMailboxFile_IsDirectory
57 "Cannot create temporary mailbox file because the name for the\ntemporary mailbox already exists and is a directory."
$ // DTME_CannotCreateTemporaryMailboxFile_NoSuchFile
58 "Cannot create temporary mailbox file because a component of the\npath name of the temporary file is not a directory."
$ // DTME_CannotCreateTemporaryMailboxFile_RemoteAccessLost
59 "Cannot create temporary mailbox file because the remote system on\nwhich the file was to be created is no longer accessible."
$ // DTME_CannotSetPermissionsOfTemporaryMailboxFile
60 "Cannot set permissions on temporary mailbox file.\nTemporary Mailbox file: %s\nPermissions requested: %o\nReason: %s"
$ // DTME_CannotSetOwnerOfTemporaryMailboxFile
61 "Cannot set owner of temporary mailbox file.\nTemporary Mailbox file: %s\nOwner uid requested: %d\nReason: %s"
$ // DTME_CannotSetGroupOfTemporaryMailboxFile
62 "Cannot set group of temporary mailbox file.\nTemporary Mailbox file: %s\nGroup gid requested: %d\nReason: %s"
$ // DTME_CannotWriteToTemporaryMailboxFile
63 "Cannot write to temporary mailbox file.\nTemporary Mailbox file: %s\nReason: %s"
$ // DTME_CannotWriteToTemporaryMailboxFile_ProcessLimitsExceeded
64 "Cannot write to temporary mailbox file because the process's file\nsize limit or the maximum file size has been reached."
$ // DTME_CannotWriteToTemporaryMailboxFile_RemoteAccessLost
65 "Cannot write to temporary mailbox file because the remote system on\nwhich the file was created is no longer accessible."
$ // DTME_CannotWriteToTemporaryMailboxFile_NoFreeSpaceLeft
66 "Cannot write to temporary mailbox file because there is no free\nspace left on the device on which the file was created."
$ // DTME_CannotReadNewMailboxFile
67 "Cannot read new mailbox file\nReason: %s"
$ // DTME_CannotReadNewMailboxFile_OutOfMemory
68 "Cannot read new mailbox file because no memory is available for the operation."
$ // DTME_CannotRemoveMailboxLockFile
69 "Cannot unlock mailbox (could not remove lock file).\nMailbox lock file: %s\nReason: %s"
$ // DTME_CannotRenameNewMailboxFileOverOld
70 "Cannot rename new mailbox file over old mailbox file.\nOld mailbox file still exists but complete and correct contents\nof mailbox contents have been saved in the new mailbox file.\nThis problem must be corrected manually as soon as possible.\nOld Mailbox file: %s\nNew Mailbox file: %s\nReason: %s"
$ // DTME_InternalAssertionFailure
71 "An internal error has occurred within this application.\nThere is no way to recover and continue from this error.\nError condition: %s\n"
$ "-NEW"
$ // - DTME_ResourceParsingNoEndif
$
72 "An error occurred while parsing the .mailrc resource file.\nThere is a conditional if statement that does not have a corresponding endif statement.\n"
$ "-NEW"
$ // - DTME_AlreadyOpened
$
73 "This mail folder is already opened."
$ "-NEW"
$ // - DTME_OutOfSpace
$
74 "No Space on Temporary Filesystem."
$ "-NEW"
$ // - DTME_CannotCreateMailboxDotDtmailLockFile
75 "Mailer has detected a mailbox lockfile:\n%s"
$ "-NEW"
$ // - DTME_MailboxInodeChanged
76 "Mailer can no longer access this mailbox.\nIt would be best to close and reopen it."
$ "-NEW"
$ // - DTME_MailServerAccess_AuthorizationFailed
77 "Cannot retrieve mail for '%s@%s' using '%s'.\nAuthorization failed. The server returned:\n %s\n\nPlease enter a new password"
$ "-NEW"
$ // - DTME_MailServerAccess_Error
78 "Cannot retrieve mail for '%s@%s' using '%s'.\nThe server returned:\n %s"
$ "-NEW"
$ // - DTME_MailServerAccess_MissingPassword
79 "Please enter a password for '%s@%s' using '%s'"
$ "-NEW"
$ // - DTME_MailServerAccess_ProtocolViolation
80 "Cannot retrieve mail for '%s@%s' using '%s'.\nClient/server protocol error."
$ "-NEW"
$ // - DTME_MailServerAccess_ServerTimeoutError
81 "Cannot retrieve mail for '%s@%s' using '%s'.\nTimed out waiting for server."
$ "-NEW"
$ // - DTME_MailServerAccess_SocketIOError
82 "Cannot retrieve mail for '%s@%s' using '%s'.\n%s."
$ "-NEW"
$ // - DTME_AppendMailboxFile_Error
83 "Cannot append to mailbox"
$ "-NEW"
$ // - DTME_AppendMailboxFile_FileTooBig
84 "Cannot append to mailbox: %s\nSYSERROR(%d): %s."
$ "-NEW"
$ // - DTME_AppendMailboxFile_LinkLost
85 "Cannot append to mailbox: %s\nSYSERROR(%d): %s."
$ "-NEW"
$ // - DTME_AppendMailboxFile_NoSpaceLeft
86 "Cannot append to mailbox: %s\nSYSERROR(%d): %s."
$ "-NEW"
$ // - DTME_AppendMailboxFile_SystemError
87 "Cannot append to mailbox: %s\nSYSERROR(%d): %s."
$ "-NEW"
$ // - DTME_GetmailCommandRetrieval_SystemError
88 "Getmail command failed: %s\nSYSERROR(%d): %s."
$ "-NEW"
$ // - DTME_GetmailCommandRetrieval_AbnormalExit
89 "Getmail command exited abnormally: %s."
$ "-NEW"
$ // - DTME_PathElementPermissions
90 "Search permission denied on a component of the path prefix,\n'%s'."
$ "-NEW"
$ // - DTME_PathElementNotDirectory
91 "A component of the path prefix is not a directory,\n'%s'."
$ "-NEW"
$ // - DTME_PathElementDoesNotExist
92 "A component of the path prefix does not exist,\n'%s'."
$ "-NEW"
$ // - DTME_MailServerAccessInfo_SocketOpen
93 "Opening connection for '%s@%s'."
$ "-NEW"
$ // - DTME_MailServerAccessInfo_NoMessages
94 "No messages for '%s@%s'."
$ "-NEW"
$ // - DTME_MailServerAccessInfo_RetrievingMessage
95 "Retrieving message %d of %d for '%s@%s'."
$ "-NEW"
$ // - DTME_MailServerAccessInfo_MessageTooLarge
96 "Skipping oversized message (%d bytes)."
$
$ Strings from libDtMail/Common/DtMailValuesBuiltin.C
$set 2
$ /* NL_COMMENT
$ * The %C is the time and date format, please refer to strftime man page for
$ * explanation of each format.
$ */
1 "%C"
$
$ SockOpen error strings from libDtMail/Common/IO.C
$ "-NEW"
2 "Unknown host: %s"
$ "-NEW"
3 "Error creating socket: %s"
$ "-NEW"
4 "Error connecting to socket: %s"
$
$ FileShare error strings from libDtMail/Common/FileShare.C
$ "-NEW"
5 "Another user would like your lock."
$ "-NEW"
6 "Another session has this mailbox locked. Request access?"
$ "-NEW"
7 "Unable to obtain lock, open this mailbox as read only?"
$ "-NEW"
8 "Unable to obtain lock because system not responding, open this mailbox as read only, read write, or cancel?"
$ "-NEW"
9 "Another user has taken your lock."

View File

@@ -0,0 +1,344 @@
/*
*+SNOTICE
*
* $XConsortium: md5.C /main/4 1996/04/21 19:49:12 drk $
*
* 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
*/
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include <string.h>
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
static void Encode PROTO_LIST
((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST
((UINT4 *, unsigned char *, unsigned int));
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
extern "C"
void MD5Init (MD5_CTX *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
extern "C"
void MD5Update (MD5_CTX *context,
unsigned char *input,
unsigned int inputLen)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
extern "C"
void MD5Final (unsigned char digest[16],
MD5_CTX *context)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (UINT4 state[4],
unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (unsigned char *output,
UINT4 *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output,
unsigned char *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (POINTER output,
POINTER input,
unsigned int len)
{
memcpy(output, input, len);
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (POINTER output,
int value,
unsigned int len)
{
memset(output, value, len);
}

View File

@@ -0,0 +1,70 @@
/*
*+SNOTICE
*
*
* $XConsortium: md5.h /main/3 1995/11/06 16:39:40 rswiston $
*
* 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
*/
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifndef _MD5_H
#define _MD5_H
#include "md5global.h"
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
#ifdef __cplusplus
extern "C" {
#endif
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char *, MD5_CTX *);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,53 @@
/*
*+SNOTICE
*
*
* $XConsortium: md5global.h /main/3 1995/11/06 16:39:48 rswiston $
*
* 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
*/
/* GLOBAL.H - RSAREF types and constants
*/
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
been defined with C compiler flags.
*/
#if defined(__STDC__) || defined(__cplusplus)
#define PROTOTYPES 1
#else
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif

View File

@@ -0,0 +1,61 @@
/* $TOG: str_utils.C /main/2 1997/09/03 17:26:30 mgreess $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1993-1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <ctype.h>
#include "str_utils.h"
#ifdef NEED_STRCASECMP
/*
* In case strcasecmp and strncasecmp are not provided by the system
* here are ones which do the trick.
*/
extern "C"
int
strcasecmp(register const char *s1,
register const char *s2)
{
register int c1, c2;
while (*s1 && *s2) {
c1 = isupper(*s1) ? tolower(*s1) : *s1;
c2 = isupper(*s2) ? tolower(*s2) : *s2;
if (c1 != c2)
return (c1 - c2);
s1++;
s2++;
}
return (int) (*s1 - *s2);
}
extern "C"
int
strncasecmp(register const char *s1,
register const char *s2,
register size_t count)
{
register int c1, c2;
if (!count)
return 0;
while (*s1 && *s2) {
c1 = isupper(*s1) ? tolower(*s1) : *s1;
c2 = isupper(*s2) ? tolower(*s2) : *s2;
if ((c1 != c2) || (! --count))
return (c1 - c2);
s1++;
s2++;
}
return (int) (*s1 - *s2);
}
#endif

View File

@@ -0,0 +1,82 @@
XCOMM $TOG: Imakefile /main/10 1998/08/10 15:47:14 mgreess $
#define DoNormalLib YES
#define DoSharedLib NO
#define DoDebugLib NO
#define DoProfileLib NO
#define LibName DtMail
#define LibHeaders NO
#define LibInstall NO
#define CplusplusSource YES
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
#define IHaveSubdirs
#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CXXDEBUGFLAGS=$(CXXDEBUGFLAGS)'
SUBDIRS = Common RFC
EXTRALIBRARYDEPS = Common/DONE RFC/DONE
MakeSubdirs($(SUBDIRS))
ForceSubdirs($(SUBDIRS))
DependSubdirs($(SUBDIRS))
#include <Threads.tmpl>
#if defined(DtMailDynamicLinking) && DtMailDynamicLinking
DYNLIB_SRCS = Common/DlDynamicLib.C
DYNLIB_OBJS = Common/DlDynamicLib.o
#else
DYNLIB_SRCS = Common/NotDynamic.C
DYNLIB_OBJS = Common/NotDynamic.o
#endif
COMMON_OBJS = \
$(DYNLIB_OBJS) \
Common/APOPServer.o \
Common/AUTOServer.o \
Common/Buffer.o \
Common/DetermineFileLocality.o \
Common/DtMailBodyPart.o \
Common/DtMailEnvelope.o \
Common/DtMailError.o \
Common/DtMailMailBox.o \
Common/DtMailMessage.o \
Common/DtMailRc.o \
Common/DtMailServer.o \
Common/DtMailTransport.o \
Common/DtMailValuesBuiltin.o \
Common/DtMailXtProc.o \
Common/DtVirtArray.o \
Common/DynamicLib.o \
Common/FileShare.o \
Common/HashTable.o \
Common/IMAPServer.o \
Common/IO.o \
Common/LanguagePortability.o \
Common/ObjectKey.o \
Common/POP2Server.o \
Common/POP3Server.o \
Common/Process.o \
Common/Session.o \
Common/Threads.o \
Common/md5.o \
Common/str_utils.o
RFC_OBJS = \
RFC/AliasExpand.o \
RFC/MIMEBodyPart.o \
RFC/MIMEPartial.o \
RFC/RFCBodyPart.o \
RFC/RFCEnvelope.o \
RFC/RFCFormat.o \
RFC/RFCMailBox.o \
RFC/RFCMailValues.o \
RFC/RFCMessage.o \
RFC/RFCMIME.o \
RFC/RFCTransport.o \
RFC/SunV3.o \
RFC/V3BodyPart.o
OBJS = $(COMMON_OBJS) $(RFC_OBJS)
#include <Library.tmpl>

View File

@@ -0,0 +1,165 @@
/*
*+SNOTICE
*
*
* $XConsortium: AliasExpand.C /main/4 1996/04/21 19:49:19 drk $
*
* 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
*/
#include <assert.h>
#include "AliasExpand.hh"
#include "RFCImpl.hh"
AliasKey::AliasKey(const char * str)
: ObjectKey("AliasKey")
{
_str = strdup(str);
}
AliasKey::~AliasKey(void)
{
free(_str);
}
int
AliasKey::operator==(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) == 0);
}
int
AliasKey::operator!=(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) != 0);
}
int
AliasKey::operator<(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) < 0);
}
int
AliasKey::operator<=(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) <= 0);
}
int
AliasKey::operator>(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) > 0);
}
int
AliasKey::operator>=(ObjectKey & other)
{
AliasKey * ok = (AliasKey *)&other;
return(strcmp(_str, ok->_str) >= 0);
}
HashVal
AliasKey::hashValue(void)
{
return(genericHashValue(_str, strlen(_str)));
}
// deleteAllocatedKey: used to iterate through a hash table to remove
// all key values that are allocated during the duration of rfcAliasExpand
//
static int
deleteAllocatedKey(ObjectKey & object, AliasKey *, void *) {
assert(&object != NULL);
delete &object;
return(1);
}
void
rfcAliasExpand(DtMailEnv & error,
DtMail::MailRc & mailrc,
DtMailAddressSeq & addrs)
{
HashTable<DtMailBoolean> been_there(32);
error.clear();
// We will go through each item in the address table.
// For each address, we will look it up in the alias
// table. If it exists there, we will check to see if
// we have expanded before. If not, then we expand and
// note our visit.
//
DtMailEnv lerror;
for (int naddr = 0; naddr < addrs.length(); naddr++) {
DtMailValueAddress * caddr = addrs[naddr];
const char * alias = mailrc.getAlias(lerror, caddr->dtm_address);
if (alias) {
AliasKey * key = new AliasKey(caddr->dtm_address);
if (been_there.lookup(*key)) { // already visited address?
delete key; // yes: cleanup unneeded key
}
else { // no: expand the alias
DtMailAddressSeq exp_addrs(32);
RFCTransport::arpaPhrase(alias, exp_addrs);
for (int cp = 0; cp < exp_addrs.length(); cp++) {
DtMailValueAddress * new_addr = new DtMailValueAddress(*exp_addrs[cp]);
addrs.append(new_addr);
}
been_there.set(*key, DTM_TRUE);
}
addrs.remove(naddr); // no longer need this address
naddr -= 1; // ...
delete caddr; // or what it pointed to.
}
}
// Finally, as a courtesy to the recipients, we will throw away
// duplicates that have resulted from our expansion.
//
HashTable<DtMailBoolean> done_that(32);
for (int cur = 0; cur < addrs.length(); cur++) {
DtMailValueAddress * caddr = addrs[cur];
AliasKey * dup_key = new AliasKey(caddr->dtm_address);
if (done_that.lookup(*dup_key)) {
addrs.remove(cur);
delete caddr;
delete dup_key;
cur -= 1;
}
else {
done_that.set(*dup_key, DTM_TRUE);
}
}
}

View File

@@ -0,0 +1,50 @@
/*
*+SNOTICE
*
*
* $XConsortium: AliasExpand.hh /main/4 1996/04/21 19:49:22 drk $
*
* 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 _ALIASEXPAND_HH
#define _ALIASEXPAND_HH
#include <DtMail/DtMail.hh>
#include <DtMail/HashTable.hh>
class AliasKey : public ObjectKey {
public:
AliasKey(const char * str);
~AliasKey(void);
int operator==(ObjectKey &);
int operator!=(ObjectKey &);
int operator<(ObjectKey &);
int operator>(ObjectKey &);
int operator<=(ObjectKey &);
int operator>=(ObjectKey &);
HashVal hashValue(void);
private:
char * _str;
};
void rfcAliasExpand(DtMailEnv &,
DtMail::MailRc & mailrc,
DtMailAddressSeq & addrs);
#endif

View File

@@ -0,0 +1,53 @@
XCOMM $TOG: Imakefile /main/8 1998/08/05 13:25:32 mgreess $
#define DoNormalLib YES
#define DoSharedLib NO
#define DoDebugLib NO
#define DoProfileLib NO
#define LibName DtMail
#define LibHeaders NO
#define LibCreate NO
#define CplusplusSource YES
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
#include <Threads.tmpl>
INCLUDES = -I. -I../Common -I../../include -I../../include/utils -I$(CDELIBSRC)
#if HasVFork
VFORK_DEFINES = -DHAS_VFORK
#else
VFORK_DEFINES =
#endif
#ifndef DtMailDefines
# define DtMailDefines
#endif
DEFINES = -DTTLOCK_OFF $(VFORK_DEFINES) DtMailDefines
SRCS = \
AliasExpand.C MIMEBodyPart.C \
MIMEPartial.C RFCBodyPart.C \
RFCEnvelope.C RFCFormat.C \
RFCMIME.C RFCMailBox.C \
RFCMailValues.C RFCMessage.C \
RFCTransport.C SunV3.C \
V3BodyPart.C
/*
* NOTE: All changes here must be mirrored in ../Imakefile's RFC_OBJS
*/
OBJS = \
AliasExpand.o MIMEBodyPart.o \
MIMEPartial.o RFCBodyPart.o \
RFCEnvelope.o RFCFormat.o \
RFCMailBox.o RFCMailValues.o \
RFCMessage.o RFCMIME.o \
RFCTransport.o SunV3.o \
V3BodyPart.o
#include <Library.tmpl>
SubdirLibraryRule($(OBJS))
DependTarget()

View File

@@ -0,0 +1,998 @@
/*
*+SNOTICE
*
*
* $TOG: MIMEBodyPart.C /main/11 1998/04/06 13:27:03 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
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <Dt/Dts.h>
#include <DtMail/DtMail.hh>
#include "RFCImpl.hh"
#include "RFCMIME.hh"
#include <DtMail/Threads.hh>
#include "md5.h"
// For CHARSET
#include <locale.h>
#include <DtHelp/LocaleXlate.h>
#include "str_utils.h"
MIMEBodyPart::MIMEBodyPart(DtMailEnv & error,
DtMail::Message * parent,
const char * start,
const int len,
RFCEnvelope * body_env)
: RFCBodyPart(error, parent, start, len, body_env)
{
// A single part message. We are done for now.
//
error.clear();
return;
}
MIMEBodyPart::MIMEBodyPart(DtMailEnv & error,
DtMail::Message * parent,
const char * start,
const char ** end,
const char * boundary)
: RFCBodyPart(error, parent, start, 0, NULL)
{
error.clear();
// We are sitting at the start of a boundary. We need to get
// past the boundary to do the real processing.
//
const char * body_end;
for (body_end = _body_text; body_end <= *end && *body_end != '\n'; body_end++) {
continue;
}
body_end += 1;
if (body_end > *end) {
// Don't know. Give up!
*end = body_end;
_body_len = *end - start + 1;
// Need a bogus envelope for other uses.
//
_body_env = new RFCEnvelope(error, parent, NULL, 0);
return;
}
const char * env_start = body_end;
_my_env = DTM_TRUE;
if (isTerm(env_start)) {
_body_env = new RFCEnvelope(error, parent, env_start, 0);
}
else {
// Find the blank line where the envelope ends.
//
for (; body_end <= *end; body_end++) {
if (*body_end == '\n') {
int blank_only = 1;
for (const char * blank = body_end + 1;
blank <= *end && *blank != '\n'; blank++) {
if (!isspace((unsigned char)*blank)) {
blank_only = 0;
break;
}
}
if (blank_only) {
break;
}
}
}
_body_env = new RFCEnvelope(error,
parent,
env_start,
body_end - env_start + 1);
body_end += 1;
}
// Chew everything up to the next new line, which should be only
// a CRLF.
//
for (;body_end <= *end && *body_end != '\n'; body_end++) {
continue;
}
body_end += 1;
_body_text = body_end; // This is where the body really starts.
// Now we need to find the end of the body. MIME doesn't have
// any predefined length fields so we have to use the boundaries.
//
int bndry_len = strlen(boundary);
for (;body_end <= *end; body_end++) {
if (*body_end == '\n' &&
*(body_end + 1) == '-' &&
*(body_end + 2) == '-' &&
strncmp(body_end + 3, boundary, bndry_len) == 0) {
break;
}
}
if (*(body_end - 1) == '\r') {
body_end -= 1;
}
_body_len = body_end - _body_text + 1;
// MIME says the CRLF preceding a boundary belongs to the boundary.
// We will pull it off here rather than do it on entry to this
// method for the next message.
for (;body_end <= *end && *body_end != '\n'; body_end++) {
continue;
}
body_end += 1;
// Computing the end here is a little different. If the boundary
// ends with a "--" as well, then we are at the real end of
// the message.
//
const char * bndry_end = body_end + 2 + strlen(boundary);
if (*bndry_end == '-' && *(bndry_end + 1) == '-') {
*end = *end + 1;
}
else {
*end = body_end;
}
return;
}
MIMEBodyPart::~MIMEBodyPart(void)
{
}
#ifdef DEAD_WOOD
DtMailChecksumState
MIMEBodyPart::checksum(DtMailEnv & error)
{
error.clear();
// Look for the Content-MD5 header. If it is not present, then
// the state is unknown and we can punt.
//
DtMailEnv my_error;
DtMailValueSeq value;
_body_env->getHeader(my_error, "Content-MD5", DTM_FALSE, value);
if (my_error.isSet()) {
return(DtMailCheckUnknown);
}
if (_body_type == NULL) {
getDtType(error);
if (error.isSet()) {
return(DtMailCheckUnknown);
}
}
char stored_digest[32];
int stored_size = 0;
RFCMIME::readBase64(stored_digest, stored_size,
*(value[0]), strlen(*(value[0])));
if (stored_size != 16) {
// The MD5 sum must be 16 bytes, or we have a bad checksum.
//
return(DtMailCheckBad);
}
// See if we call this text. We need to handle md5 checksums
// different for text. They must be computed with CRLF line
// termination.
//
char * text_type = DtDtsDataTypeToAttributeValue(_body_type,
DtDTS_DA_IS_TEXT,
NULL);
unsigned char digest[16];
if (text_type && strcasecmp(text_type, "true") == 0) {
RFCMIME::md5PlainText(_body, _body_decoded_len, digest);
}
else {
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, (unsigned char *)_body, _body_decoded_len);
MD5Final(digest, &context);
}
free(text_type);
if (memcmp(digest, stored_digest, sizeof(digest)) == 0) {
return(DtMailCheckGood);
}
else {
return(DtMailCheckBad);
}
}
#endif /* DEAD_WOOD */
static int
countTypes(char ** types)
{
int count;
for (count = 0; *types; types++, count++) {
continue;
}
return(count);
}
void
MIMEBodyPart::getContentType(DtMailEnv &error, char **mime_type)
{
DtMailValueSeq value;
if (mime_type)
*mime_type = (char *)0;
if (_body_env)
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
if (_body_env && !error.isSet())
{
// Handle "Content-Type: text" problem with /usr/lib/mail.local
if (strcasecmp(*(value[0]), "text")==0)
*mime_type = strdup("text/plain");
else
*mime_type = strdup(*(value[0]));
}
else
{
error.clear();
*mime_type = strdup("text/plain");
}
}
void
MIMEBodyPart::getDtType(DtMailEnv & error)
{
MutexLock lock_scope(_obj_mutex);
MutexLock dt_lib_lock(_DtMutex);
// error.clear();
char * end;
char * mime_type;
DtMailValueSeq value;
if (_body_env) {
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
}
if (_body_env && !error.isSet()) {
// Handle "Content-Type: text" problem with /usr/lib/mail.local
//
if (strcasecmp(*(value[0]), "text")==0)
mime_type = strdup("text/plain");
else
mime_type = strdup(*(value[0]));
}
else {
error.clear();
mime_type = strdup("text/plain");
}
for (end = mime_type; *end; end++) {
if (*end == ';' || isspace((unsigned char)*end)) {
break;
}
if (isupper(*end)) {
*end = tolower(*end);
}
}
*end = 0;
char ** types = DtDtsFindAttribute(DtDTS_DA_MIME_TYPE, mime_type);
// We must have an exact 1:1 mapping between the mime type and the
// CDE type to use this inverse mapping. If we have no hits then we
// dont have any thing to use. If we have several hits, then we have
// no idea which type is the correct type.
//
if (NULL != types) {
if (countTypes(types) == 1) {
// We will use the first name. It may be wrong, but
// it is the best we can do at this point.
//
_body_type = strdup(types[0]);
DtDtsFreeDataTypeNames(types);
free(mime_type);
return;
}
DtDtsFreeDataTypeNames(types);
}
// We need the bits so we can type the buffer and get
// a type for the object. This is where things can get
// very slow for the user.
//
loadBody(error);
if (error.isSet()) {
return;
}
int istext = (strcasecmp(mime_type, "text/plain") == 0);
char * name = getNameHeaderVal(error);
char * type = DtDtsBufferToDataType(_body, _body_decoded_len, name);
// We have written a name pattern for text parts that will match
// the name "text" as a TEXT part. If the first attempt to get the
// data type fails and we have a MIMETYPE of text/plain, then we try
// again using the name "text".
//
if ( (0 == strcasecmp(mime_type, "text/plain")) &&
(NULL == type || 0 == strcasecmp(type, "DATA")) )
{
if (type)
DtDtsFreeDataType(type);
type = DtDtsBufferToDataType(_body, _body_decoded_len, "text");
}
if (NULL != type)
_body_type = strdup(type);
else
_body_type = strdup("UNKNOWN");
if (error.isSet())
error.clear();
if (type)
DtDtsFreeDataType(type);
if (mime_type)
free(mime_type);
if (name)
free(name);
}
void
MIMEBodyPart::loadBody(DtMailEnv & error)
{
// For CHARSET
char *cs = NULL, *to_cs = NULL, *from_cs = NULL;
// There is no reason to clear the error object because it is assumed
// that whoever instantiated it, cleared it.
// error.clear();
if (_body) {
return;
}
// If there is any encoding done to the body, reverse it
//
DtMailValueSeq value;
if (_body_env) {
_body_env->getHeader(error, "Content-Transfer-Encoding",
DTM_FALSE, value);
}
if (_body_env && !error.isSet()) {
const char * enc = *(value[0]);
if (strcasecmp(enc, "base64") == 0) {
// Decoded bodies will always be smaller than
// encoded bodies.
//_body = (char *)malloc(_body_len);
_body = (char *)malloc(_body_len+1);
int size = _body_decoded_len = 0;
_must_free_body = DTM_TRUE;
RFCMIME::readBase64(_body, size, _body_text, _body_len);
_body_decoded_len = size;
// Changed this temporarily until after release. We really should not
// be null terminating these buffers.
(_body)[_body_decoded_len] = 0;
}
else if (strcasecmp(enc, "quoted-printable") == 0) {
_body = (char *)malloc(_body_len + 20);
_must_free_body = DTM_TRUE;
int size = _body_decoded_len = 0;
RFCMIME::readQPrint(_body, size, _body_text, _body_len);
_body_decoded_len = size;
// Changed this temporarily until after release. We really should not
// be null terminating these buffers.
(_body)[_body_decoded_len] = 0;
}
else {
// Default case is no transfer encoding applies (7bit==8bit==binary)
_body = (char *)_body_text;
_must_free_body = DTM_FALSE;
_body_decoded_len = _body_len;
}
}
else {
// Default case is no transfer encoding applies.
error.clear();
_body = (char *)_body_text;
_must_free_body = DTM_FALSE;
_body_decoded_len = _body_len;
}
// For CHARSET
// Get charset from content-type field
char *ret = NULL;
value.clear();
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
if (error.isNotSet()) {
cs = csFromContentType(value);
if ( cs == NULL ) {
// Random allocation for cs
cs = (char *)calloc(128, sizeof(char));
DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
setlocale(LC_CTYPE, NULL),
NULL,
NULL,
&ret);
strcpy(cs, "DEFAULT");
strcat(cs, ".");
strcat(cs, ret);
}
} else { // No Content-Type
// We'll be flexible here. If Content-Type header is missing, we'll
// still try to convert from the locale specific default codeset.
error.clear();
// Random allocation for cs
cs = (char *)calloc(128, sizeof(char));
DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
setlocale(LC_CTYPE, NULL),
NULL,
NULL,
&ret);
strcpy(cs, "DEFAULT");
strcat(cs, ".");
strcat(cs, ret);
}
// Handle ISO-2022-INT, RFC approved, or private encoding names
if ( strcasecmp(cs, "ISO-2022-INT-1") == 0 ) {
// Need to obtain charset from encoding
} // RFC approved and private names are not treated differently.
// Get iconv name from charset - this is the "from" name.
from_cs = NULL;
from_cs = csToConvName(cs);
// Get current locale's iconv name - this is the "to" name.
to_cs = NULL;
to_cs = locToConvName();
if ( from_cs && to_cs ) {
if ( strcasecmp(from_cs, to_cs) != 0 ) {
unsigned long tmp_len = (unsigned long) _body_decoded_len;
if (csConvert(&_body, tmp_len, (int)_must_free_body, from_cs, to_cs)) {
_must_free_body = DTM_TRUE;
_body_decoded_len = (int) tmp_len;
}
}
}
if ( cs )
free ( cs );
if ( from_cs )
free( from_cs );
if ( to_cs )
free ( to_cs );
if ( ret )
free( ret );
// End of For CHARSET
// Clear the error condition before proceeding. This is done
// because functions that take a DtMailEnv object as a parameter
// expect it to be cleared. (Already cleared above)
// error.clear();
// If the body is text/enriched, convert it to text/plain
// At some point the front end should be able to handle this via
// data typing and do an 'intelligent' conversion, in which
// case this code can be removed
//
value.clear();
if (_body_env) {
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
}
if (_body_env && !error.isSet() &&
((strncasecmp(*(value[0]), "text/enriched", 13) == 0)
|| (strncasecmp(*(value[0]), "text/richtext", 13) == 0))) {
char *new_body = (char *)malloc((unsigned)(_body_len*2));
int size = 0;
RFCMIME::readTextEnriched(new_body, size, _body, _body_decoded_len);
new_body = (char *)realloc(new_body, size+2);
if (_must_free_body == DTM_TRUE)
free(_body);
_must_free_body = DTM_TRUE;
_body_decoded_len = size;
_body = new_body;
// Changed this temporarily until after release. We really should not
// be null terminating these buffers.
(_body)[_body_decoded_len] = 0;
}
error.clear();
return;
}
// NOTES ON HANDLING OF "FILE NAMES" FOR BODY PARTS IN MIME COMPLIANT ENTITIES:
// (see full description in evaluation for bug 1189035)
//
// The ability to provide a "file name" for a body part in a MIME compliant
// entity is partially addressed in RFC 1341 [MIME: Multipurpose Internet Mail
// Extentions] and RFC 1521 [which obsoleted RFC 1341].
//
// RFC 1341 proposed a solution to the file name problem (Content-Type:
// type; name=name); RFC 1521 subsequently depreciated this solution in
// favor of a to-be-defined future specification of "Content-Disposition".
//
// In essence there is an anticipation that "Content-Disposition" will
// be defined in a future RFC such that the notion of a "file name" may
// be given to a body part of a MIME compliant entity.
//
// OpenWindows mailtool currently recognizes "Content-Description" on MIME
// compliant entities and uses that information as the "file name" for
// an attachment (as per a loose interpretation of RFC 1521).
//
// CDE DtMail currently sends out and recognizes "X-Content-Name" on MIME
// compliant entities and uses that information as the "file name" for an
// attachment. This is essentially a non-standard header field as per RFC
// 1521:
//
// "X-" fields may be created for experimental or private purposes,
// with the recognition that the information they contain may be
// lost at some gateways.
//
// Since OpenWindows mailtool does not understand "X-Content-Name", any
// body part in e-mail originating from CDE DtMail does not appear to
// have a file name when read by mailtool.
//
// Given these facts:
//
// . OpenWindows mailtool cannot be changed until at least the Solaris
// 2.5 release (if at all).
//
// . OpenWindows mailtool is recognizing a valid MIME header field
// which is essentially "free form" in nature.
//
// . CDE DtMail is currently using an experimental or private field
// which is not part of the standard and is not guaranteed to survive
// transport across gateways.
//
// . There is no officially proscribed method for providing the "file
// name" of a body part in a MIME compliant entity in RFC 1521.
//
// The reasonable approach to take to solve this problem is:
//
// 1. Have DtMail use "Content-Description" to transmit the "file name"
// for a body part - this achieves compatibility with mailtool.
//
// 2. Have DtMail also continue to use "X-Content-Name" to transmit the
// "file name" - this maintains compatibility with previous versions
// of DtMail which only recognize this header.
//
// 3. Have Dtmail recognize both "Content-Description" and "X-Content-Name"
// as specifying the "file name" for a body part. In the case that both
// fields are present, "Content-Description" takes precedence over
// "X-Content-Name".
//
// 4. When "Content-Disposition" is properly defined and included as part
// of an updated MIME specification, revisit this issue.
//
//
// So, since dtmail currently *ignores* the "Content-Description" field,
// we overload the "getNameHeaderVal" function to use "Content-Description"
// first, then the older unofficial experimental "X-Content-Name". If
// and when Content-Disposition takes hold, it will have to override
// Content-Description when both are present.
//
//
// March 25, 1997
// The Content-Disposition field has been designated as the primary
// header field for transmitting file names. See RFC 1806. Therefore
// the algorithm has bee updated as follows.
//
// 1. DtMail checks the following headers for the "filename" for a body part:
// o The "filename" parameter of the "Content-Disposition" header field.
// o The contents of the "Content-Description" header field.
// o The "name" parameter of the "Content-Type" header field.
// o The contents of the "Content-Name" header field.
// o The contents of the "X-Content-Name" header field.
//
// 2. DtMail uses the following fields to specify the "filename" for a body
// part in outgoing mail:
// o The "filename" parameter of the "Content-Disposition" header field.
// o The contents of the "Content-Description" header field.
//
char *
MIMEBodyPart::getDescription(DtMailEnv &)
{
// Dont have this return anything without checking
// ramifications with getNameHeaderValue
// No need to clear error object here because we assume it has already
// been cleared by the caller and nothing has touched it in this method.
// error.clear();
return(NULL);
}
char *
MIMEBodyPart::getNameHeaderVal(DtMailEnv & error)
{
DtMailValueSeq value;
if (_body_env == NULL) {
// No need to clear the error object...it is unchanged from the
// state we received it in.
//error.clear();
return(NULL);
}
// The current standard seems to be to use the "Content-Disposition"
// header as the primary mechanism for transmitting file names.
//
_body_env->getHeader(error, "Content-Disposition", DTM_FALSE, value);
if (error.isNotSet()) {
char *param = parameterValue(value, "filename", DTM_FALSE);
if (NULL != param)
return strdup(param);
}
error.clear();
// In keeping with the current undefined nature of
// file names for body parts in RFC 1521, and to be
// compatible with OpenWindows mailtool, the first
// overriding "name" comes from "Content-Description"
//
_body_env->getHeader(error, "Content-Description", DTM_FALSE, value);
if (error.isNotSet()) {
return(strdup(*(value[0])));
}
error.clear();
// For backward compatibility with older mail agents, check the "Name"
// parameter in the "Content-Type" header.
//
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
if (error.isNotSet()) {
char *param = parameterValue(value, "name", DTM_FALSE);
if (NULL != param)
return strdup(param);
}
error.clear();
// Next we remain compatible with previous versions
// of DtMail that used "X-Content-Name" instead of
// "Content-Description" for the file name of a
// body part (1-27-95)
//
_body_env->getHeader(error, "X-Content-Name",
DTM_FALSE, value);
if (error.isNotSet()) {
return(strdup(*(value[0])));
}
error.clear();
// This code was in dtmail on 1-27-95 and even though
// that version of dtmail did not send out "Content-Name"
// (which is not part of RFC 1341 or 1521) it doesnt
// hurt to recognize it if its the only header there.
//
_body_env->getHeader(error, "Content-Name",
DTM_FALSE, value);
if (error.isNotSet()) {
return(strdup(*(value[0])));
}
error.clear(); // NULL is the real error here.
// No name for this body part
//
return(NULL);
}
char *
MIMEBodyPart::getName(DtMailEnv & error)
{
char * h_name = getNameHeaderVal(error);
// don't care about the error returned by getNameHeaderVal()
error.clear();
if (h_name) {
return(h_name);
}
if (!_body_type) {
getDtType(error);
if (error.isSet()) {
error.clear();
return(strdup("Attachment"));
}
}
char * pat = DtDtsDataTypeToAttributeValue(_body_type,
"NAME_TEMPLATE",
NULL);
if (pat) {
int max_len = strlen(pat) + 20;
char * name = (char*) malloc((size_t) max_len);
sprintf(name, pat, "Attachment");
DtDtsFreeAttributeValue(pat);
return(name);
}
return(strdup("Attachment"));
}
void
MIMEBodyPart::setName(DtMailEnv & error, const char * name)
{
if (_body_env) {
_body_env->setHeader(error, "X-Content-Name", DTM_TRUE, name);
}
}
unsigned long
MIMEBodyPart::getLength(DtMailEnv & error)
{
MutexLock lock_scope(_obj_mutex);
loadBody(error);
if (error.isSet()) {
// propogate the error back to the caller.
return (0);
}
// We have to treat external bodies differently. The headers on these
// parts contain useful information to the client.
//
const char * mime_type;
DtMailValueSeq value;
if (_body_env) {
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
}
if (_body_env && !error.isSet()) {
mime_type = *(value[0]);
}
else {
// only need to clear the error object if getHeader returned
// an error condition. We don't want to propogate the error
// back up the calling sequence.
error.clear();
mime_type = "text/plain";
}
unsigned long len;
if (strncasecmp(mime_type, "message/external-body", 21) == 0) {
const char * contents = _body_start;
for (;contents < (_body_text + _body_len); contents++) {
if (*contents == '\n') {
break;
}
}
contents += 1;
len = _body_len + (_body_text - contents);
}
else {
len = _body_decoded_len;
}
return(len);
}
int
MIMEBodyPart::rfcSize(const char *, DtMailBoolean &)
{
return(0);
}
char *
MIMEBodyPart::writeBodyParts(char * buf)
{
return(buf);
}
const void *
MIMEBodyPart::getBody(DtMailEnv & error)
{
// No need to clear the error here, should be cleared by the object
// that instantiated it.
// error.clear();
if (!_body) {
loadBody(error);
// loadBody currently (version 1.31) clears the error before
// returning, so the following check is not needed. We'll
// leave it alone on the chance that loadBody() will someday
// return an error condition.
if (error.isSet()) {
return(NULL);
}
}
// We have to treat external bodies differently. The headers on these
// parts contain useful information to the client.
//
const char * mime_type;
DtMailValueSeq value;
if (_body_env) {
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
}
if (_body_env && !error.isSet()) {
// Handle "Content-Type: text" problem with /usr/lib/mail.local
//
if (strcasecmp(*(value[0]), "text")==0)
mime_type = "text/plain";
else
mime_type = *(value[0]);
}
else {
error.clear();
mime_type = "text/plain";
}
const char * contents;
if (strncasecmp(mime_type, "message/external-body", 21) == 0) {
contents = _body_start;
for (;contents < (_body_text + _body_len); contents++) {
if (*contents == '\n') {
break;
}
}
contents += 1;
}
else {
contents = _body;
}
return(contents);
}
// For CHARSET
// Given the Content-Type field, extract the charset value.
// Returns one of the following:
// 1) charset value,
// Caller MUST FREE this return value.
// 2) NULL if charset is not specified but Content-Type specifies
// text/plain data. If this routine returns NULL, that means
// charset is not specified but the data is text/plain. Therefore,
// (as in the case of MIMEBodyPart::loadBody) caller
// will call csToConvName("DEFAULT.<locale>") and csToConvName will return
// a default iconv conversion name for the current locale.
// This is the case because some (old) mailers do not set the charset value
// but encodes the message in a "popular" codeset. The default conversion
// name for a particular locale assumes the "popular" codeset used.
// 3) non NULL but invalid charset value if Content-Type does not specify
// text/plain data. Caller MUST FREE this return value.
char *
MIMEBodyPart::csFromContentType(DtMailValueSeq &value)
{
char *cs_str = NULL;
char *val_ptr = NULL;
int quoted = 0;
// value[0] should be valid else error would have occurred before
// this routine ever gets called. And value index is 0 because
// previous value stored should have been removed.
const char *val = *(value[0]);
// Check to see if Content-Type field specifies text/plain data.
// If so, look for charset value
// else, returns value in Content-Type field
if ( strstr(val, "text") == NULL ) {
if ( strstr(val, "TEXT") == NULL ) {
cs_str = strdup(val);
return cs_str;
}
}
// Get charset value
val_ptr = strstr(val, "charset=");
if ( val_ptr == NULL ) {
val_ptr = strstr(val, "CHARSET=");
}
if ( val_ptr == NULL ) {
return NULL;
}
val_ptr = val_ptr+8;
// Check if charset value is quoted
if ( val_ptr[0] == '"' ) {
val_ptr++;
quoted = 1;
}
if ( quoted ) {
cs_str = strdup(strtok(val_ptr, "\""));
} else {
cs_str = (char *)calloc(strlen(val_ptr)+1, sizeof(char));
sscanf(val_ptr, "%s", cs_str);
}
return cs_str;
}
// End of For CHARSET
char *
MIMEBodyPart::parameterValue(
DtMailValueSeq &value,
const char * parameter,
DtMailBoolean isCaseSensitive)
{
char *lasts=NULL;
char *ptok, *vtok;
char *parm, *val;
int rtn = 0;
val = strdup(*(value[0]));
vtok = strrchr(val, ';');
while (NULL != vtok)
{
*vtok = '\0';
vtok++;
while(isspace(*vtok))
vtok++;
if (isCaseSensitive)
rtn = strncmp(vtok, parameter, sizeof(parameter));
else
rtn = strncasecmp(vtok, parameter, sizeof(parameter));
if (0 == rtn)
{
ptok = strrchr(vtok, '=');
if (NULL == ptok)
{
free(val);
return NULL;
}
ptok++;
if (*ptok == '"' )
{
ptok++;
parm = strdup(strtok(ptok, (const char *) "\""));
}
else
parm = strdup(ptok);
free(val);
return parm;
}
vtok = strrchr(val, ';');
}
free(val);
return NULL;
}

View File

@@ -0,0 +1,538 @@
/*
*+SNOTICE
*
*
* $TOG: MIMEPartial.C /main/6 1998/04/06 13:27:21 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
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <DtMail/DtMail.hh>
#include "RFCImpl.hh"
#include "str_utils.h"
static const char * contentType = "content-type";
static const char * partial = "message/partial";
//
// Get the named header out of out of the message.
//
static char *
getNamedHeader(DtMailEnv & error,
const char * headerName,
RFCMessage * message)
{
DtMailValueSeq value;
char * results = NULL;
RFCEnvelope * env = (RFCEnvelope *)message->getEnvelope(error);
if (error.isNotSet()) {
env->getHeader(error, headerName, DTM_FALSE, value);
if (error.isNotSet()) {
results = strdup(*(value[0]));
}
}
return(results);
}
//
// Return the value to the right of the '=' in the named string.
// As an INT.
//
static unsigned int
getNamedValueInt(const char *string, const char *name)
{
int stringLen = strlen(string);
int nameLen = strlen(name);
int results = 0;
register unsigned int offset;
for (offset = 0; offset < stringLen - nameLen; offset++) {
if (strncasecmp(&string[offset], name, nameLen) == 0) {
if (string[offset + nameLen] == '=') {
results = atoi(&string[offset + nameLen + 1]);
break;
}
}
}
return(results);
}
//
// Return the value to the right of the '=' in the named string.
// As a const char *.
//
static const char *
getNamedValueString(const char *string, const char *name)
{
int stringLen = strlen(string);
int nameLen = strlen(name);
const char * results;
char * stringEnd;
register unsigned int offset;
for (offset = 0; offset < stringLen - nameLen; offset++) {
if (strncasecmp(&string[offset], name, nameLen) == 0) {
if (string[offset + nameLen] == '=') {
//
// We only want what is inside the '"' quotes.
//
results = strdup(&string[offset + nameLen + 1]);
if (*results == '"') {
results++;
stringEnd = strchr(results, '"');
if (stringEnd != NULL) {
*stringEnd = '\0';
}
}
break;
}
}
}
return(results);
}
DtMailBoolean
RFCMailBox::_isPartial(DtMailEnv & error,
RFCMessage * message)
{
DtMailBoolean results = DTM_FALSE;
RFCMessage * messageArray = NULL;
char * type;
if (message != NULL
&& (type = getNamedHeader(error, contentType, message)) != NULL) {
if (error.isNotSet()) {
if (strncasecmp(type, partial, 15) == 0) {
//
// Add ourselves to the array.
//
_partialData * newData = new _partialData;
newData->id = getNamedValueString(type, "id");
newData->number = getNamedValueInt(type, "number");
newData->total = getNamedValueInt(type, "total");
newData->msg = message;
//
// It has to have a number and an ID or it is not a valid
// message/partial and there would be no way to put it
// back together. Total is optional except for the last part
// where it is required.
//
if (newData->number > 0 && newData->id != NULL) {
_partialList = (_partialData **)realloc(_partialList,
sizeof(_partialData *)
*(_partialListCount+1));
if (_partialList != NULL) {
_partialList[_partialListCount] = newData;
_partialListCount++;
results = DTM_TRUE;
}
} else {
delete newData; // Not a valid message/partial.
}
}
free(type);
}
else {
error.clear();
}
}
return(results);
}
RFCMessage *
RFCMailBox::_assemblePartial(DtMailEnv & error,
RFCMessage * message)
{
register unsigned int offset;
unsigned int totalParts = 0;
RFCMessage * msg = message;
_partialData * data = NULL;
if (message != NULL) {
char * type = getNamedHeader(error, contentType, message);
//
// Find ourselfs in the list.
//
for (offset = 0 ; offset < _partialListCount ; offset++) {
if (_partialList[offset]->msg == message) {
data = _partialList[offset];
break;
}
}
//
// Now look for the total for this message-id.
//
if (data != NULL) {
for (offset = 0 ; offset < _partialListCount ; offset++) {
if (strcasecmp(_partialList[offset]->id, data->id) == 0) {
totalParts = _partialList[offset]->total;
if (totalParts > 0) {
break;
}
}
}
}
//
// If we know how many parts we are to process - start looking.
//
// If we do not know the total, then we know that not all of the
// parts have arrived. (the last partial message must have
// the total in it).
//
if (totalParts > 0) {
char * dummy = (char *) calloc(1, totalParts * sizeof(RFCMessage *));
RFCMessage ** messages = (RFCMessage **)dummy;
//
// Now we go thru the list again, this time looking for
// all of the parts. Place them in the correct order
// in the list.
//
for (offset = 0 ; offset < _partialListCount ; offset++) {
if (strcasecmp(_partialList[offset]->id, data->id) == 0) {
messages[_partialList[offset]->number - 1]
= _partialList[offset]->msg;
}
}
//
// If all of the parts are IN, then assemble them into
// a new message.
//
int totalSize = 0; // Total size of all of the parts.
char *messageLength;
for (offset = 0 ; offset < totalParts ; offset++) {
if (messages[offset] == NULL) {
break; // Found a missing part, do not assemble.
}
messageLength = getNamedHeader(error, "Content-Length",
messages[offset]);
if (messageLength == NULL || error.isSet()) {
break; // No way to assemble if we do not know the size.
}
totalSize += atoi(messageLength); // Bump the total size.
free(messageLength);
}
if (offset == totalParts) { // Did we find all of the parts ?
//
// From RFC 1521, section 7.3.2:
//
// When generating and reassembling the parts of a message/partial
// message, the headers of the encapsulated message must be merged with
// the headers of the enclosing entities. In this process the
// following rules must be observed:
//
// (1) All of the header fields from the initial enclosing entity
// (part one), except those that start with "Content-" and the
// specific header fields "Message-ID", "Encrypted", and
// "MIME-Version", must be copied, in order, to the new message.
//
// (2) Only those header fields in the enclosed message which start
// with "Content-" and "Message-ID", "Encrypted", and "MIME-Version"
// must be appended, in order, to the header fields of the new
// message. Any header fields in the enclosed message which do not
// start with "Content-" (except for "Message-ID", "Encrypted", and
// "MIME-Version") will be ignored.
//
// (3) All of the header fields from the second and any subsequent
// messages will be ignored.
//
// Pick 10% more space for the headers, or a random size for
// the new message.
//
totalSize = (totalSize > 10*1024) ? (int) (totalSize*1.1) : (20*1024);
char * newMessage = (char *)malloc(totalSize);
newMessage[0] = '\0';
//
// Copy over all of the headers from the outer 1st message
// except the ones that we are not suppost to copy.
//
RFCEnvelope * env
= (RFCEnvelope *)messages[0]->getEnvelope(error);
DtMailHeaderHandle headerHandle;
DtMailValueSeq headerValue;
char * headerName;
const char * unixFromLine = NULL;
unsigned int duplicateCount;
int fromLen;
int headerNumber = 0;
register unsigned int dupOffset;
if (error.isNotSet()) {
//
// Get the first header.
//
headerHandle = env->getFirstHeader(error, &headerName, headerValue);
unixFromLine = env->unixFrom(error, fromLen);
if (unixFromLine != NULL) {
strncat(newMessage, unixFromLine, fromLen);
newMessage[fromLen] = '\0';
}
if (error.isNotSet()) {
//
// Keep geting more (all) of the headers.
//
do {
if ((strncasecmp(headerName, "Content-", 8) != 0)
&& (strcasecmp(headerName, "Message-ID") != 0)
&& (strcasecmp(headerName, "Encrypted") != 0)
&& (strcasecmp(headerName, "MIME-Version") != 0)
&& (strcasecmp(headerName, "Status") != 0)) {
//
// If there is more than one value for each type,
// then get all of the values.
//
duplicateCount = headerValue.length();
for (dupOffset=0; dupOffset < duplicateCount; dupOffset++ ) {
//
// Skip if the first line is a from.
//
if (unixFromLine != NULL && headerNumber == 0) {
continue;
}
strcat(newMessage, headerName);
strcat(newMessage, ": ");
strcat(newMessage, *(headerValue[dupOffset]));
strcat(newMessage, "\n");
}
}
//
// Clear out the current one, so that getNextHeader
// does not append.
//
headerValue.clear();
headerHandle = env->getNextHeader(error,
headerHandle,
&headerName,
headerValue);
headerNumber++;
//
// getNextHeader returns NULL where there are no more.
//
} while(error.isNotSet() && headerHandle != NULL);
//
headerValue.clear();
//
// Now add in the headers from the imbeded message in part 1.
// To do this we need to convert the message to an envelope
// and then get the headers from that.
//
// We then delete the envelope as it is not longer needed.
//
RFCBodyPart * bp
= (RFCBodyPart *)messages[0]->getFirstBodyPart(error);
unsigned long length;
int embHeader1StLen;
const void * contents;
const char * embHeader1St;
char * endHeader;
//
// Get the body part of the first message. It contains
// the headers that we need to merge with.
//
if (error.isNotSet()) {
bp->getContents(error, &contents, &length,
NULL, NULL, NULL, NULL);
if (error.isNotSet()) {
//
// Turn the 1st messages body into an envelope.
//
// Headers end with two new lines.
//
embHeader1StLen = (int) length;
embHeader1St = (const char *)contents;
endHeader = strstr((const char *)contents, "\n\n");
if (endHeader != NULL) {
RFCEnvelope embEnv(error,
(DtMail::Message *)NULL,
(const char *)contents,
(int)((unsigned long)endHeader
- (unsigned long)contents));
if (error.isNotSet()) {
//
// Get the first header from the embeded message.
//
headerHandle = embEnv.getFirstHeader(error,
&headerName,
headerValue);
if (error.isNotSet()) {
//
// Keep geting more (all) of the headers.
//
do {
if ((strncasecmp(headerName, "Content-", 8) == 0)
|| (strcasecmp(headerName, "Message-ID") == 0)
|| (strcasecmp(headerName, "Encrypted") == 0)
|| (strcasecmp(headerName, "MIME-Version") == 0)) {
//
// If there is more than one value for each type,
// then get all of the values.
//
duplicateCount = headerValue.length();
for (dupOffset=0
; dupOffset < duplicateCount
; dupOffset++ ) {
strcat(newMessage, headerName);
strcat(newMessage, ": ");
strcat(newMessage, *(headerValue[dupOffset]));
strcat(newMessage, "\n");
}
}
//
// Clear out the current one, so that getNextHeader
// does not append.
//
headerValue.clear();
headerHandle = embEnv.getNextHeader(error,
headerHandle,
&headerName,
headerValue);
//
// getNextHeader returns NULL where there are no more.
//
} while(error.isNotSet() && headerHandle != NULL);
//
headerValue.clear();
strcat(newMessage, "\n"); // End of headers.
}
}
}
}
if (error.isNotSet()) {
//
// Now add the data parts into the one part.
//
size_t messageSize = strlen(newMessage);
length = embHeader1StLen - (&endHeader[2] - embHeader1St);
strncat(newMessage,
(const char *)&endHeader[2], // After \n\n.
(size_t) length);
messageSize += (size_t) length;
newMessage[messageSize] = '\0';
//
// Add in the 2nd -> Nth body parts.
//
for (offset = 1; offset < totalParts ; offset++) {
bp =(RFCBodyPart *)messages[offset]->getFirstBodyPart(error);
if (error.isSet()) {
break;
}
bp->getContents(error, &contents, &length,
NULL, NULL, NULL, NULL);
if (error.isSet()) {
break;
}
strncat(newMessage, (const char *)contents, (size_t) length);
messageSize += (size_t) length;
newMessage[messageSize] = '\0';
}
//
// Make the new Message, we strdup() so we only use
// as much space as needed (and free() old).
//
const char *msgResults = strdup(newMessage);
free(newMessage);
newMessage = (char *)msgResults;
msg = new RFCMessage(error, this,
(const char **)&msgResults,
(const char *)newMessage + messageSize);
for (offset = 0; offset < totalParts ; offset++) {
//
// Delete the old parts.
//
messages[offset]->setFlag(error, DtMailMessageDeletePending);
//
// TODO - CALL EXPUNGE to get rid of the message that
// we just marked for delete !!!!!
//
messages[offset] = NULL;
}
}
}
}
}
}
if (messages != NULL) {
free(messages);
}
}
free(type);
}
return(msg); // This could be the new or the original message.
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,224 @@
/*
*+SNOTICE
*
*
* $TOG: RFCFormat.C /main/11 1998/07/23 18:03:02 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
*/
#include <ctype.h>
#include <EUSCompat.h>
#include <DtMail/IO.hh>
#include "RFCFormat.hh"
#include "str_utils.h"
#include <time.h>
RFCFormat::RFCFormat(DtMail::Session * session)
{
_session = session;
_is_write_bcc = DTM_FALSE;
}
RFCFormat::~RFCFormat(void)
{
}
void
RFCFormat::msgToBuffer(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_content_length,
DtMailBoolean include_unix_from,
DtMailBoolean,
Buffer & headers,
Buffer & body)
{
error.clear();
_use_cr = DTM_TRUE;
if (include_content_length || include_unix_from) {
_use_cr = DTM_FALSE;
}
// We will format the bodies first, then the headers. The
// reason we do this is that the result of formatting the body
// is required for the headers. The content-type, content-length,
// and other content based headers need to be computed before
// being written.
//
char * extra_headers = NULL;
formatBodies(error, msg, include_content_length, &extra_headers, body);
if (error.isSet()) {
return;
}
formatHeaders(error, msg, include_unix_from, extra_headers, headers);
free(extra_headers);
return;
}
void
RFCFormat::writeHeaders(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_unix_from,
const char * extra_headers,
const char ** suppress_headers,
Buffer & buf)
{
error.clear();
// First we copy each header from the message to the
// buffer. The headers may need encoding to put them away, so
// we will apply RFC1522 if necessary.
//
DtMailHeaderHandle hnd;
DtMail::Envelope * env = msg.getEnvelope(error);
if (error.isSet()) {
return;
}
char * name = NULL;
DtMailValueSeq value;
hnd = env->getFirstHeader(error, &name, value);
if (!hnd || error.isSet()) {
return;
}
if (include_unix_from &&
(error.isSet() || strcmp(name, "From") != 0)) {
// We require a Unix from line, and we don't have one.
// we will make one up using the sender, and the current
// date.
//
char *unix_from = new char[100];
strcpy(unix_from, "From ");
DtMailValueSeq sender;
env->getHeader(error, DtMailMessageSender, DTM_TRUE, sender);
if (error.isSet()) {
// We no longer know who this is really from.
//
strcat(unix_from, "nobody@nowhere");
}
else {
DtMailAddressSeq * addrSeq = sender[0]->toAddress();
strcat(unix_from, (*addrSeq)[0]->dtm_address);
delete addrSeq;
}
error.clear();
time_t now = time(NULL);
char time_format[30];
SafeCtime(&now, time_format, sizeof(time_format));
strcat(unix_from, " ");
strcat(unix_from, time_format);
buf.appendData(unix_from, strlen(unix_from));
delete [] unix_from;
}
else {
// Put out any header, except Unix From line
//
if (strcmp(name, "From") == 0) {
value.clear();
free(name);
hnd = env->getNextHeader(error, hnd, &name, value);
}
}
for (; // First time is determined above.
hnd && !error.isSet();
value.clear(), hnd = env->getNextHeader(error, hnd, &name, value)) {
for (const char ** hdr = suppress_headers; *hdr; hdr++) {
if (strcasecmp(name, *hdr) == 0)
break;
}
//add _is_write_bcc for fixing aix defect 177096
if (*hdr || strcasecmp(name, "bcc") == 0 && !_is_write_bcc ) {
free(name);
continue; // We will generate these headers.
}
int name_len = strlen(name);
for (int val = 0; val < value.length(); val++) {
//
// If the value is null or empty do not emit this field
for (const char *valPtr = *(value[val]);
*valPtr && (isspace((unsigned char)*valPtr));
valPtr++)
{}
if (!*valPtr)
continue;
buf.appendData(name, name_len);
buf.appendData(": ", 2);
rfc1522cpy(buf, *(value[val]));
}
free(name);
}
error.clear();
buf.appendData(extra_headers, strlen(extra_headers));
// Add new line that terminates the headers.
//
crlf(buf);
}
void
RFCFormat::rfc1522cpy(Buffer & buf, const char * value)
{
buf.appendData(value, strlen(value));
crlf(buf);
}
void
RFCFormat::getCharSet(char * charset)
{
char *mimeCS = NULL;
mimeCS = _session->targetTagName();
if (mimeCS) {
strcpy(charset, mimeCS);
free(mimeCS);
} else {
strcpy(charset, "us-ascii"); /* default MIME codeset */
}
}
void
RFCFormat::getCharSet(char * charset, char *special)
{
char *mimeCS = NULL;
mimeCS = _session->targetTagName(special);
if (mimeCS) {
strcpy(charset, mimeCS);
free(mimeCS);
} else {
strcpy(charset, "us-ascii"); /* default MIME codeset */
}
}

View File

@@ -0,0 +1,98 @@
/*
*+SNOTICE
*
*
* $XConsortium: RFCFormat.hh /main/4 1996/04/02 16:20:29 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
#ifndef _RFCFORMAT_HH
#define _RFCFORMAT_HH
#include <DtMail/DtMail.hh>
#include <DtMail/Buffer.hh>
class RFCFormat : public DtCPlusPlusAllocator {
public:
RFCFormat(DtMail::Session * session);
~RFCFormat(void);
virtual void msgToBuffer(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_content_length,
DtMailBoolean include_unix_from,
DtMailBoolean process_ignores,
Buffer & headers,
Buffer & body);
//call setIsWriteBcc when log message to files so that the BCC
// field will log to those files.
void setIsWriteBcc() { _is_write_bcc = DTM_TRUE;}
void unsetIsWriteBcc() { _is_write_bcc = DTM_FALSE;}
DtMailBoolean getIsWriteBcc() { return _is_write_bcc;}
protected:
DtMail::Session *_session;
DtMailBoolean _use_cr;
DtMailBoolean _is_write_bcc; // if log to file: Yes
// send out: No (RFC 822)
virtual void formatBodies(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_content_length,
char ** extra_headers,
Buffer & buf) = 0;
virtual void formatHeaders(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_unix_from,
const char * extra_headers,
Buffer & buf) = 0;
void writeHeaders(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_unix_from,
const char * extra_headers,
const char ** suppress_headers,
Buffer & buf);
virtual void rfc1522cpy(Buffer & buf, const char * value);
void getCharSet(char * charset);
void getCharSet(char * charset, char *special);
int OpenLcxDb(void);
void DtXlateStdToOpLocale(char *op, char *std, char *dflt, char **ret);
void DtXlateOpToStdLocale(char *op, char *opLoc, char **retLoc, char **ret_retLang, char **retSet);
char *targetTagName();
void crlf(Buffer & buf)
{
const char * term = (_use_cr ? "\r\n" : "\n");
int len = (_use_cr ? 2 : 1);
buf.appendData(term, len);
}
};
inline void
appendString(Buffer & buf, const char * str)
{
buf.appendData(str, strlen(str));
}
#endif

View File

@@ -0,0 +1,895 @@
/*
*+SNOTICE
*
*
* $TOG: RFCImpl.hh /main/22 1998/10/01 17:28:08 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
#ifndef _RFCIMPL_HH
#define _RFCIMPL_HH
#include <DtMail/Buffer.hh>
#include <DtMail/DtMail.hh>
#include <DtMail/DtMailServer.hh>
#include <DtMail/FileShare.hh>
#include <DtMail/Threads.hh>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#if defined(NEED_MMAP_WRAPPER)
extern "C" {
#endif
#include <sys/mman.h>
#if defined(NEED_MMAP_WRAPPER)
}
#endif
// Structs needed to exec sendmail
typedef struct waitentry {
struct waitentry * next;
int pid;
void * data;
SubProcessFinishedProc * proc;
} waitentry_t;
typedef struct pipedata {
int pid;
int status;
} pipedata_t;
typedef enum {
DTMBX_LONGLOCK_FAILED_CANCEL, // failed to obtain lock, cancel operation
DTMBX_LONGLOCK_FAILED_READONLY, // failed to obtain lock, open read only
DTMBX_LONGLOCK_FAILED_READWRITE, // failed to obtain lock,
// open read write [user locking override]
DTMBX_LONGLOCK_SUCCESSFUL // obtained the lock
} DTMBX_LONGLOCK;
class RFCMailBox;
class RFCBodyPart;
class RFCMessage : public DtMail::Message {
public:
RFCMessage(DtMailEnv & error,
DtMail::MailBox * parent,
const char ** start, // Also returns the end of the message.
const char * end_of_file);
RFCMessage(DtMailEnv & error,
const char * alt_start,
const char * alt_end);
RFCMessage(DtMailEnv & error,
DtMail::Session * session,
DtMailObjectSpace space,
void * arg,
DtMailCallback cb,
void * client_data);
virtual ~RFCMessage(void);
virtual DtMail::Envelope * getEnvelope(DtMailEnv &);
// This should only be used when you REALLY need to know
// how many body parts are present before actually traversing
// the body parts (i.e. like when writing a MIME format message).
virtual int getBodyCount(DtMailEnv &);
virtual DtMail::BodyPart * getFirstBodyPart(DtMailEnv &);
virtual DtMail::BodyPart * getNextBodyPart(DtMailEnv &,
DtMail::BodyPart *);
virtual DtMail::BodyPart * newBodyPart(DtMailEnv &,
DtMail::BodyPart *);
#ifdef DEAD_WOOD
virtual void newBodyPartOrder(DtMailEnv &,
DtMail::BodyPart *,
const int) { };
#endif /* DEAD_WOOD */
virtual void setFlag(DtMailEnv &,
const DtMailMessageState);
virtual void resetFlag(DtMailEnv &,
const DtMailMessageState);
virtual DtMailBoolean flagIsSet(DtMailEnv &,
const DtMailMessageState);
virtual time_t getDeleteTime(DtMailEnv &);
virtual void toBuffer(DtMailEnv & error, DtMailBuffer &);
virtual const char * impl(DtMailEnv &);
// Methods following this point are specific to RFCMessage.
//
void markDirty(const int delta);
void fixMessageLocation(char ** msgHeaderStart, long & msgHeaderLen,
char ** msgBodyStart, long &msgBodyLen,
int & msgTemporary, long & msgBodyOffset);
void unfixMessageLocation(char *msgStart, int msgTemporary);
void adjustMessageLocation(
char * oldStart,
char * newStart,
long newLength,
int msgTemporary,
long newBodyOffset);
void pinMessageDown(char ** msgHeaderStart, long & msgHeaderLen,
char ** msgBodyStart, long &msgBodyLen);
RFCMailBox * parent(void) { return (RFCMailBox *)_parent; }
protected:
unsigned long _object_signature;
const char * _msg_start;
const char * _msg_end;
const char * _body_start;
SafeScalar<int> _dirty;
DtMailBuffer *_msg_buf;
struct BodyPartCache : public DtCPlusPlusAllocator {
RFCBodyPart *body;
const char * body_start;
};
DtVirtArray<BodyPartCache *> _bp_cache;
// _alternativeMultipart -- does message contain alternative messages?
// If DTM_FALSE: this message does not contain alternative messages.
// .. can ignore: _alt_msg_cache, _alternativeValid
// If DTM_TRUE: this message does contain alternative messages.
// The body part cache is allocated; however, the pointers within
// the cache are copied from the latest valid alternative message
// within the alternative message cache, and so should not be
// deleted when a message is destroyed and this is true.
// The alternative message cache (_alt_msg_cache) contains one or
// more messages that map 1 to 1 with the corresponding alternative
// messages contained within the entire message.
//
DtMailBoolean _alternativeMultipart;
// _alternativeMessage -- is this message an alternative message?
// If DTM_FALSE: this is not an alternative message but rather a real
// message -- _msg_start, _msg_end, _body_start, etc. are valid.
// If DTM_TRUE: this message is an alternative message; _msg_start,
// _msg_end, _body_start, etc. demark the alternative message within
// the entire real message. The body part cache is fully allocated and
// represents all body parts contained within this alternative message.
//
DtMailBoolean _alternativeMessage;
// _alternativeValid -- is this alternative message part valid?
// If DTM_FALSE: this alternative cannot be displayed or otherwise
// acted upon on this system
// If DTM_TRUE: this alternative can be displayed or otherwise
// acted upon on this system
//
DtMailBoolean _alternativeValid;
// _alt_msg_cache is the "alternative message cache", an array of
// MIMEBodyParts an RFCMessages, which have _alternativeMessage
// set, and contain only those body parts that are associated with a
// single alternative message. There is one entry in the array for
// each alternative message within the entire message. Each alternative
// message will have _alternativeMessage == DTM_TRUE.
// This cache is present only if _alternativeMultipart == DTM_TRUE.
//
struct AlternativeMessageCache : public DtCPlusPlusAllocator {
RFCMessage * amc_msg; // -> RFCMessage for alternative
RFCBodyPart * amc_body; // -> MIMEBodyPart for alternative
const char * amc_body_start; // -> first byte of body
const char * amc_body_end; // -> last byte of body
};
DtVirtArray<AlternativeMessageCache *> _alt_msg_cache;
DtMail::BodyPart * bodyPart(DtMailEnv & error, const int slot);
int lookupByBody(DtMail::BodyPart *);
const char * parseMsg(DtMailEnv &, const char * end_of_file);
const char * findMsgEnd(DtMailEnv &, const char * end_of_file);
void parseBodies(DtMailEnv &);
void parseMIMEBodies(DtMailEnv &);
void parseMIMETextPlain(DtMailEnv &);
void parseMIMEMultipartSubtype(DtMailEnv &, const char * subtype);
void parseMIMEMessageSubtype(DtMailEnv &, const char * subtype);
void parseMIMEMessageExternalBody(DtMailEnv &);
void parseMIMEMultipartMixed(DtMailEnv &, const char * boundary);
void parseMIMEMultipartAlternative(DtMailEnv &, const char * boundary);
void parseV3Bodies(DtMailEnv &);
void writeMsg(char * buffer);
int sizeMIMEBodies(DtMailEnv &);
int sizeV3Bodies(DtMailEnv &);
char * extractBoundary(const char * content_type);
DtMailBoolean hasHeaders(const char * buf, const unsigned long size);
// This friend declaration is used temporarily by copyMsg to copy
// messages from RFC->RFC. A more general solution is needed for
// FCS.
friend class RFCMailBox;
};
class RFCEnvelope : public DtMail::Envelope {
public:
RFCEnvelope(DtMailEnv & error,
DtMail::Message * parent,
const char * start,
const int len);
virtual ~RFCEnvelope(void);
virtual DtMailHeaderHandle getFirstHeader(DtMailEnv &,
char ** name,
DtMailValueSeq & value);
virtual DtMailHeaderHandle getNextHeader(DtMailEnv &,
DtMailHeaderHandle last,
char ** name,
DtMailValueSeq & value);
virtual void getHeader(DtMailEnv &,
const char * name,
const DtMailBoolean abstract,
DtMailValueSeq & value);
virtual void setHeaderSeq(DtMailEnv &,
const char *,
const DtMailValueSeq &) {} ;
// The last parameter is left to the client to provide
// because it can not be done in a type safe manner.
//
virtual void setHeader(DtMailEnv &,
const char *,
const DtMailBoolean,
const char *);
virtual void removeHeader(DtMailEnv &,
const char *);
// Methods below this point are specific to RFCEnvelope.
//
int dirty(void) { return _dirty; }
void adjustHeaderLocation(char * headerStart, int headerLength);
char *writeHeaders(char *buf);
const char * headerLocation(void) { return _header_text; }
long headerLength(void) { return _header_len; }
const char * unixFrom(DtMailEnv &, int & length);
//
// fix for the defect 177527
// when a reply-to field is in a message headers, the reply-to is
// going to be displayed as the send in RMW's msg list scrolled window
// instead of the real sender. The following three public methods are
// going to access _use_reply_to.
//
void setUseReplyTo(void) { _use_reply_to = DTM_TRUE; }
void unsetUseReplyTo(void) { _use_reply_to = DTM_FALSE; }
DtMailBoolean getUseReplyTo(void) { return _use_reply_to; }
protected:
DtMailBoolean _use_reply_to;
unsigned long _object_signature;
SafeScalar<int> _dirty;
struct ParsedHeader : public DtCPlusPlusAllocator {
ParsedHeader(void);
~ParsedHeader(void);
const char *name_start;
int name_len;
const char *value_start;
int value_len;
int alloc_mask; // Tracks updates to value.
void * mutex;
};
const char * _header_text;
int _header_len;
DtVirtArray<ParsedHeader *> _parsed_headers;
void * _header_lock;
void getTransportHeader(DtMailEnv & error,
const char * name,
DtMailValueSeq & value);
DtMailBoolean matchName(const ParsedHeader &, const char *);
void parseUnixFrom(DtMailEnv &,
const ParsedHeader &,
DtMailValueSeq & value);
void parseUnixDate(DtMailEnv &,
const ParsedHeader &,
DtMailValueSeq & value);
void makeValue(DtMailEnv &,
const ParsedHeader &,
DtMailValueSeq & value);
void makeReply(DtMailEnv &,
const char * name,
DtMailValueSeq & value);
DtMailBoolean metooAddr(DtMailValueAddress & addr,
DtMailAddressSeq & alts,
DtMailBoolean allnet);
void parseHeaders(void);
int lookupHeader(const char * name, DtMailBoolean real_only = DTM_FALSE);
const char * mapName(const char * name);
};
class RFCBodyPart : public DtMail::BodyPart {
public:
RFCBodyPart(DtMailEnv &,
DtMail::Message * parent,
const char * start,
const int len,
RFCEnvelope * body_env);
virtual void lockContents(DtMailEnv &, const DtMailLock);
virtual void unlockContents(DtMailEnv &);
virtual void getContents(DtMailEnv &,
const void ** contents,
unsigned long * length,
char ** type,
char ** name,
int * mode,
char ** description);
virtual void setContents(DtMailEnv &,
const void * contents,
const unsigned long length,
const char * type,
const char * name,
const int mode,
const char * description);
virtual void setFlag(DtMailEnv &,
DtMailBodyPartState);
virtual void resetFlag(DtMailEnv &,
DtMailBodyPartState);
virtual DtMailBoolean flagIsSet(DtMailEnv &,
DtMailBodyPartState);
virtual time_t getDeleteTime(DtMailEnv &);
virtual void getHeader(DtMailEnv &,
const char * name,
const DtMailBoolean abstract,
DtMailValueSeq & value);
// For CHARSET
//---------------------------------------------------
// These methods are duplicated in class BodyPart (also being implemented
// in class Session) because RFCFormat and RFCBodyPart need to access
// them. Duplicating routines like what is being done here is a workaround
// for an implementation bug/hole because there is no class where global
// routines can be defined (and be accessed by any class).
// class Session is not a proper place to put (global) methods because
// not every class can get at Session.
// RFCFormat accesses these routines through its private Session handle.
// RFCBodyPart does not have a Session handle. Hence the need to duplicate
// the following routines.
virtual int OpenLcxDb(void);
virtual void DtXlateStdToOpLocale(char *op, char *std, char *dflt,
char **ret);
virtual void DtXlateOpToStdLocale(char *op, char *opLoc, char **retLoc,
char **ret_retLang, char **retSet);
virtual void DtXlateStdToOpCodeset(char *op, char *std, char *dflt,
char **ret);
virtual void DtXlateMimeToIconv(const char *, const char *, const char *,
char **, char **);
virtual void DtXlateLocaleToMime(const char *, const char *,
const char *, char **);
virtual char *csToConvName(char *);
virtual char *locToConvName();
virtual char *targetConvName();
virtual char *targetTagName();
virtual int csConvert(char **, unsigned long &, int, char *, char *);
//---------------------------------------------------
// Implement in both MIMEBodyPart and V3BodyPart
virtual char *csFromContentType(DtMailValueSeq & value) = 0;
// End of For CHARSET
#ifdef DEAD_WOOD
virtual DtMailChecksumState checksum(DtMailEnv &) = 0;
#endif /* DEAD_WOOD */
// Methods below this point are specific to RFCBodyPart.
//
virtual char *writeBodyParts(char * buf) = 0;
void adjustBodyPartsLocation(char * start);
virtual int rfcSize(const char * boundary, DtMailBoolean &) = 0;
protected:
~RFCBodyPart(void);
DtMailBoolean isTerm(const char *); // Determines if we have an eol.
void * _body_lock;
// _body_start includes any boundaries.
const char * _body_start;
// _body_text is where the text of the body begins, after
// boundaries, headers, and other uninteresting stuff.
//
const char * _body_text;
int _body_len;
RFCEnvelope * _body_env;
DtMailBoolean _my_env; // True if we made the envelope.
SafeScalar<int> _dirty;
friend class RFCMessage;
// The following entries are a computed cache. They
// are built in a lazy fashion, based on the caller's
// requests. These entries can be very expensive to
// compute so lazy is important.
//
char * _body;
DtMailBoolean _must_free_body;
int _body_decoded_len;
char * _body_type;
// The sub classes implement these because they are the major difference
// in the get/set contents methods.
//
virtual void getContentType(DtMailEnv &, char**) = 0;
virtual void getDtType(DtMailEnv &) = 0;
virtual void loadBody(DtMailEnv &) = 0;
virtual char * getDescription(DtMailEnv &) = 0;
virtual char * getName(DtMailEnv &) = 0;
virtual void setName(DtMailEnv &, const char *) = 0;
virtual unsigned long getLength(DtMailEnv &) = 0;
virtual const void * getBody(DtMailEnv &);
};
class MIMEBodyPart : public RFCBodyPart {
public:
MIMEBodyPart(DtMailEnv &,
DtMail::Message * parent,
const char * start,
const int len,
RFCEnvelope * body_env);
MIMEBodyPart(DtMailEnv &,
DtMail::Message * parent,
const char * start,
const char ** end,
const char * boundary);
#ifdef DEAD_WOOD
virtual DtMailChecksumState checksum(DtMailEnv &);
#endif /* DEAD_WOOD */
char *writeBodyParts(char * buf);
int rfcSize(const char * boundary, DtMailBoolean &);
// For CHARSET
virtual char *csFromContentType(DtMailValueSeq & value);
char * parameterValue(
DtMailValueSeq & value,
const char* parameter,
DtMailBoolean isCaseSensitive);
protected:
friend RFCMessage::~RFCMessage(void);
~MIMEBodyPart(void);
void getContentType(DtMailEnv &, char **);
void getDtType(DtMailEnv &);
void loadBody(DtMailEnv &);
char * getDescription(DtMailEnv &);
char * getName(DtMailEnv &);
void setName(DtMailEnv &, const char *);
char * getNameHeaderVal(DtMailEnv &);
unsigned long getLength(DtMailEnv &);
const void * getBody(DtMailEnv &);
};
class V3BodyPart : public RFCBodyPart {
public:
V3BodyPart(DtMailEnv &,
DtMail::Message * parent,
const char * start,
const int len,
RFCEnvelope * body_env);
V3BodyPart(DtMailEnv &,
DtMail::Message * parent,
const char * start,
const char ** end);
#ifdef DEAD_WOOD
virtual DtMailChecksumState checksum(DtMailEnv &);
#endif /* DEAD_WOOD */
char *writeBodyParts(char * buf);
int rfcSize(const char * boundary, DtMailBoolean &);
// For CHARSET
virtual char *csFromContentType(DtMailValueSeq & value);
protected:
friend RFCMessage::~RFCMessage(void);
~V3BodyPart(void);
void getContentType(DtMailEnv &, char **);
void getDtType(DtMailEnv &);
void loadBody(DtMailEnv &);
char * getDescription(DtMailEnv &);
char * getName(DtMailEnv &);
void setName(DtMailEnv &, const char *);
unsigned long getLength(DtMailEnv &);
};
class RFCMailBox : public DtMail::MailBox
{
public:
RFCMailBox(DtMailEnv &,
DtMail::Session * session,
DtMailObjectSpace space,
void * arg,
DtMailCallback cb,
void * clientData,
const char * impl_name);
virtual ~RFCMailBox(void);
static void appendCB(DtMailEnv&, char *buf, int len, void *clientData);
virtual void append(DtMailEnv &error, char *buf, int len);
virtual void create(DtMailEnv & error, mode_t = DTMAIL_DEFAULT_CREATE_MODE);
virtual void open(DtMailEnv &,
DtMailBoolean auto_create = DTM_TRUE,
int open_mode = DTMAIL_DEFAULT_OPEN_MODE,
mode_t create_mode = DTMAIL_DEFAULT_CREATE_MODE,
DtMailBoolean lock_flag = DTM_TRUE,
DtMailBoolean auto_parse = DTM_TRUE);
virtual void lock();
virtual void unlock();
virtual void save();
virtual void callCallback(DtMailCallbackOp, void *);
virtual void disableMailRetrieval()
{ _mr_allowed = DTM_FALSE; }
virtual void enableMailRetrieval()
{ _mr_allowed = DTM_TRUE; }
virtual void checkForMail(
DtMailEnv &,
const DtMailBoolean
already_locked = DTM_FALSE);
virtual void clearMessageSummary(DtMailHeaderLine &);
virtual void copyMessage(DtMailEnv &, DtMail::Message *);
virtual void copyMailBox(DtMailEnv &, DtMail::MailBox *);
virtual void createMailRetrievalAgent(char *passwd=NULL);
virtual void deleteMailRetrievalAgent();
virtual void expunge(DtMailEnv &);
virtual DtMail::Message *getFirstMessage(DtMailEnv &);
virtual DtMailMessageHandle getFirstMessageSummary(
DtMailEnv &,
const DtMailHeaderRequest &,
DtMailHeaderLine &);
virtual DtMail::Message *getNextMessage(DtMailEnv &, DtMail::Message *);
virtual DtMailMessageHandle getNextMessageSummary(
DtMailEnv &,
DtMailMessageHandle,
const DtMailHeaderRequest &,
DtMailHeaderLine &);
virtual DtMail::Message *getMessage(DtMailEnv &, DtMailMessageHandle);
virtual void getMessageSummary(
DtMailEnv &,
DtMailMessageHandle,
const DtMailHeaderRequest &,
DtMailHeaderLine &);
virtual const char *impl(DtMailEnv & error);
#ifdef DEAD_WOOD
virtual int messageCount(DtMailEnv &);
#endif /* DEAD_WOOD */
virtual DtMail::Message *newMessage(DtMailEnv &);
virtual DtMailCallbackOp retrieveNewMail(DtMailEnv&);
virtual void updateMailRetrievalPassword(char *passwd=NULL);
// This is not used by any clients!
struct MapRegion : public DtCPlusPlusAllocator
{
char * map_region;
unsigned long map_size;
char * file_region; // Where the parsing begins.
unsigned long file_size;
long offset;
};
struct MessageCache : public DtCPlusPlusAllocator {
RFCMessage *message;
DtMailBoolean delete_pending;
};
// Methods below this point are specific to RFCMailBox.
void markDirty(const int delta);
void startAutoSave(DtMailEnv & error, DtMailBoolean start=DTM_TRUE);
protected:
struct NewMailData : public DtCPlusPlusAllocator
{
RFCMailBox * self;
Condition * object_valid;
};
// Content-Type: message/partial support.
struct _partialData
{
const char * id;
unsigned int number;
unsigned int total; // 0 == I do not know.
RFCMessage * msg;
};
// Keep track of how many messages, and whether we've hit the
// EOF. The number of messages is a condition variable because
// we might have multiple threads trying to read the state
// while the parsing thread is reading the state.
//
Condition _at_eof;
char *_buffer;
SafeScalar<int> _dirty; // Write access/dirty state.
DtMailBoolean _dot_lock_active;
DtMailBoolean _errorLogging; // Extra logging done??
int _fd;
SafeScalar<unsigned long> _file_size;
const char *_impl_name; // Might be V3 or MIME.
int _last_check; // For polling only.
time_t _last_poll; // For polling only.
int _links;
DtMailBoolean _lock_flag;
FileShare *_lock_obj;
DtMailBoolean _lockf_active; // lockf() is being held
char * _lockFileName; // lock file name for mailbox
DtMailBoolean _long_lock_active;
Thread _mbox_daemon;
void * _map_lock;
DtVirtArray<MapRegion *> _mappings;
unsigned long _object_signature;
Condition *_object_valid;
DtMailBoolean _parsed;
char *_real_path;
DtMailBoolean _mr_allowed;
char *_mra_command;
DtMailServer *_mra_server;
char *_mra_serverpw;
DtVirtArray<MessageCache *> _msg_list;
_partialData **_partialList;
unsigned int _partialListCount;
struct stat _stinfo;
NewMailData *_thread_info;
DtMailBoolean _tt_lock;
char * _uniqueLockId; // unique id for .lock files
int _uniqueLockIdLength;
DtMailBoolean _use_dot_lock;
// void CheckPointEvent(DtMailEnv & error);
void CheckPointEvent();
void ExpungeEvent(DtMailBoolean closing = DTM_FALSE);
void NewMailEvent(const DtMailBoolean already_locked = DTM_FALSE);
static DtMailBoolean
PollEntry(void *);
static void *ThreadNewMailEntry(void *);
static void *ThreadParseEntry(void *);
RFCMessage *_assemblePartial(DtMailEnv &error,RFCMessage *Message);
DtMailBoolean
_isPartial(DtMailEnv &error, RFCMessage *message);
DtMailBoolean
addressIsMapped(void *addressToCheck);
#if defined(linux)
void alterPageMappingAdvice(MapRegion *map, int advice = 0);
#else
void alterPageMappingAdvice(
MapRegion *map,
int advice = MADV_SEQUENTIAL);
#endif
int createTemporaryMailboxFile(DtMailEnv &, char *tmp_name);
void checkLockFileOwnership(DtMailEnv &);
void dotDtmailLockFile(char *, int);
void dotDtmailLock(DtMailEnv &);
void dotDtmailUnlock(DtMailEnv &);
void dumpMaps(const char *);
char *generateLockFileName(void);
char *generateUniqueLockId(void);
void incorporate(
DtMailEnv &,
const DtMailBoolean already_locked = DTM_FALSE);
time_t linkLockFile(DtMailEnv &, char *tempLockFileName);
void lockFile(DtMailEnv &);
void lockNewMailboxFile(int new_fd);
DTMBX_LONGLOCK
longLock(DtMailEnv &);
void longUnlock(DtMailEnv &);
int lookupByMsg(RFCMessage * msg);
void mailboxAccessHide(char *prefix);
void mailboxAccessShow(time_t mtime, char *prefix);
void makeHeaderLine(DtMailEnv & error,
int slot,
const DtMailHeaderRequest & request,
DtMailHeaderLine &);
int mapFile(DtMailEnv & error,
const DtMailBoolean already_locked = DTM_FALSE,
mode_t create_mode = DTMAIL_DEFAULT_CREATE_MODE);
MapRegion *mapNewRegion(DtMailEnv &, int fd, unsigned long bytesWritten);
int nextNotDel(const int cur);
void openRealFile(DtMailEnv &error, int mode, mode_t create_mode);
int prevNotDel(const int cur);
void parseFile(DtMailEnv & error, int slot);
off_t realFileSize(DtMailEnv &error, struct stat *stat_buffer = NULL);
void transferLock(int old_fd, int new_fd);
void unlockOldMailboxFile(int old_fd);
void unlockFile(DtMailEnv &, int fd);
void waitForMsgs(int needed);
void writeMailBox(DtMailEnv&, DtMailBoolean);
void writeToDumpFile(const char* format, ...);
};
class RFCTransport : public DtMail::Transport {
public:
RFCTransport(DtMailEnv &, DtMail::Session *, DtMailStatusCallback, void *,
const char * impl);
virtual ~RFCTransport(void);
virtual DtMailOperationId submit(DtMailEnv &,
DtMail::Message *,
DtMailBoolean log_msg);
static void arpaPhrase(const char * list, DtMailAddressSeq & tokens);
// SendMsgDialog initiates a send. It needs to set information
// needed to exec sendmail by calling these initialization functions.
// getSendmailReturnProc returns a handler so that SendMsgDialog
// can use it in XtAppAddInput.
virtual void initTransportData(int fds[2],
SubProcessFinishedProc proc, void *ptr);
virtual void *getSendmailReturnProc(void);
protected:
Condition * _object_valid;
char * _impl;
struct ThreadSimpleData : public DtCPlusPlusAllocator {
RFCTransport * self;
const char * to;
const char * cc;
const char * bcc;
const char * subject;
const char * text;
};
static void * ThreadSimpleEntry(void * arg);
void format(DtMailEnv &, DtMail::Message * msg, DtMailBoolean log_msg);
void formatSimple(DtMailEnv &,
const char * to,
const char * cc,
const char * bcc,
const char * subject,
const char * text);
void deliver(DtMailEnv &,
DtMailAddressSeq &,
Buffer & headers,
Buffer & bodies,
DtMailBoolean log_msg,
int **log_files,
int & log_count);
void launchSendmail(DtMailEnv & error,
Buffer & headers,
Buffer & boides,
char ** argv);
char * concatValue(DtMailValueSeq &);
void appendAddrs(DtMailAddressSeq & to, DtMailAddressSeq & from);
void skinFiles(DtMailAddressSeq &);
char * addrToString(DtMailAddressSeq &);
int openLogFile(const char * path);
void closeLogFiles(int * files, int file_cnt);
// These functions are needed to exec sendmail
static void childHandler(void);
void signalRegister(void);
int startSubprocess(DtMailEnv &error, char * cmd,
Buffer & headers, Buffer & bodies, char **argv);
static void sendmailReturnProc(void);
// Store info from SendMsgDialog
// ptr to SendMsgDialog::SendmaliErrorProc
SubProcessFinishedProc *_error_proc;
// a pointer to SendMsgDialog
void *_smd;
// get the status from the low and hi bytes returned from wait()
inline static int lowByte (int status) { return (status & 0377); }
inline static int highByte (int status) { return (lowByte(status >> 8)); }
};
extern const char * RFCDeleteHeader;
class RFCValue : public DtMailValue {
public:
RFCValue(const char * str, int size, DtMail::Session *s);
RFCValue(const char * str, int size);
~RFCValue(void);
virtual operator const char *(void);
virtual const char * operator= (const char *);
virtual DtMailValueDate toDate(void);
#ifdef DEAD_WOOD
virtual void fromDate(const DtMailValueDate &) { }
#endif /* DEAD_WOOD */
virtual DtMailAddressSeq * toAddress(void);
#ifdef DEAD_WOOD
virtual void fromAddress(const DtMailAddressSeq &) { }
#endif /* DEAD_WOOD */
virtual const char * raw(void);
protected:
DtMail::Session *_session;
char * _decoded;
void decodeValue(void);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
/*
*+SNOTICE
*
*
* $TOG: RFCMIME.hh /main/6 1997/03/28 12:10:13 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
#ifndef _RFCMIME_HH
#define _RFCMIME_HH
#include "RFCFormat.hh"
class RFCMIME : public RFCFormat {
public:
RFCMIME(DtMail::Session *);
~RFCMIME(void);
static void readBase64(char * dest, int & size, const char * text,
const unsigned long text_len);
static void readQPrint(char * dest, int & size, const char * text,
const unsigned long text_len);
static void readTextEnriched(char * dest, int & size, const char * text,
const unsigned long text_len);
void writeBase64(Buffer & buf, const char * bp,
const unsigned long len);
void writeQPrint(Buffer & buf, const char * bp,
const unsigned long len);
// digest is:
// unsigned char digest[16];
//
static void md5PlainText(const char * bp,
const unsigned long len,
unsigned char * digest);
enum Encoding {
MIME_7BIT,
MIME_8BIT,
MIME_QPRINT,
MIME_BASE64
};
protected:
virtual void formatBodies(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_content_length,
char ** extra_headers,
Buffer & buf);
virtual void formatHeaders(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_unix_from,
const char * extra_headers,
Buffer & buf);
virtual void rfc1522cpy(Buffer & buf, const char * value);
private:
void getMIMEType(
DtMail::BodyPart * bp,
char * mime_type,
DtMailBoolean & is_text);
Encoding getHdrEncodingType(
const char *,
const unsigned int,
DtMailBoolean,
const char *);
Encoding getEncodingType(
const char *,
const unsigned int,
DtMailBoolean,
int *);
Encoding getClearEncoding(
const char *,
const unsigned int,
int *);
void writeContentHeaders(
Buffer & buf,
const char * type,
const char * name,
const Encoding,
const char * digest,
DtMailBoolean show_as_attachment,
int is2022ASCII );
void writePlainText(
Buffer & buf,
const char * bp,
const unsigned long len);
void owCompat(
Buffer & buf, char * type, char * name,
char *contents, unsigned long len);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,823 @@
/*
*+SNOTICE
*
*
* $TOG: RFCMailValues.C /main/10 1998/09/03 07:01:06 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 <EUSCompat.h>
#include <stdlib.h>
#include <string.h>
#if !defined(USL) && !defined(__uxp__)
#include <strings.h>
#endif
#include <ctype.h>
#include <DtMail/IO.hh>
#include "RFCImpl.hh"
#include "RFCMIME.hh"
#include "str_utils.h"
// String values. These assume an RFC format for now. They will
// apply RFC1522 coding rules to the strings for dealing with
// non-ASCII text in RFC headers.
//
RFCValue::RFCValue(const char * str, int size) : DtMailValue(NULL)
{
_value = (char *)malloc(size + 1);
memcpy(_value, str, size);
_value[size] = 0;
_decoded = NULL;
}
RFCValue::RFCValue(const char * str, int size, DtMail::Session *s) : DtMailValue(NULL)
{
_value = (char *)malloc(size + 1);
memcpy(_value, str, size);
_value[size] = 0;
_decoded = NULL;
_session = s;
}
RFCValue::~RFCValue(void)
{
if (_decoded) {
free(_decoded);
}
}
static const char *
decode1522(const char * enc_start, const char * max_end, char **output, DtMail::Session *s)
{
// Find the end of the encoded region.
//
int qs = 0;
const char *enc_end;
for (enc_end = enc_start;
*enc_end && enc_end < max_end;
enc_end++) {
if (*enc_end == '?') {
qs += 1;
if (qs > 3 && *(enc_end + 1) == '=') {
break;
}
}
}
if (*enc_end != '?') {
return(enc_start);
}
enc_end += 1;
// Pull off the char set name.
//
const char *cs_end;
for (cs_end = enc_start + 2; *cs_end != '?'; cs_end++) {
continue;
}
int cs_name_length = cs_end - enc_start - 2;
char *cs_name = (char*) malloc(cs_name_length + 1);
strncpy(cs_name, enc_start + 2, cs_name_length);
cs_name[cs_name_length] = 0;
// Set the encoding method and start of buffer.
//
char encoding = *(cs_end + 1);
const char * buf_start = cs_end + 3;
switch (toupper(encoding)) {
case 'Q':
{
int len = 0;
RFCMIME::readQPrint(*output, len, buf_start, enc_end - buf_start - 1);
(*output)[len] = 0;
break;
}
case 'B':
{
int len = 0;
RFCMIME::readBase64(*output, len, buf_start, enc_end - buf_start - 1);
(*output)[len] = 0;
break;
}
default:
// Invalid encoding. Assume a false match.
if (cs_name != NULL) free(cs_name);
return (enc_start);
}
// Do codeset conversion if charset is present
char *from_cs = s->csToConvName(cs_name);
char *to_cs = s->locToConvName();
if ( from_cs && to_cs ) {
if ( strcasecmp(from_cs, to_cs) != 0 ) {
unsigned long tmplen = (unsigned long) strlen(*output);
(void) s->csConvert(&(*output), tmplen, 1, from_cs, to_cs);
}
}
if (NULL != from_cs)
free( from_cs );
if (NULL != to_cs)
free ( to_cs );
if (NULL != cs_name)
free(cs_name);
return(enc_end);
}
RFCValue::operator const char *(void)
{
if (_decoded) {
return(_decoded);
}
decodeValue();
return(_decoded);
}
const char *
RFCValue::operator= (const char * str)
{
if (_decoded) {
free(_decoded);
_decoded = NULL;
}
if (_value) {
free(_value);
}
_value = strdup(str);
return(_value);
}
static const char * DaysOfTheWeek[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char * MonthsOfTheYear[] = {
"Jan", "Feb", "Mar",
"Apr", "May", "Jun",
"Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"
};
static int
matchDay(const char * start, const char * end)
{
int len = end - start + 1;
for (int i = 0; i < 7; i++) {
if (strncmp(DaysOfTheWeek[i], start, len) == 0) {
return(i);
}
}
return(-1);
}
static int
matchMonth(const char * start, const char * end)
{
int len = end - start + 1;
for (int i = 0; i < 12; i++) {
if (strncmp(MonthsOfTheYear[i], start, len) == 0) {
return(i);
}
}
return(-1);
}
static void
parseTime(const char * start, const char * end, tm & val)
{
int size = end - start + 1;
// Time will be in the form hh:mm:ss where seconds are optional.
char num_buf[10];
strncpy(num_buf, start, 2);
num_buf[2] = 0;
val.tm_hour = (int) strtol(num_buf, NULL, 10);
strncpy(num_buf, &start[3], 2);
num_buf[2] = 0;
val.tm_min = (int) strtol(num_buf, NULL, 10);
if (size > 6) {
strncpy(num_buf, &start[6], 2);
num_buf[2] = 0;
val.tm_sec = (int) strtol(num_buf, NULL, 10);
}
else {
val.tm_sec = 0;
}
return;
}
static const char * TZNames[] = {
"EST", "CST", "MST", "PST"
};
static const char * TZNamesDST[] = {
"EDT", "CDT", "MDT", "PDT"
};
static time_t
parseTZ(const char * start, const char * end)
{
int size = end - start + 1;
// There are at 3 possibilities that we understand. There
// is the single letter military time zone. In that case
// Z is 0 UTC. A-M is -1 to -12, skipping J. N-Y is +1 to +12
// from UTC.
//
// Lets start with that one because it is the easiest.
if (size == 1) {
int hours_from = 0;
if (*start >= 'A' && *start <= 'I') {
hours_from = *start - 'A' + 1;
}
else if (*start >= 'L' && *start <= 'M') {
hours_from = *start - 'K' + 10;
}
else if (*start >= 'N' && *start <= 'Y') {
hours_from = ('N' - *start) - 1;
}
return(hours_from * 3600);
}
// The next option is one of the ANSI standard time zones. These
// are three letter abbrievations that tell us where DST in in effect.
// So, if we have a length of three, lets see if it is in the table.
if (size == 3) {
// First normal zones.
int i;
for (i = 0; i < 4; i++) {
if (strncmp(start, TZNames[i], 3) == 0) {
return((5 + i) * -3600);
}
}
// Now DST zones
for (i = 0; i < 4; i++) {
if (strncmp(start, TZNames[i], 3) == 0) {
return((4 + i) * -3600);
}
}
}
// Finally we understand +/- HHMM from UTC.
if (size == 5) {
int sign = (*start == '+') ? 1 : -1;
char num_buf[10];
strncpy(num_buf, &start[1], 2);
num_buf[2] = 0;
int hours = (int) strtol(num_buf, NULL, 10);
strncpy(num_buf, &start[3], 2);
num_buf[2] = 0;
int minutes = (int) strtol(num_buf, NULL, 10);
return(sign * ((hours * 3600) + (minutes * 60)));
}
// We have no idea at this point, and it is very unlikely that the
// text is meaningful to the reader either. Set the zone to UTC and
// punt. It is also possible that the text is "UT" or "GMT" in which
// case offset 0 is the right answer.
return(0);
}
DtMailValueDate
RFCValue::toDate(void)
{
DtMailValueDate date;
const char * pos = _value;
tm new_time;
memset(&date, 0, sizeof(date));
memset(&new_time, 0, sizeof(new_time));
date.dtm_date = 0;
date.dtm_tz_offset_secs = 0;
// Before doing anything, check to see if _value is valid.
// Some messages have no Date string. Return date with zeroed fields
// in those cases.
if (!_value || (strlen(_value) == 0)) return (date);
// Find the first non-blank
for (; *pos && isspace((unsigned char)*pos); pos++) {
continue;
}
// There are usually no more than 6 tokens in an RFC date. We will
// have a few extras just in case we are given a wierd string.
const char *token_begin[12];
const char *token_end[12];
int n_tokens = 0;
// Look for the end of each token. Date tokens are white space
// separated.
while (*pos) {
token_begin[n_tokens] = pos;
for (; *pos && !isspace((unsigned char)*pos); pos++) {
continue;
}
if (*pos) {
token_end[n_tokens++] = pos - 1;
}
else {
token_end[n_tokens++] = pos;
}
for (; *pos && isspace((unsigned char)*pos); pos++) {
continue;
}
// This means the message is most likely corrupted so just bail out
if (n_tokens == 12)
break;
}
// Some dates will have a comma after the day of the week. We
// want to remove that. It will always be the first token if
// we have the day of the week.
if (*token_end[0] == ',') {
token_end[0]--;
}
if (n_tokens < 2) {
return(date);
}
// There are two possible formats, and many variations, that we
// will see in an RFC message. They are:
//
// Tue Oct 12 10:36:10 1993
// Tue, 12 Oct 1993 10:35:05 PDT
//
// The first is the 821 format put on by sendmail. The second is
// one of the many variants of the 822 format. The big difference
// we must detect is "mon dd time year" vs "dd mon year time tz"
//
// The first qualifier is usually the day of the week. For our purposes,
// we will simply throw it away. This information will be recomputed
// based on the date and time.
int this_token = 0;
int day = matchDay(token_begin[this_token], token_end[this_token]);
if (day >= 0) {
// Ignore the day.
this_token += 1;
}
// This token should either be a numeric day, or an alpha month.
// Lets see if it is a month. If so, we know what the rest of
// the date will look like.
int month = matchMonth(token_begin[this_token], token_end[this_token]);
if (month >= 0) {
new_time.tm_mon = month;
// Now should be the day of the month.
char num_buf[20];
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
strncpy(num_buf, token_begin[this_token], 2);
num_buf[2] = 0;
new_time.tm_mday = (int) strtol(num_buf, NULL, 10);
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
parseTime(token_begin[this_token], token_end[this_token], new_time);
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
// Sometimes the Unix date will include the time zone.
//
if (isalpha(*token_begin[this_token])) {
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
}
strncpy(num_buf, token_begin[this_token], 4);
// Don't remove last digit from year and get bad dates in header.
num_buf[token_end[this_token] - token_begin[this_token] + 1] = 0;
new_time.tm_year = (int) strtol(num_buf, NULL, 10);
if (new_time.tm_year > 1900) {
new_time.tm_year -= 1900;
}
new_time.tm_isdst = -1;
date.dtm_date = SafeMktime(&new_time);
date.dtm_tz_offset_secs = (int) timezone;
}
else {
// In this format, we should have a day of the month.
char num_buf[20];
strncpy(num_buf, token_begin[this_token], 2);
num_buf[2] = 0;
new_time.tm_mday = (int) strtol(num_buf, NULL, 10);
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
// Now the month name.
new_time.tm_mon = matchMonth(token_begin[this_token], token_end[this_token]);
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
// The year, which is either 2 or 4 digits.
int t_size = token_end[this_token] - token_begin[this_token] + 1;
strncpy(num_buf, token_begin[this_token], t_size);
num_buf[t_size] = 0;
new_time.tm_year = (int) strtol(num_buf, NULL, 10);
if (new_time.tm_year > 1900) {
new_time.tm_year -= 1900;
}
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
// The time, in the specified time zone.
parseTime(token_begin[this_token], token_end[this_token], new_time);
this_token += 1;
if (this_token == n_tokens) {
return(date);
}
time_t offset = parseTZ(token_begin[this_token], token_end[this_token]);
time_t orig_zone = (time_t) timezone;
timezone = offset;
// Tell "mktime" to figure "dst" on or not.
new_time.tm_isdst = -1;
date.dtm_date = SafeMktime(&new_time);
date.dtm_tz_offset_secs = offset;
timezone = orig_zone;
}
return(date);
}
static char *
findParenComment(const char * value)
{
int in_quote = 0;
const char *sparen;
for (sparen = value; *sparen; sparen++) {
// We must ignore stuff in quotes.
//
if (*sparen == '"') {
if (in_quote) {
in_quote = 0;
}
else {
in_quote = 1;
}
continue;
}
if (in_quote) {
continue;
}
if (*sparen == '(') {
break;
}
}
if (*sparen != '(') {
return(NULL);
}
in_quote = 0;
const char *lparen;
for (lparen = (sparen + 1); *lparen; lparen++) {
// We will support nested comments of the form (Joe (Hi) Blow)
//
if (*lparen == '(') {
in_quote += 1;
continue;
}
if (*lparen == ')') {
in_quote -= 1;
}
if (in_quote < 0) {
break;
}
}
if (*lparen != ')') {
return(NULL);
}
char * comment = (char *)malloc(lparen - sparen + 1);
memcpy(comment, (sparen + 1), lparen - sparen - 1);
comment[lparen - sparen - 1] = 0;
return(comment);
}
static char *
stripAngleAddr(const char * value)
{
int in_quote = 0;
const char *lt;
for (lt = value; *lt; lt++)
{
if (*lt == '"')
{
if (in_quote) in_quote = 0;
else in_quote = 1;
continue;
}
if (in_quote) continue;
if (*lt == '<') break;
}
if (*lt != '<') return(NULL);
in_quote = 0;
const char *gt;
for (gt = (lt + 1); *gt; gt++)
{
if (*gt == '"')
{
if (in_quote) in_quote = 0;
else in_quote = 1;
continue;
}
if (in_quote) continue;
if (*gt == '>') break;
}
if (*gt != '>') return(NULL);
// Copy everything not in the angle brackets.
//
char * name = (char *)malloc(strlen(value) + 1);
char * out = name;
for (const char * cp = value; *cp; cp++)
{
if (cp >= lt && cp <= gt) continue;
*out++ = *cp;
}
*out = 0;
if (strlen(name) == 0)
{
free(name);
return(NULL);
}
return(name);
}
static char *
stripQuotesWhiteSpace(const char * value)
{
int found_alphanum = 0;
char *name = NULL;
char *out = NULL;
//
// Skip past leading white space.
//
const char *cp = value;
while (isspace(*cp)) cp++;
//
// If there are no quotes, copy and return.
//
if (*cp != '"')
{
name = strdup(cp);
return name;
}
//
// Strip out the quotes.
//
cp++;
out = name = (char*) malloc(strlen(value)+1);
if (NULL == out) return NULL;
while (*cp != '"')
{
*out = *cp;
out++;
cp++;
}
*out = 0;
return name;
}
DtMailAddressSeq *
RFCValue::toAddress(void)
{
// Count the commas, to figure out how big to make the
// sequence.
//
int commas = 3;
for (const char * comma = _value; *comma; comma++)
if (*comma == ',') commas += 1;
DtMailAddressSeq * seq = new DtMailAddressSeq(commas);
if (!_decoded) decodeValue();
RFCTransport::arpaPhrase(_decoded, *seq);
// If we have only one address, then let's try to find a comment
// so the person can be set. This is trivial to do for one address
// and can have a win for displaying the headers in the message
// scrolling list.
//
if (seq->length() == 1)
{
// This is less than perfect, but we will look for (Name) and
// use it first. If we can't find that, then see if we can
// find something outside <addr>. If not that, then simply
// give up.
//
DtMailValueAddress * addr = (*seq)[0];
addr->dtm_person = findParenComment(_decoded);
if (!addr->dtm_person)
{
char *name = stripAngleAddr(_decoded);
if (name)
{
addr->dtm_person = stripQuotesWhiteSpace(name);
free(name);
}
}
}
return(seq);
}
const char *
RFCValue::raw(void)
{
return(_value);
}
void
RFCValue::decodeValue(void)
{
// Create the output buffer. We will assume that it is
// the header will only shrink by applying RFC1522.
//
int outleft = strlen(_value);
char * output = (char *)malloc(outleft + 2);
*output = 0;
char * cur_c = output;
char *buf = NULL;
// Scan the value, looking for =? which indicates the start
// of a encoded string.
//
for (const char * in_c = _value; *in_c; in_c++) {
if (*in_c == '=' && *(in_c + 1) == '?') {
//
// Decode the encoding. Return the last character so the loop
// continues to work. Also reset cur_c because the output buffer
// has been updated.
//
// Allocate space for buf to contain rest of output because it
// is enough space for the decoded quoted-printable or base64.
// If codeset conversion is done, then csConvert will re-allocate
// enough space.
//
size_t _valueLen = strlen(_value);
const char *in_c_sav = in_c;
buf = (char *)malloc(outleft + 2);
strcpy(buf, in_c);
in_c = decode1522(in_c, _value + _valueLen - 1, &buf, _session);
if (in_c > in_c_sav) {
size_t bufLen = strlen(buf);
if (bufLen > outleft) {
output =
(char*) realloc((char*)output, _valueLen + bufLen + 2);
outleft += bufLen;
}
strncat(output, buf, bufLen);
cur_c = output + strlen(output);
outleft -= bufLen;
free(buf);
continue;
}
free(buf);
}
// Just copy the byte and reset the null pointer, unless
// we are dealing with carriage return.
//
if (*in_c != '\r') {
if (outleft == 0) {
output = (char*) realloc((char*) output, strlen(output) * 2);
outleft = strlen(output);
}
*cur_c = *in_c;
cur_c++;
*cur_c = 0;
outleft--;
}
}
// Kill any trailing white space.
//
*cur_c = 0;
for (cur_c -= 1;
cur_c >= output && isspace((unsigned char)*cur_c);
cur_c--)
{
*cur_c = 0;
}
_decoded = output;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/*
*+SNOTICE
*
*
* $XConsortium: SunV3.hh /main/4 1996/04/21 19:50:07 drk $
*
* 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 _SUNV3_HH
#define _SUNV3_HH
#include "RFCFormat.hh"
class SunV3 : public RFCFormat {
public:
SunV3(DtMail::Session *);
~SunV3(void);
static void decode(const char * enc_info,
char ** outputBp,
int & outputLen,
const char * inputBp,
const unsigned long inputLen);
static void encode(Buffer & buf,
const char * path,
const char * bp,
const unsigned long len);
protected:
virtual void formatBodies(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_content_length,
char ** extra_headers,
Buffer & buf);
virtual void formatHeaders(DtMailEnv & error,
DtMail::Message & msg,
DtMailBoolean include_unix_from,
const char * extra_headers,
Buffer & buf);
private:
static int uudecode(char ** outputBp,
int & outputLen,
const char * inputBp,
const unsigned long inputLen);
static int uncompress(char ** outputBp,
int & outputLen,
const char * inputBp,
const unsigned long inputLen);
void encode_uue_line(Buffer & buf,
const unsigned char * unencodedBp,
const unsigned long unencodedLen);
void uuencode(Buffer & buf,
const char * path,
const char * bp,
const unsigned long len);
void getV3Type(DtMail::BodyPart *, char *);
};
#endif

View File

@@ -0,0 +1,680 @@
/*
*+SNOTICE
*
* $TOG: V3BodyPart.C /main/8 1998/07/23 18:04:38 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
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <Dt/Dts.h>
#include <DtMail/DtMail.hh>
#include "RFCImpl.hh"
#include "SunV3.hh"
#include <DtMail/Threads.hh>
#include "str_utils.h"
#include <assert.h>
// For CHARSET
#include <locale.h>
#include <DtHelp/LocaleXlate.h>
V3BodyPart::V3BodyPart(DtMailEnv & error,
DtMail::Message * parent,
const char * start,
const int len,
RFCEnvelope * body_env)
: RFCBodyPart(error, parent, start, len, body_env)
{
// This constructor is used for single body parts. This
// includes generic RFC822 messages, i.e. no Mime-Version
// field.
//
// There really isn't anything we can do. We may have to
// apply a content encoding, but let's wait until the user
// expresses an interest.
//
error.clear();
return;
}
// V3BodyPart:V3BodyPart -- retrieve next V3 message body part
// Arguments:
// DtMailEnv & error --
// DtMail::Message * parent --
// const char * start -- -> beginning of boundary separator
// const char ** end -- -> end of message
// Outputs:
// *end -- is set to the first byte past the end of the retrieved
// part. This either points to the next body part (if any) or
// is 1 byte past the end of the message if no further parts.
// _body_env -- RFCEnvelope defining entire body part
// _body_len -- true length of contained body part (minus headers)
// _body_text -- first byte of contained body part (minus headers)
// Description:
// This constructor is used for multi-part body parts. Given a
// pointer to the beginning of the boundary separator and a
// pointer to the end of the message, reduce pointers to actual
// body part data (minus headers) and update class variables
// as appropriate.
//
V3BodyPart::V3BodyPart(DtMailEnv & error,
DtMail::Message * parent,
const char * start,
const char ** end)
: RFCBodyPart(error, parent, start, 0, NULL)
{
// Get past the boundary separator.
//
const char * body_end;
for (body_end = start; body_end <= *end && *body_end != '\n'; body_end++) {
continue;
}
if (body_end > *end) {
// no data after separator?? Bogus body part!
_body_len = 0;
*end = body_end;
return;
}
// The body part headers begin here. We will look from here until
// the first blank line for the end of the headers.
//
body_end += 1; // Chew the newline.
const char * env_start = body_end;
for (; body_end <= *end; body_end++) {
if (*body_end == '\n') {
int blank_only = 1;
for (const char * blank = body_end + 1;
blank <= *end && *blank != '\n'; blank++) {
if (!isspace((unsigned char)*blank)) {
blank_only = 0;
break;
}
}
if (blank_only) {
break;
}
}
}
_my_env = DTM_TRUE; // indicate that we created this envelope
_body_env = new RFCEnvelope(error, parent, env_start, body_end - env_start + 1);
// Now we need to find the start of the body (the real start, not
// where the boundary begins. This is immediately after the newline
// that is placed after the end of the headers.
//
_body_text = body_end + 1;
for (; _body_text <= *end && *_body_text != '\n'; _body_text++) {
continue;
}
_body_text += 1;
// We now need to figure out where the end of the attachment is.
// We have 2 choices. Content lines, or content length.
//
DtMailValueSeq value;
_body_env->getHeader(error, "x-sun-content-length",
DTM_FALSE, value);
if (error.isNotSet()) {
// Great! content-length is much easier.
// We do this by computing a -> where the end of the attachment
// is supposed to be as indicated by the specified content length.
// If we come to the end of the message altogether, or to the start
// of another header body, then we know we have bounded this body part.
//
int content_length = (int) strtol(*(value[0]), NULL, 10);
body_end = _body_text + content_length; // "supposed" end of body part
for (int i = 0; i < 2; i++) {
if (body_end == *end) { // at end of message??
// Yes, this is the last header body in this message
// We are at the end -- force this body part to end at the
// end of the message and use length as computed.
// Mark end of this body for caller as 1 byte past end of last body header
// to prevent from being called again.
//
_body_len = content_length;
*end += 1;
return;
}
if (body_end > *end) { // past end of message??
// Yes, this is the last header body in this message
// We are past the end -- force this body part to end at the
// end of the message and compute length based upon that assumption.
// Mark end of this body for caller as 1 byte past end of last body header
// to prevent from being called again.
//
*end += 1;
_body_len = *end - _body_text;
return;
}
// V3BodyParts have a "----------" (10 dashes) at the beginning of a
// line with no white space before them and a new line at the end to
// signal the beginning of an attachment.
if ((*(body_end-1) == '\n') &&
strncmp(body_end, "----------", 10) == 0 &&
isTerm(body_end + 10)) { // start of another body header?
// Yes, this is one of many header bodies in this message
// Mark end of this body for caller as first byte of next body header
//
assert(body_end < *end); // cant be last
_body_len = body_end - _body_text;
*end = body_end+1; // current end
return;
}
// Chew through white space and test again.
//
while (isspace((unsigned char)*body_end)) {
body_end += 1;
}
}
}
else {
error.clear();
}
// We didn't have content-length, or it was wrong or bogus.
// Try for content lines.
//
value.clear(); // clear out any previous header(s) retrieved
_body_env->getHeader(error, "x-sun-content-lines",
DTM_FALSE, value);
if (error.isNotSet()) {
// content-lines requires a bit o' muching first.
// We do this by marching through the body counting new lines
// until the specified number of lines have been passed. This
// is the determined end of the body part.
//
int content_lines = (int) strtol(*(value[0]), NULL, 10);
int lines = 0;
for (body_end = _body_text;
body_end <= *end && lines < content_lines; body_end++) {
if (*body_end == '\n') {
lines += 1;
}
}
if (body_end >= *end) { // at end of message??
// Yes, this is the last header body in this message
// We are at or past the end -- force this body part to end at the
// end of the message and compute length based upon that assumption.
// Mark end of this body for caller as 1 byte past end of last body header
// to prevent from being called again.
//
*end += 1;
_body_len = *end - _body_text;
return;
}
// V3BodyParts have a "----------" (10 dashes) at the beginning of a
// line with no white space before them and a new line at the end to
// signal the beginning of an attachment.
if ((*(body_end-1) == '\n') &&
strncmp(body_end, "----------", 10) == 0 &&
isTerm(body_end + 10) == DTM_TRUE) { // start of another body header?
// Yes, this is one of many header bodies in this message
// Mark end of this body for caller as first byte of next body header
//
assert(body_end < *end); // cant be last
_body_len = body_end - _body_text;
*end = body_end+1; // current end
return;
}
}
else {
error.clear();
}
// We either didn't have a length, or number of lines, or they
// didn't work. We will now apply a dangerous but last resort
// effort to find the end of the body by looking for the 10 dash
// separator.
// V3BodyParts have a "----------" (10 dashes) at the beginning of a
// line with no white space before them and a new line at the end to
// signal the beginning of an attachment.
//
for (body_end = _body_text; body_end <= (*end - 12); body_end++) {
if (*body_end == '\n' &&
strncmp(body_end + 1, "----------", 10) == 0 &&
isTerm(body_end + 11) == DTM_TRUE) {
// Dangerously by successfully located what appears to be the end
// of this attachment.
//
*end = body_end;
_body_len = body_end - _body_text;
return;
}
}
// At this point we are at the end of the message and are without
// the benefit of content lines or content length or the discovery
// of what appears to be a message separator. Assume this body part
// consumes the remainder of the message. Mark end of this body for
// caller as 1 byte past end to prevent from being called again.
//
*end += 1;
_body_len = *end - _body_text;
return;
}
V3BodyPart::~V3BodyPart(void)
{
}
#ifdef DEAD_WOOD
DtMailChecksumState
V3BodyPart::checksum(DtMailEnv & error)
{
error.clear();
return(DtMailCheckUnknown);
}
#endif /* DEAD_WOOD */
static int
countTypes(char ** types)
{
if (NULL == types) return 0;
for (int count = 0; *types; types++, count++) {
continue;
}
return(count);
}
void
V3BodyPart::getContentType(DtMailEnv &error, char **v3_type)
{
MutexLock lock_scope(_obj_mutex);
MutexLock dt_lib_lock(_DtMutex);
DtMailValueSeq value;
if (v3_type)
*v3_type = (char *)0;
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
if (error.isNotSet())
*v3_type = strdup(*(value[0]));
else
{
error.clear();
value.clear();
_body_env->getHeader(error, "X-Sun-Data-Type", DTM_FALSE, value);
if (error.isNotSet())
*v3_type = strdup(*(value[0]));
else
{
error.clear();
*v3_type = strdup("text");
}
}
}
void
V3BodyPart::getDtType(DtMailEnv & error)
{
MutexLock lock_scope(_obj_mutex);
MutexLock dt_lib_lock(_DtMutex);
// No need to clear the error object here because it should have
// been cleared by the object that instantiated it.
// error.clear();
char * v3_type;
DtMailValueSeq value;
_body_env->getHeader(error, "Content-Type", DTM_FALSE, value);
if (error.isNotSet()) {
v3_type = strdup(*(value[0]));
}
else {
error.clear();
value.clear();
_body_env->getHeader(error, "X-Sun-Data-Type", DTM_FALSE,
value);
if (error.isNotSet()) {
v3_type = strdup(*(value[0]));
}
else {
error.clear();
v3_type = strdup("text");
}
}
char ** types = DtDtsFindAttribute("SUNV3_TYPE", v3_type);
if (NULL != types)
{
if (countTypes(types) == 1) {
// We will use the first name. It may be wrong, but
// it is the best we can do at this point.
//
_body_type = strdup(types[0]);
DtDtsFreeDataTypeNames(types);
free(v3_type);
return;
}
DtDtsFreeDataTypeNames(types);
}
// We need the bits so we can type the buffer and get
// a type for the object. This is where things can get
// very slow for the user.
//
loadBody(error);
if (error.isSet()) {
return;
}
char * name = getName(error);
if (error.isSet()) {
// don't care about error conditions returned by getName().
error.clear();
}
// If the name is "Attachment" and the type is "text", then
// use the type as the name to avoid the buffer being called
// generic data.
//
if (name && strcasecmp(name, "attachment") == 0 &&
strcasecmp(v3_type, "text") == 0) {
free(name);
name = strdup(v3_type);
}
char * type = DtDtsBufferToDataType(_body, _body_decoded_len, name);
_body_type = strdup(type);
DtDtsFreeDataType(type);
free(name);
free(v3_type);
// error.clear();
}
void
V3BodyPart::loadBody(DtMailEnv &)
{
// For CHARSET
char *to_cs = NULL, *from_cs = NULL;
char *cs = new char[64];
// End of For CHARSET
int do_decode = 1;
if (_body) {
delete [] cs;
return;
}
// See if we are using an encoding.
DtMailValueSeq value;
DtMailEnv lerror;
_body_env->getHeader(lerror, "X-Sun-Encoding-Info",
DTM_FALSE, value);
if (lerror.isSet() || (_body_len == 0)) {
// No Encodings.
lerror.clear();
_body = (char *)_body_text;
_must_free_body = DTM_FALSE;
_body_decoded_len = _body_len;
// Before the codeset conversion code was put in, return here.
do_decode = 0;
}
if (do_decode) {
_body_decoded_len = 0;
_must_free_body = DTM_TRUE;
SunV3::decode(*(value[0]), &_body, _body_decoded_len,
_body_text, _body_len);
}
// For CHARSET
// If Content-Type is text, then get charset and do conversion.
// If Content-Type is X-sun-attachment, then if X-Sun-Data-Type is text,
// then get charset and do conversion.
// If Content-Type is missing, check if X-Sun-Data-Type exists, and
// if X-Sun-Data-Type exists and is text, then get charset and do conversion.
// If Content-Type and X-Sun-Data-Type are missing, then assume text so get
// charset and do conversion.
// Else don't need codeset conversion.
const char *cstmp = NULL;
const char *ct = NULL;
value.clear();
_body_env->getHeader(lerror, "Content-Type", DTM_FALSE, value);
if (lerror.isNotSet()) {
// Sun's V.3 Mail File Format requires a Content-Type header field to be
// "X-sun-attachment" for attachment message. X-Sun-Data-Type header
// field is also required for attachment message.
ct = *(value[0]);
if ( strcasecmp(ct, "X-sun-attachment") == 0 ) {
value.clear();
_body_env->getHeader(lerror, "X-Sun-Data-Type", DTM_FALSE, value);
if (lerror.isNotSet()) {
ct = *(value[0]);
if ( strcasecmp(ct, "text") == 0 ) {
// Get charset from X-Sun-Text-Type which contains the name of
// the codeset for the text-based body part. It is a mandatory
// header iff X-Sun-Data-Type is of type text.
value.clear();
_body_env->getHeader(lerror, "X-Sun-Text-Type", DTM_FALSE, value);
if (lerror.isNotSet()) {
cstmp = *(value[0]);
strcpy(cs, cstmp);
} else {
// We are not returning yet. We'll be flexible here.
// Some mailers may not set this field. We'll try to obtain charset
// from X-Sun-Charset or use the locale default. See below.
lerror.clear();
}
} else { // Attachment not text type
delete [] cs;
return;
}
} else {
// Required field for attachment message not set -- return!
delete [] cs;
return;
}
} else if ( strcasecmp(ct, "text") != 0 ) {
delete [] cs;
return;
}
} else { // Content-Type does not exist!
lerror.clear();
value.clear();
_body_env->getHeader(lerror, "X-Sun-Data-Type", DTM_FALSE, value);
if (lerror.isNotSet()) {
ct = *(value[0]);
if ( strcasecmp(ct, "text") == 0 ) {
// Get charset from X-Sun-Text-Type which contains the name of
// the codeset for the text-based body part. It is a mandatory
// header iff X-Sun-Data-Type is of type text.
value.clear();
_body_env->getHeader(lerror, "X-Sun-Text-Type", DTM_FALSE, value);
if (lerror.isNotSet()) {
cstmp = *(value[0]);
strcpy(cs, cstmp);
} else {
// We are not returning yet. We'll be flexible here.
// Some mailers may not set this field. We'll try to obtain charset
// from X-Sun-Charset or use the locale default. See below.
lerror.clear();
}
} else { // Attachment not text type
delete [] cs;
return;
}
} else {
// Base on Sun's V.3 Mail File Format version 1.9: If no Content-Type,
// and X-Sun-Data-Type is not set (means no/not attachment,
// then assume text. Proceed with getting charset.
lerror.clear();
}
}
if (cstmp == NULL) {
value.clear();
// Get charset from charset field
_body_env->getHeader(lerror, "X-Sun-Charset", DTM_FALSE, value);
if (lerror.isNotSet()) {
cstmp = *(value[0]);
strcpy(cs, cstmp);
} else { // No Charset
// We'll be flexible here. If Content-Type is missing or if Content-Type
// is text, then we get charset but if charset is missing, we'll try to
// convert from the locale specific default codeset.
lerror.clear();
char *ret = NULL;
strcpy(cs, "DEFAULT");
DtXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
setlocale(LC_CTYPE, NULL),
NULL,
NULL,
&ret);
strcpy(cs, "DEFAULT");
strcat(cs, ".");
strcat(cs, ret);
if ( ret )
free( ret );
}
} // If cstmp is NULL
// Handle ISO-2022-INT, RFC approved, or private encoding names
if ( strcasecmp(cs, "ISO-2022-INT-1") == 0 ) {
// Need to obtain charset from encoding
} // RFC approved and private names are not treated differently.
// Get iconv name from charset - this is the "from" name.
from_cs = NULL;
from_cs = csToConvName(cs);
// Get current locale's iconv name - this is the "to" name.
to_cs = NULL;
to_cs = locToConvName();
if ( from_cs && to_cs ) {
if ( strcasecmp(from_cs, to_cs) != 0 ) {
unsigned long tmp_len = (unsigned long) _body_decoded_len;
if (csConvert(&_body, tmp_len, (int)_must_free_body, from_cs, to_cs)) {
_must_free_body = DTM_TRUE;
_body_decoded_len = (int) tmp_len;
}
}
}
if ( from_cs )
free( from_cs );
if ( to_cs )
free ( to_cs );
// End of For CHARSET
delete [] cs;
}
char *
V3BodyPart::getDescription(DtMailEnv & error)
{
// No need to clear the error object here, whoever created it, cleared it.
// error.clear();
DtMailValueSeq value;
_body_env->getHeader(error, "X-Sun-Data-Description",
DTM_FALSE, value);
if (error.isNotSet()) {
return(strdup(*(value[0])));
}
error.clear(); // clear error so it doesn't propogate back up.
return(NULL);
}
char *
V3BodyPart::getName(DtMailEnv & error)
{
// No need to clear the error object here, it should be passed in already
// cleared.
// error.clear();
DtMailValueSeq value;
_body_env->getHeader(error, "X-Sun-Data-Name",
DTM_FALSE, value);
if (error.isNotSet()) {
return(strdup(*(value[0])));
}
// Since we are returning a valid name in spite of the call to
// getHeader returning an error, we should clear the error.
//
error.clear();
return(strdup("Attachment"));
}
void
V3BodyPart::setName(DtMailEnv & error, const char * name)
{
_body_env->setHeader(error, "X-Sun-Data-Name", DTM_TRUE, name);
}
unsigned long
V3BodyPart::getLength(DtMailEnv & error)
{
MutexLock lock_scope(_obj_mutex);
loadBody(error);
if (error.isSet()) {
// propogate the error back to the caller
return (0);
}
return(_body_decoded_len);
}
int
V3BodyPart::rfcSize(const char *, DtMailBoolean &)
{
return(0);
}
char *
V3BodyPart::writeBodyParts(char *buf)
{
return(buf);
}
// Do not need to implement this method because getHeader already
// returns the X-Sun-Charset value.
char *
V3BodyPart::csFromContentType(DtMailValueSeq&)
{
return NULL;
}

View File

@@ -0,0 +1,172 @@
/* ObjectCenter Project File */
/* Options for project */
unsetopt ansi
setopt auto_compile
unsetopt auto_reload
setopt auto_replace
unsetopt batch_load
unsetopt batch_run
setopt cc_prog cc
setopt ccargs -g
setopt primary_language C++
setopt cxx_prog /net/leaves/export/tools/compilers/CenterLine/bin/CC
setopt cxxargs +d -g
setopt demand_driven_level 3
setopt cxx_suffixes C c CC cc CXX cxx cpp H h HH hh HXX hxx hpp
setopt c_suffixes c h
setopt show_inheritance
setopt print_inherited
unsetopt print_static
setopt print_runtime_type
setopt tmpl_instantiate_obj
unsetopt tmpl_instantiate_flg
unsetopt create_file
unsetopt debug_child
unsetopt echo
unsetopt edit_jobs
unsetopt edit_line
unsetopt edit_line_file
unsetopt editor
unsetopt edit_query
unsetopt edit_line_query
unsetopt edit_pause
unsetopt edit_wakeup
unsetopt eight_bit
setopt email_address objectcenter-support@centerline.com
unsetopt ignore_sharp_lines
setopt instrument_all
setopt instrument_byte
setopt instrument_space 4
setopt histchar 35
setopt line_edit
unsetopt line_meta
setopt lint_load 2
setopt lint_run 2
setopt list_action
unsetopt load_flags
setopt long_not_int
setopt old_make
unsetopt make_args
setopt make_hfiles
unsetopt make_offset
setopt make_prog make
setopt make_symbol #
setopt mem_config 16384
unsetopt mem_trace
unsetopt page_cmds
setopt page_list 10
unsetopt page_load
unsetopt path
setopt proto_path . /net/leaves/export/tools/compilers/CenterLine/oc_2.0.0/sparc-solaris2/proto /net/leaves/export/tools/compilers/CenterLine/general/proto
unsetopt preprocessor
setopt program_name a.out
unsetopt print_custom
setopt print_pointer
setopt print_string 20
unsetopt save_memory
setopt sbrk_size 1048576
unsetopt swap_uses_path
setopt sys_load_cflags -L/lib -L/usr/lib -L/usr/local/lib -I/net/leaves/export/tools/compilers/CenterLine/include/CodeCenter -I/usr/include -Dunix -Dsun -Dsparc
setopt sys_load_cxxflags -L/object/CenterLine/sparc-solaris2/lib -L/lib -L/usr/lib -L/usr/local/lib -I/opt/CenterLine/clc++/sparc-solaris2/incl -I/opt/CenterLine/include/CodeCenter -I/usr/include -Dsun -DBSD -Dsparc -Dunix -D__STDC__=0 -L/usr/openwin/lib -L/net/zule/workspace/dt-tree/lib -I../../../lib -I../include/utils -I.. -I. -I../include -I../../dtcompat -I/net/zule/workspace/dt-tree/include -I/usr/openwin/include -DDTMAIL_TOOLTALK -DSunOS -DREL=53 -DDL_DYNAMIC_LIBS -DMMAP_NORESERVE
unsetopt tab_stop
unsetopt terse_suppress
unsetopt terse_where
setopt unset_value 191
unsetopt win_fork_nodup
unsetopt win_no_raise
unsetopt win_message_list
unsetopt win_project_list
/* Suppressions for project */
suppress 5
/* DEFAULT SUPPRESSION: Over/underflow unsigned <minus> */
suppress 7
/* DEFAULT SUPPRESSION: Over/underflow unsigned <plus> */
suppress 52
/* DEFAULT SUPPRESSION: Information lost <float> */
suppress 97 in xfree
/* DEFAULT SUPPRESSION: Freeing memory */
suppress 137
/* Bad Cast */
suppress 157 on __builtin_va_alist
/* DEFAULT SUPPRESSION: Formal variable */
suppress 465 /usr/include/
/* DEFAULT SUPPRESSION: */
suppress 481
/* DEFAULT SUPPRESSION: */
suppress 500 on alloca
/* DEFAULT SUPPRESSION: */
suppress 1075
/* DEFAULT SUPPRESSION: */
suppress 1076
/* DEFAULT SUPPRESSION: */
suppress 1102
/* DEFAULT SUPPRESSION: */
suppress 1103
/* DEFAULT SUPPRESSION: */
suppress 1104
/* DEFAULT SUPPRESSION: */
/* Contents of project */
load /lib/libc.so.1
load /usr/lib/libdl.so.1
load /net/leaves/export/tools/compilers/CenterLine/sparc-solaris2/lib/libC.so.2.0
load /net/zule/workspace/dt-tree/lib/libDtSvc.a
load /net/zule/workspace/dt-tree/lib/libtt.so.1
load /net/zule/workspace/dt-tree/lib/libXm.a
load /usr/dt/lib/libbento.so.1
load /usr/openwin/lib/libXt.so.4
load /usr/openwin/lib/libXext.so.0
load /usr/openwin/lib/libX11.so.4
load /usr/lib/libnsl.so.1
load /usr/lib/libsocket.so.1
load /usr/lib/libintl.so.1
load /usr/lib/libc.so.1
load /usr/lib/libw.so.1
load /usr/lib/libm.so.1
load -CXX DlDynamicLib.C DtMail.C DtMailBodyPart.C DtMailEnvelope.C DtMailMailBox.C DtMailMessage.C DtMailTransport.C DtMailValuesBuiltin.C DtMailXtProc.C
load -CXX DtVirtArray.C DynamicLib.C IO.C LanguagePortability.C MailRc.C MIMEBodyPart.C RFCBodyPart.C RFCEnvelope.C RFCMIME.C RFCMailBox.C RFCMessage.C
load -CXX Threads.C V3BodyPart.C BigMalloc.C SunV3.C Process.C md5.c xdr_utils.c
load RFCTransport.C Session.C
load dlopen /usr/lib/switch.so
load dlopen /usr/lib/nss_files.so.1
load dlopen /usr/openwin/lib/libX11.so
load /usr/ccs/lib/libgen.a
/* Instrumented files */
/* Signals caught and ignored */
catch HUP
catch INT
catch QUIT
catch ILL
catch TRAP
catch IOT
catch EMT
catch FPE
catch KILL
catch BUS
catch SEGV
catch SYS
catch PIPE
catch TERM
catch USR1
catch USR2
catch PWR
catch STOP
catch TSTP
catch TTIN
catch TTOU
catch XCPU
catch XFSZ
catch WAITING
catch LWP
ignore ALRM
ignore CLD
ignore WINCH
ignore URG
ignore POLL
ignore CONT
ignore VTALRM
ignore PROF
/* Status of project */