/*
* ratSender.c --
*
* This is the subprocess which handles the actual sending of messages.
*
*
* TkRat software and its included text is Copyright 1996-2002 by
* Martin Forssén
*
* The full text of the legal notice is contained in the file called
* COPYRIGHT, included with this distribution.
*/
#include "ratFolder.h"
#include "ratPGP.h"
/*
* This is a list of outstanding commands
*/
typedef struct CmdList {
char *cmd;
struct CmdList *next;
} CmdList;
static CmdList *cmdList = NULL;
/*
* Create bodypart s procedure
*/
static BODY *RatCreateBody(Tcl_Interp *interp, char *handler, ENVELOPE *env,
int *errorFlag, Tcl_Obj *files, const char *role);
static int RatSenderSend(Tcl_Interp *interp, const char *prefix,
Tcl_Obj *usedArraysPtr, Tcl_Obj *files, int *hardError);
static void RatSenderStanddown(Tcl_Interp *interp);
static int RatParseParameter(Tcl_Interp *interp, const char *src,
PARAMETER **dstPtrPtr);
/*
*----------------------------------------------------------------------
*
* RatSender --
*
* This routine runs the sending process.
*
* Results:
* None, this routine never returns
*
* Side effects:
* Messages may be sent
*
*
*----------------------------------------------------------------------
*/
void
RatSender(Tcl_Interp *interp)
{
Tcl_DString result;
CONST84 char **sendlistArgv, **argv;
char *buf;
CmdList *cmdPtr;
int sendlistArgc, objc, i, s, buflen, hardError = 0, argc;
Tcl_Obj *usedArraysPtr, **objv, *filesPtr;
/*
* Clear cached passwords
*/
ClearPGPPass(NULL);
Tcl_DStringInit(&result);
buflen = 1024;
buf = (char*)ckalloc(buflen);
while (1) {
if (cmdList) {
cmdPtr = cmdList;
strlcpy(buf, cmdList->cmd, buflen);
cmdList = cmdList->next;
ckfree(cmdPtr->cmd);
ckfree(cmdPtr);
} else {
i = 0;
while (buf[buflen-2] = '\0',
fgets(buf+i, buflen-i, stdin)
&& buflen-i-1 == strlen(buf+i)
&& buf[buflen-2] != '\n') {
i = buflen-1;
buflen += 1024;
buf = ckrealloc(buf, buflen);
}
if (feof(stdin)) {
exit(0);
}
}
if (!strncmp(buf, "SEND", 4)) {
(void)Tcl_SplitList(interp, buf, &sendlistArgc, &sendlistArgv);
for (s=1; s<sendlistArgc && !hardError; s++) {
(void)Tcl_SplitList(interp, sendlistArgv[s], &argc, &argv);
usedArraysPtr = Tcl_NewObj();
filesPtr = Tcl_NewObj();
Tcl_DStringSetLength(&result, 0);
if (TCL_OK == RatSenderSend(interp, argv[1], usedArraysPtr,
filesPtr, &hardError)){
Tcl_DStringAppendElement(&result, "SENT");
Tcl_DStringAppendElement(&result, argv[0]);
Tcl_ListObjGetElements(interp, filesPtr, &objc, &objv);
for (i=0; i<objc; i++) {
(void)unlink(Tcl_GetString(objv[i]));
}
} else {
Tcl_DStringAppendElement(&result, "FAILED");
Tcl_DStringAppendElement(&result, argv[0]);
Tcl_DStringAppendElement(&result, argv[1]);
Tcl_DStringAppendElement(&result,
Tcl_GetStringResult(interp));
sprintf(buf, "%d", hardError);
Tcl_DStringAppendElement(&result, buf);
}
ckfree(argv);
Tcl_ListObjGetElements(interp, usedArraysPtr, &objc, &objv);
for (i=0; i < objc; i++) {
(void)Tcl_UnsetVar(interp, Tcl_GetString(objv[i]),
TCL_GLOBAL_ONLY);
}
Tcl_DecrRefCount(usedArraysPtr);
Tcl_DecrRefCount(filesPtr);
for (i=Tcl_DStringLength(&result)-1; i>=0; i--) {
if ('\n' == Tcl_DStringValue(&result)[i]) {
Tcl_DStringValue(&result)[i] = ' ';
}
}
fwrite(Tcl_DStringValue(&result), Tcl_DStringLength(&result)+1,
1, stdout);
fflush(stdout);
}
ckfree(sendlistArgv);
RatSenderStanddown(interp);
} else if (!strncmp(buf, "RSET", 4)) {
hardError = 0;
} else {
exit(0);
}
}
/* Notreached */
exit(0);
}
/*
*----------------------------------------------------------------------
*
* RatSenderSend --
*
* Send a specified message
*
* Results:
* A standard tcl result.
*
* Side effects:
* A message is sent.
*
*
*----------------------------------------------------------------------
*/
static int
RatSenderSend(Tcl_Interp *interp, const char *prefix, Tcl_Obj *usedArraysPtr,
Tcl_Obj *filesPtr, int *hardError)
{
int listObjc, i, errorFlag = 0, requestDSN, verbose, listArgc;
char *tmp, buf[1024], *handler, *header = NULL, host[1024], *s;
const char *role, *ctmp, *saveTo;
CONST84 char **listArgv;
SMTPChannel smtpChannel = NULL;
Tcl_Obj *oPtr, *rPtr, **listObjv;
Tcl_DString ds;
ENVELOPE *env;
BODY *body;
/*
* Extract the message
*/
if (TCL_OK != RatHoldExtract(interp, prefix, usedArraysPtr, filesPtr)) {
return TCL_ERROR;
}
handler = cpystr(Tcl_GetStringResult(interp));
role = Tcl_GetVar2(interp, handler, "role", 0);
/*
* Check hostname to use for unqualified addresses
*/
strlcpy(host, RatGetCurrent(interp, RAT_HOST, role), sizeof(host));
/*
* Construct the headers
*/
if (!(oPtr = Tcl_GetVar2Ex(interp, handler, "request_dsn",TCL_GLOBAL_ONLY))
|| TCL_OK != Tcl_GetBooleanFromObj(interp, oPtr, &requestDSN)) {
requestDSN = 0;
}
env = mail_newenvelope ();
RatGenerateAddresses(interp, role, handler, &env->from, &env->sender);
buf[0] = '\0';
tmp = cpystr(Tcl_GetVar2(interp, handler, "to", TCL_GLOBAL_ONLY));
rfc822_parse_adrlist(&env->to, tmp, host);
ckfree(tmp);
RatEncodeAddresses(interp, env->to);
env->remail = cpystr(Tcl_GetVar2(interp,handler,"remail",TCL_GLOBAL_ONLY));
if (NULL == (env->date =
(char*)Tcl_GetVar2(interp,handler, "date",TCL_GLOBAL_ONLY))) {
rfc822_date(buf);
env->date = buf;
}
env->date = cpystr(env->date);
if ((ctmp = Tcl_GetVar2(interp, handler, "reply_to", TCL_GLOBAL_ONLY))
&& !RatIsEmpty(ctmp)) {
tmp = cpystr(ctmp);
rfc822_parse_adrlist(&env->reply_to, tmp, host);
ckfree(tmp);
RatEncodeAddresses(interp, env->reply_to);
}
oPtr = Tcl_GetVar2Ex(interp, handler, "subject", TCL_GLOBAL_ONLY);
if (oPtr && 0 < Tcl_GetCharLength(oPtr)) {
env->subject = cpystr(RatEncodeHeaderLine(interp, oPtr, 9));
}
if ((ctmp = Tcl_GetVar2(interp, handler, "cc", TCL_GLOBAL_ONLY))
&& !RatIsEmpty(ctmp)) {
tmp = cpystr(ctmp);
rfc822_parse_adrlist(&env->cc, tmp, host);
ckfree(tmp);
RatEncodeAddresses(interp, env->cc);
}
if ((ctmp = Tcl_GetVar2(interp, handler, "bcc", TCL_GLOBAL_ONLY))
&& !RatIsEmpty(ctmp)) {
tmp = cpystr(ctmp);
rfc822_parse_adrlist(&env->bcc, tmp, host);
ckfree(tmp);
RatEncodeAddresses(interp, env->bcc);
}
env->in_reply_to = cpystr(Tcl_GetVar2(interp, handler, "in_reply_to",
TCL_GLOBAL_ONLY));
env->message_id = cpystr(Tcl_GetVar2(interp, handler, "message_id",
TCL_GLOBAL_ONLY));
env->newsgroups = NULL;
/*
* Construct the body
*/
if ((ctmp = Tcl_GetVar2(interp, handler, "body", TCL_GLOBAL_ONLY))) {
body = RatCreateBody(interp, (char*)ctmp, env, &errorFlag, filesPtr,
role);
} else {
body = mail_newbody ();
}
if (errorFlag) {
goto error;
}
/*
* Send the message
*/
header = (char*)ckalloc(RatHeaderSize(env, body));
oPtr = Tcl_GetVar2Ex(interp, "option", "smtp_verbose", TCL_GLOBAL_ONLY);
Tcl_GetIntFromObj(interp, oPtr, &verbose);
if (1 == verbose) {
RatLogF(interp, RAT_PARSE, "sending_message", RATLOG_EXPLICIT);
}
snprintf(buf, sizeof(buf), "%s,sendprot", role);
ctmp = Tcl_GetVar2(interp, "option", buf, TCL_GLOBAL_ONLY);
if (ctmp && !strcmp(ctmp, "smtp")) {
int reuseChannel;
oPtr = Tcl_GetVar2Ex(interp, "option", "smtp_reuse", TCL_GLOBAL_ONLY);
Tcl_GetBooleanFromObj(interp, oPtr, &reuseChannel);
listObjc = 0;
snprintf(buf, sizeof(buf), "%s,smtp_hosts", role);
if ((oPtr = Tcl_GetVar2Ex(interp, "option", buf, TCL_GLOBAL_ONLY))) {
Tcl_ListObjGetElements(interp, oPtr, &listObjc, &listObjv);
}
if (0 == listObjc) {
Tcl_SetResult(interp,
"Configuration error; no valid SMTP hosts given",
TCL_STATIC);
*hardError = 1;
goto error;
}
for (i=0; !smtpChannel && i<listObjc; i++) {
smtpChannel = RatSMTPOpen(interp, Tcl_GetString(listObjv[i]),
verbose, role);
}
if (!smtpChannel) {
Tcl_SetResult(interp, "No valid SMTP hosts", TCL_STATIC);
*hardError = 1;
goto error;
}
if (TCL_OK != RatSMTPSend(interp, smtpChannel, env, body, requestDSN,
verbose)) {
rPtr = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(rPtr);
RatSMTPClose(interp, smtpChannel, verbose);
Tcl_SetObjResult(interp, rPtr);
Tcl_DecrRefCount(rPtr);
goto error;
}
if (!reuseChannel) {
RatSMTPClose(interp, smtpChannel, verbose);
}
} else if (ctmp && !strcmp(ctmp, "prog")) {
Tcl_Channel channel;
ADDRESS *adrPtr;
snprintf(buf, sizeof(buf), "%s,sendprog_8bit", role);
oPtr = Tcl_GetVar2Ex(interp, "option", buf, TCL_GLOBAL_ONLY);
Tcl_GetBooleanFromObj(interp, oPtr, &i);
snprintf(buf, sizeof(buf), "%s,sendprog", role);
if (NULL == (ctmp = RatGetPathOption(interp, buf))) {
Tcl_SetResult(interp, "Invalid send program", TCL_STATIC);
*hardError = 1;
goto error;
}
Tcl_DStringInit(&ds);
Tcl_DStringAppendElement(&ds, ctmp);
Tcl_DStringAppendElement(&ds, "-i");
for (adrPtr = env->to; adrPtr; adrPtr = adrPtr->next) {
if (RatAddressSize(adrPtr, 0) > sizeof(buf)-1) {
Tcl_SetResult(interp, "Ridiculously long address", TCL_STATIC);
*hardError = 1;
goto error;
} else {
buf[0] = '\0';
rfc822_address(buf, adrPtr);
Tcl_DStringAppendElement(&ds, buf);
}
}
for (adrPtr = env->cc; adrPtr; adrPtr = adrPtr->next) {
if (RatAddressSize(adrPtr, 0) > sizeof(buf)-1) {
Tcl_SetResult(interp, "Ridiculously long address", TCL_STATIC);
*hardError = 1;
goto error;
} else {
buf[0] = '\0';
rfc822_address(buf, adrPtr);
Tcl_DStringAppendElement(&ds, buf);
}
}
for (adrPtr = env->bcc; adrPtr; adrPtr = adrPtr->next) {
if (RatAddressSize(adrPtr, 0) > sizeof(buf)-1) {
Tcl_SetResult(interp, "Ridiculously long address", TCL_STATIC);
*hardError = 1;
goto error;
} else {
buf[0] = '\0';
rfc822_address(buf, adrPtr);
Tcl_DStringAppendElement(&ds, buf);
}
}
Tcl_ResetResult(interp);
if (TCL_OK != Tcl_SplitList(interp, Tcl_DStringValue(&ds),
&listArgc, &listArgv)
|| (NULL == (channel = Tcl_OpenCommandChannel(interp, listArgc,
listArgv, TCL_STDIN|TCL_STDOUT|TCL_STDERR)))) {
rPtr = Tcl_NewStringObj("Failed to run send program: ", -1);
Tcl_AppendToObj(rPtr, Tcl_GetStringResult(interp), -1);
Tcl_SetObjResult(interp, rPtr);
goto error;
} else {
Tcl_DStringFree(&ds);
ckfree(listArgv);
rfc822_output(header, env, body, RatTclPutsSendmail, channel, i);
Tcl_Close(interp, channel);
}
} else {
snprintf(buf, sizeof(buf), "Invalid send protocol '%s'",
tmp ? tmp : "<NULL>");
Tcl_SetResult(interp, buf, TCL_VOLATILE);
*hardError = 1;
goto error;
}
if (verbose) {
RatLog(interp, RAT_PARSE, "", RATLOG_EXPLICIT);
}
saveTo = Tcl_GetVar2(interp, handler, "save_to", TCL_GLOBAL_ONLY);
if (saveTo && *saveTo) {
MESSAGECACHE elt;
Tcl_DString saveArg, ds;
Tcl_Channel channel;
char saveFile[1024];
struct tm *tmPtr;
time_t now;
int perm;
Tcl_DStringInit(&saveArg);
Tcl_DStringInit(&ds);
ctmp = Tcl_GetVar(interp, "rat_tmp", TCL_GLOBAL_ONLY);
RatGenId(NULL, interp, 0, NULL);
snprintf(saveFile, sizeof(saveFile), "%s/rat.%s",
ctmp, Tcl_GetStringResult(interp));
oPtr = Tcl_GetVar2Ex(interp, "option", "permissions", TCL_GLOBAL_ONLY);
Tcl_GetIntFromObj(interp, oPtr, &perm);
if (NULL == (channel=Tcl_OpenFileChannel(interp,saveFile,"a",perm))){
Tcl_AppendResult(interp, "Failed to save copy of message: ",
Tcl_PosixError(interp), (char*) NULL);
goto error;
}
rfc822_output(header, env, body, RatTclPuts, channel, 1);
Tcl_Close(interp, channel);
Tcl_DStringAppendElement(&saveArg, saveFile);
Tcl_DStringAppendElement(&saveArg, saveTo);
Tcl_DStringSetLength(&ds, RatAddressSize(env->to, 1));
Tcl_DStringValue(&ds)[0] = '\0';
rfc822_write_address(Tcl_DStringValue(&ds), env->to);
Tcl_DStringSetLength(&ds, strlen(Tcl_DStringValue(&ds)));
Tcl_DStringAppendElement(&saveArg,
RatDecodeHeader(interp, Tcl_DStringValue(&ds), 1));
if (env->from) {
Tcl_DStringSetLength(&ds, RatAddressSize(env->from, 1));
Tcl_DStringValue(&ds)[0] = '\0';
rfc822_write_address(Tcl_DStringValue(&ds), env->from);
Tcl_DStringSetLength(&ds, strlen(Tcl_DStringValue(&ds)));
} else {
s = RatGetCurrent(interp, RAT_MAILBOX, role);
Tcl_DStringSetLength(&ds, strlen(s) + strlen(host)+2);
sprintf(Tcl_DStringValue(&ds), "%s@%s", s, host);
}
Tcl_DStringAppendElement(&saveArg,
RatDecodeHeader(interp, Tcl_DStringValue(&ds), 1));
Tcl_DStringSetLength(&ds, RatAddressSize(env->cc, 1));
Tcl_DStringValue(&ds)[0] = '\0';
rfc822_write_address(Tcl_DStringValue(&ds), env->cc);
Tcl_DStringSetLength(&ds, strlen(Tcl_DStringValue(&ds)));
Tcl_DStringAppendElement(&saveArg,
RatDecodeHeader(interp, Tcl_DStringValue(&ds), 1));
Tcl_DStringAppendElement(&saveArg, env->message_id);
Tcl_DStringAppendElement(&saveArg,
(env->in_reply_to ? env->in_reply_to : env->references));
Tcl_DStringAppendElement(&saveArg,
RatDecodeHeader(interp, env->subject, 0));
Tcl_DStringAppendElement(&saveArg, flag_name[RAT_SEEN].imap_name);
now = time(NULL);
tmPtr = gmtime(&now);
elt.day = tmPtr->tm_mday;
elt.month = tmPtr->tm_mon+1;
elt.year = tmPtr->tm_year+1900-BASEYEAR;
elt.hours = tmPtr->tm_hour;
elt.minutes = tmPtr->tm_min;
elt.seconds = tmPtr->tm_sec;
elt.zoccident = 0;
elt.zhours = 0;
elt.zminutes = 0;
Tcl_DStringAppendElement(&saveArg, mail_date(buf, &elt));
fprintf(stdout, "SAVE %s", Tcl_DStringValue(&saveArg));
fputc('\0', stdout);
fflush(stdout);
Tcl_DStringFree(&saveArg);
}
mail_free_envelope(&env);
mail_free_body(&body);
ckfree(header);
return TCL_OK;
error:
if (verbose) {
RatLog(interp, RAT_PARSE, "", RATLOG_EXPLICIT);
}
ckfree(header);
mail_free_envelope(&env);
mail_free_body(&body);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* RatSenderStanddown --
*
* Closes the open SMTP channel (if open)
*
* Results:
* None
*
* Side effects:
* All open SMTP channels are closed.
*
*
*----------------------------------------------------------------------
*/
static void
RatSenderStanddown(Tcl_Interp *interp)
{
int verbose;
Tcl_Obj *oPtr;
oPtr = Tcl_GetVar2Ex(interp, "option", "smtp_verbose", TCL_GLOBAL_ONLY);
Tcl_GetIntFromObj(interp, oPtr, &verbose);
RatSMTPCloseAll(interp, verbose);
}
/*
*----------------------------------------------------------------------
*
* RatCreateBody --
*
* See ../doc/interface
*
* Results:
* The return value is normally TCL_OK and the result can be found
* in the result area. If something goes wrong TCL_ERROR is returned
* and an error message will be left in the result area.
*
* Side effects:
* None.
*
*
*----------------------------------------------------------------------
*/
static BODY*
RatCreateBody(Tcl_Interp *interp, char *handler, ENVELOPE *env,
int *errorFlag, Tcl_Obj *filesPtr, const char *role)
{
BODY *body = mail_newbody();
CONST84 char *type;
CONST84 char *encoding;
CONST84 char *parameter;
char buf[1024];
CONST84 char *filename = NULL;
CONST84 char *children;
int pgp_sign, pgp_encrypt;
Tcl_Obj *oPtr;
if (NULL == (type = Tcl_GetVar2(interp, handler, "type",
TCL_GLOBAL_ONLY))) {
Tcl_SetResult(interp, "Internal error, no bhandler(type)", TCL_STATIC);
(*errorFlag)++;
return body;
}
if (!strcasecmp(type, "text")) body->type = TYPETEXT;
else if (!strcasecmp(type, "multipart")) body->type = TYPEMULTIPART;
else if (!strcasecmp(type, "message")) body->type = TYPEMESSAGE;
else if (!strcasecmp(type, "application")) body->type = TYPEAPPLICATION;
else if (!strcasecmp(type, "audio")) body->type = TYPEAUDIO;
else if (!strcasecmp(type, "image")) body->type = TYPEIMAGE;
else if (!strcasecmp(type, "video")) body->type = TYPEVIDEO;
else body->type = TYPEOTHER;
if (NULL == (encoding = Tcl_GetVar2(interp, handler, "encoding",
TCL_GLOBAL_ONLY))) {
body->encoding = ENC7BIT;
} else {
if (!strcasecmp(encoding, "7bit")) body->encoding = ENC7BIT;
else if (!strcasecmp(encoding, "8bit")) body->encoding = ENC8BIT;
else if (!strcasecmp(encoding, "binary")) body->encoding = ENCBINARY;
else if (!strcasecmp(encoding, "base64")) body->encoding = ENCBASE64;
else if (!strcasecmp(encoding, "quoted-printable"))
body->encoding = ENCQUOTEDPRINTABLE;
else {
snprintf(buf, sizeof(buf), "Unkown encoding %s\n", encoding);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
(*errorFlag)++;
}
}
/*
* Force all non-text and non-message bodyparts to binary
* (unless already encoded)
*/
if (TYPETEXT != body->type && TYPEMESSAGE != body->type
&& (ENC7BIT == body->encoding || ENC8BIT == body->encoding)) {
body->encoding = ENCBINARY;
}
if (NULL == (body->subtype = (char*)Tcl_GetVar2(interp, handler, "subtype",
TCL_GLOBAL_ONLY))) {
Tcl_SetResult(interp, "Internal error, no bhandler(subtype)",
TCL_STATIC);
(*errorFlag)++;
return body;
}
body->subtype = cpystr(body->subtype);
if ((parameter = (char*)Tcl_GetVar2(interp, handler, "parameter",
TCL_GLOBAL_ONLY))){
(*errorFlag) += RatParseParameter(interp, parameter, &body->parameter);
}
if ((parameter =
Tcl_GetVar2(interp, handler, "disp_parm", TCL_GLOBAL_ONLY))) {
(*errorFlag) += RatParseParameter(interp, parameter,
&body->disposition.parameter);
}
body->disposition.type = cpystr(Tcl_GetVar2(interp, handler,
"disp_type", TCL_GLOBAL_ONLY));
if (body->disposition.type && !strlen(body->disposition.type)) {
body->disposition.type = NULL;
}
body->id = cpystr(Tcl_GetVar2(interp, handler, "id", TCL_GLOBAL_ONLY));
if (body->id && !strlen(body->id)) {
body->id = NULL;
}
oPtr = Tcl_GetVar2Ex(interp, handler, "description", TCL_GLOBAL_ONLY);
if (oPtr) {
body->description = cpystr(RatEncodeHeaderLine(interp,oPtr,13));
}
if (body->description && !strlen(body->description)) {
body->description = NULL;
}
if (TYPEMULTIPART == body->type && NULL != (children =
Tcl_GetVar2(interp, handler, "children", TCL_GLOBAL_ONLY))) {
PART **partPtrPtr = &body->nested.part;
int childrenArgc, i;
CONST84 char **childrenArgv;
/* Convert to Tcl_Obj */
Tcl_SplitList(interp, children, &childrenArgc, &childrenArgv);
for (i=0; i<childrenArgc; i++) {
*partPtrPtr = mail_newbody_part();
(*partPtrPtr)->body =
*RatCreateBody(interp, (char*)childrenArgv[i],
env, errorFlag, filesPtr, role);
partPtrPtr = &(*partPtrPtr)->next;
}
} else if (TYPEMESSAGE == body->type) {
unsigned char *message;
if (NULL == (filename = Tcl_GetVar2(interp, handler,"filename",
TCL_GLOBAL_ONLY))) {
Tcl_SetResult(interp, "Internal error, no bhandler(filename)",
TCL_STATIC);
(*errorFlag)++;
return body;
}
message = RatReadFile(interp, filename, &body->contents.text.size, 1);
if (NULL == message) {
(*errorFlag)++;
return body;
}
body->nested.msg = RatParseMsg(interp, message);
body->contents.text.data = (unsigned char*)message;
} else {
unsigned char *data;
if (NULL == (filename = Tcl_GetVar2(interp, handler, "filename",
TCL_GLOBAL_ONLY))) {
Tcl_SetResult(interp, "Internal error, no bhandler(filename)",
TCL_STATIC);
(*errorFlag)++;
return body;
}
if (ENCBINARY != body->encoding && TYPETEXT == body->type) {
data = RatReadFile(interp, filename, &body->contents.text.size,1);
} else {
data = RatReadFile(interp, filename, &body->contents.text.size,0);
}
if (NULL == data) {
(*errorFlag)++;
return body;
}
body->contents.text.data = data;
body->size.bytes = body->contents.text.size;
if (TYPEMULTIPART == body->type) {
body->type = TYPEAPPLICATION;
ckfree(body->subtype);
body->subtype = cpystr("octet-stream");
}
}
if (filename) {
int removeFile = 0;
if ((oPtr=Tcl_GetVar2Ex(interp,handler,"removeFile",TCL_GLOBAL_ONLY))){
Tcl_GetBooleanFromObj(interp, oPtr, &removeFile);
}
if (removeFile && filesPtr) {
Tcl_ListObjAppendElement(interp, filesPtr,
Tcl_NewStringObj(filename, -1));
}
}
/*
* Do PGP signing and/or encryption
*/
if (!(oPtr = Tcl_GetVar2Ex(interp, handler, "pgp_sign",TCL_GLOBAL_ONLY)) ||
TCL_OK != Tcl_GetBooleanFromObj(interp, oPtr, &pgp_sign)) {
pgp_sign = 0;
}
if (!(oPtr = Tcl_GetVar2Ex(interp, handler,"pgp_encrypt",TCL_GLOBAL_ONLY))
|| TCL_OK != Tcl_GetBooleanFromObj(interp, oPtr, &pgp_encrypt)) {
pgp_encrypt = 0;
}
if (pgp_sign || pgp_encrypt) {
if (pgp_encrypt) {
body = RatPGPEncrypt(interp, env, body, pgp_sign);
} else {
snprintf(buf, sizeof(buf), "%s,pgp_keyid", role);
body = RatPGPSign(interp, env, body,
Tcl_GetVar2(interp, "option", buf,
TCL_GLOBAL_ONLY));
}
if (!body) {
Tcl_SetResult(interp, "Failed to do PGP operation", TCL_STATIC);
(*errorFlag)++;
return body;
}
}
return body;
}
/*
*----------------------------------------------------------------------
*
* RatParseParameter --
*
* Splits a parameter list into elements
*
* Results:
* number of encountered errors
*
* Side effects:
* None.
*
*
*----------------------------------------------------------------------
*/
static int
RatParseParameter(Tcl_Interp *interp, const char *src, PARAMETER **dstPtrPtr)
{
int parmListArgc, parmArgc, i, errcount = 0;
CONST84 char **parmListArgv, **parmArgv;
Tcl_Obj *oPtr;
char buf[1024];
/* Convert to Tcl_Obj? */
Tcl_SplitList(interp, src, &parmListArgc, &parmListArgv);
for (i=0; i<parmListArgc; i++) {
if (TCL_ERROR == Tcl_SplitList(interp, parmListArgv[i], &parmArgc,
&parmArgv) || 2 != parmArgc) {
snprintf(buf, sizeof(buf), "Illegal parameter: %s",
parmListArgv[i]);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
errcount++;
} else {
*dstPtrPtr = mail_newbody_parameter();
(*dstPtrPtr)->attribute = cpystr(parmArgv[0]);
oPtr = Tcl_NewStringObj(parmArgv[1], -1);
(*dstPtrPtr)->value = cpystr(RatEncodeHeaderLine(interp, oPtr, 0));
Tcl_DecrRefCount(oPtr);
dstPtrPtr = &(*dstPtrPtr)->next;
}
ckfree(parmArgv);
}
ckfree(parmListArgv);
return errcount;
}
/*
*----------------------------------------------------------------------
*
* RatSendPGPCommand --
*
* Sends a PGP command to the master and then waits for a reply.
*
* Results:
* A pointer to a static buffer containing the command.
*
* Side effects:
* Other commands that arrive while we are waiting are placed in cmdList
*
*
*----------------------------------------------------------------------
*/
char*
RatSendPGPCommand(char *cmd)
{
static char buf[1024];
CmdList **cmdPtrPtr;
fwrite(cmd, strlen(cmd)+1, 1, stdout);
fflush(stdout);
for (cmdPtrPtr = &cmdList; *cmdPtrPtr; cmdPtrPtr = &(*cmdPtrPtr)->next);
while(1) {
fgets(buf, sizeof(buf), stdin);
if (feof(stdin)) {
exit(0);
}
buf[strlen(buf)-1] = '\0';
if (strncmp("PGP ", buf, 4)) {
*cmdPtrPtr = (CmdList*)ckalloc(sizeof(CmdList));
(*cmdPtrPtr)->cmd = cpystr(buf);
(*cmdPtrPtr)->next = NULL;
cmdPtrPtr = &(*cmdPtrPtr)->next;
} else {
return buf+4;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1