Commit 325e1a87 authored by Sam Varshavchik's avatar Sam Varshavchik

courier: implement utf-8 DSN address type.

Store ORCPT values internally in UTF-8. Decode ORCPT upon receipt, store
internally as UTF-8, reencode when sending a RCPT TO.
parent b7c750b0
......@@ -123,7 +123,6 @@ char *ualllower(const char *);
void gettmpfilenameargs(const char **, const char **, const char **);
void getnewtmpfilenameargs(const char **, const char **, const char **);
char *mktmpfilename();
char *dsnencodeorigaddr(const char *);
int freespace(const char *, /* Filename */
unsigned long *, /* # of blocks on fs */
......
......@@ -238,7 +238,7 @@ formatted as follows:</para>
<informalexample>
<programlisting format="linespecific">
address<token>&lt;tab&gt;</token>dsn<token>&lt;tab&gt;</token>orecipient
address<token>&lt;tab&gt;</token>dsn<token>&lt;tab&gt;</token>oreceipient
</programlisting>
</informalexample>
......@@ -248,11 +248,16 @@ by the tab character, then zero or more characters specifying <replaceable>dsn</
a tab character, then the <replaceable>orecipient</replaceable> value.</para>
<para>
<replaceable>dsn</replaceable> is zero or more of the following characters: S - send a delivery
status notification upon a successful delivery to this address, F - send a DSN
upon a failed delivery, D - send a DSN upon a mail delay, N - never send a
DSN. <replaceable>orecipient</replaceable> is the "Original Recipient", as specified in RFC1894,
using xtext encoding.</para>
<replaceable>dsn</replaceable> is zero or more of the following
characters: S - send a delivery
status notification upon a successful delivery to this address,
F - send a DSN upon a failed delivery,
D - send a DSN upon a mail delay,
N - never send a DSN.
<replaceable>oreceipient</replaceable> is the "Original Recipient",
as specified in RFC1894, except that is not encoded using xtext
encoding, but in unencoded UTF-8.
</para>
<para>
<command>submit</command> will print a response to each recipient (see "RESPONSES
......
......@@ -16,7 +16,6 @@ libcommon_la_SOURCES= aliases.h \
comconfig.c comconfig.h comctlfile.c \
comctlfile.h comdsn.c comdsn2.c comerrmsg.c \
commsgcancel.c commsgcancel.h comesmtpidstring.c comfax.c comfax.h \
comorigaddr.c \
comparseqid.c comparseqid.h comqueuename.c comqueuename.h \
comqueuename2.c \
comreadtime.c comreadtime.h comrwerrfunc.c comrwheader.c comrwmsg.c \
......
......@@ -125,13 +125,13 @@ static char deferred_status[2]={COMCTLFILE_DELDEFERRED, 0};
p->sender="";
p->receipients=(char **)courier_malloc(nreceipients*sizeof(char *));
p->oreceipients=(char **)courier_malloc(nreceipients*sizeof(char *));
p->oreceipients_utf8=(char **)courier_malloc(nreceipients*sizeof(char *));
p->dsnreceipients=(char **)courier_malloc(nreceipients*sizeof(char *));
p->delstatus=(char **)courier_malloc(nreceipients*sizeof(char *));
for (i=0; i<nreceipients; i++)
{
p->receipients[i]=p->oreceipients[i]=p->dsnreceipients[i]=0;
p->receipients[i]=p->oreceipients_utf8[i]=p->dsnreceipients[i]=0;
p->delstatus[i]=deferred_status;
}
......@@ -144,9 +144,9 @@ static char deferred_status[2]={COMCTLFILE_DELDEFERRED, 0};
case COMCTLFILE_RECEIPIENT:
p->receipients[rcnt++]=p->lines[i]+1;
break;
case COMCTLFILE_ORECEIPIENT:
case COMCTLFILE_ORECEIPIENTUTF8:
if (orcnt < nreceipients)
p->oreceipients[orcnt++]=p->lines[i]+1;
p->oreceipients_utf8[orcnt++]=p->lines[i]+1;
break;
case COMCTLFILE_DSN:
if (dsncnt < nreceipients)
......@@ -167,7 +167,7 @@ static char deferred_status[2]={COMCTLFILE_DELDEFERRED, 0};
void ctlfile_close(struct ctlfile *p)
{
free( p->oreceipients );
free( p->oreceipients_utf8 );
free( p->dsnreceipients );
free( p->receipients );
free( p->lines );
......
......@@ -46,7 +46,7 @@ struct ctlfile {
const char *sender; /* Envelope sender */
char **receipients; /* Receipients */
char **oreceipients; /* Original receipients */
char **oreceipients_utf8; /* Original receipients */
char **dsnreceipients; /* DSN flags */
char **delstatus; /* Per-receipient delivery status */
unsigned nreceipients; /* # of receipients */
......@@ -84,7 +84,7 @@ time_t ctlfile_getnextattempt(struct ctlfile *);
#define COMCTLFILE_SENDER 's'
#define COMCTLFILE_RECEIPIENT 'r'
#define COMCTLFILE_ORECEIPIENT 'R'
#define COMCTLFILE_ORECEIPIENTUTF8 'R'
#define COMCTLFILE_DSN 'N'
#define COMCTLFILE_ENVID 'e'
#define COMCTLFILE_AUTHNAME 'i'
......
/*
** Copyright 1998 - 1999 Double Precision, Inc.
** See COPYING for distribution information.
*/
#include "courier.h"
#include <stdlib.h>
char *dsnencodeorigaddr(const char *address)
{
int l=0;
char *p=0, *q=0;
const char *r;
int pass;
static const char x[16]="0123456789ABCDEF";
for (pass=0; pass<2; pass++)
{
if (pass) p=q=courier_malloc(l);
l=1;
for (r="rfc822;"; *r; r++)
{
if (pass) *q++= *r;
++l;
}
for (r=address; *r; r++)
{
if ( *r < '!' || *r > '~' || *r == '+' || *r == '=')
{
if (pass)
{
*q++='+';
*q++= x[ (int) (((*r) >> 4) & 0x0F) ];
*q++= x[ (int)((*r) & 0x0F) ];
}
l += 3;
}
else
{
if (pass) *q++= *r;
++l;
}
}
}
*q=0;
return (p);
}
......@@ -473,15 +473,12 @@ static int hexconvert(char a, char b)
static int is8bitreceipient(struct ctlfile *ctf, unsigned nreceipient)
{
int flag=0;
const char *p=ctf->oreceipients[nreceipient];
const char *p=ctf->oreceipients_utf8[nreceipient];
int infoptr;
if (p && *p)
if (p)
while (*p)
{
if (*p == '+' && p[1] && p[2] &&
hexconvert(p[1], p[2]) & 0x80)
return (1);
if (*p & 0x80)
return (1);
p++;
......@@ -535,18 +532,9 @@ static void print_xtext(FILE *fp, const char *xtext)
static void print_receipient(FILE *fp, struct ctlfile *ctf, unsigned n)
{
fputs(" <", fp);
if (ctf->oreceipients[n] &&
#if HAVE_STRNCASECMP
strncasecmp(ctf->oreceipients[n], "rfc822;", 7)
#else
strnicmp(ctf->oreceipients[n], "rfc822;", 7)
#endif
== 0)
print_xtext(fp, ctf->oreceipients[n]+7);
else
fprintf(fp, "%s", ctf->receipients[n]);
putc('>', fp);
fprintf(fp, "<%s>",
(ctf->oreceipients_utf8[n] && ctf->oreceipients_utf8[n][0]
? ctf->oreceipients_utf8[n] : ctf->receipients[n]));
}
/* Format delivery info in the plain text portion of the response. */
......@@ -1010,23 +998,18 @@ static int dodsn(struct ctlfile *ctf, FILE *fp, const char *sender,
fprintf(fp, "\nFinal-Recipient: rfc822; %s\nAction: %s\n",
ctf->receipients[i], action);
if (ctf->oreceipients[i] && ctf->oreceipients[i][0])
if (ctf->oreceipients_utf8[i] &&
ctf->oreceipients_utf8[i][0])
{
const char *c;
fprintf(fp, "Original-Recipient: ");
for (c=ctf->oreceipients[i]; *c; c++)
{
putc(*c, fp);
if (*c == ';')
{
putc(' ', fp);
c++;
break;
}
}
print_xtext(fp, c);
fprintf(fp, "\n");
char *encoded=rfc6533_encode(ctf->oreceipients_utf8[i],
0);
char *p=strchr(encoded, ';');
if (p) *p=0;
fprintf(fp, "Original-Recipient: %s; %s\n",
encoded,
ctf->oreceipients_utf8[i]);
free(encoded);
}
fprintf(fp, "Status: %s\n", status);
......
......@@ -32,6 +32,7 @@
#include "comsubmitclient.h"
#include "comreadtime.h"
#include "rfc822/rfc822.h"
#include "rfc2045/rfc2045.h"
#include "waitlib/waitlib.h"
#include "esmtpiov.h"
#include "esmtpconfig.h"
......@@ -775,8 +776,8 @@ static int rcpttolocal(const char *p, const char *r, const char *q)
static int dorcptto2(const char *p, const char *q)
{
int notifyn=0,notifyf=0,notifys=0,notifyd=0;
const char *orcpt=0;
int orcptlen=0;
char *orcpt_utf8=0;
size_t orcpt_utf8_len=0;
const char *r, *s;
char *t, *buf;
const char *relayclient=getenv("RELAYCLIENT");
......@@ -828,13 +829,24 @@ int rc;
#endif
== 0)
{
char *encoded_orcpt;
r += 6;
orcpt=r;
orcptlen=s-r;
encoded_orcpt=malloc(s-r+1);
if (!encoded_orcpt)
abort();
memcpy(encoded_orcpt, r, s-r);
encoded_orcpt[s-r]=0;
orcpt_utf8=rfc6533_decode(encoded_orcpt);
free(encoded_orcpt);
}
}
buf=courier_malloc(q-p + relayclientl + orcptlen + 10);
if (orcpt_utf8)
orcpt_utf8_len=strlen(orcpt_utf8);
buf=courier_malloc(q-p + relayclientl + orcpt_utf8_len + 10);
memcpy(buf, p, q-p);
t=buf + (q-p);
if (relayclientl)
......@@ -854,9 +866,12 @@ int rc;
*t++ = 'D';
}
*t++ = '\t';
if (orcptlen)
memcpy(t, orcpt, orcptlen);
t[orcptlen]=0;
if (orcpt_utf8_len)
memcpy(t, orcpt_utf8, orcpt_utf8_len);
t[orcpt_utf8_len]=0;
if (orcpt_utf8)
free(orcpt_utf8);
submit_write_message(buf);
free(buf);
......
......@@ -845,7 +845,7 @@ static struct esmtp_rcpt_info *mk_rcpt_info(struct moduledel *del,
p[i].address=del->receipients[i*2+1];
p[i].dsn_options=ctf->dsnreceipients[n];
p[i].orig_receipient=ctf->oreceipients[n];
p[i].orig_receipient=ctf->oreceipients_utf8[n];
}
return p;
......
......@@ -2028,13 +2028,6 @@ static void mk_one_receip_idna_or_utf8(struct esmtp_info *info,
receip->our_rcpt_error=libesmtp_unicode_err;
return;
}
for (p=utf8_or_idna_orig_receip; p && *p; ++p)
if ( (*p) & 0x80 )
{
receip->our_rcpt_error=libesmtp_unicode_err;
return;
}
}
(*builder)("RCPT TO:<", arg);
......@@ -2091,8 +2084,11 @@ static void mk_one_receip_idna_or_utf8(struct esmtp_info *info,
if (utf8_or_idna_orig_receip)
{
char *encoded=rfc6533_encode(utf8_or_idna_orig_receip,
!info->hassmtputf8);
(*builder)(" ORCPT=", arg);
(*builder)(utf8_or_idna_orig_receip, arg);
(*builder)(encoded, arg);
free(encoded);
}
(*builder)("\r\n", arg);
......
......@@ -394,6 +394,9 @@ static void dofwd(const char *addr, const char *from, const char *fromuser,
{
char *p;
if (!origuser)
origuser="";
p=strcat(strcat(strcpy(courier_malloc(
strlen(addr)+strlen(origuser)+4), addr),
"\tF\t"), origuser);
......@@ -435,18 +438,16 @@ char buf[BUFSIZ];
int waitstat;
char *sender=verp_getsender(ctf, ctf->receipients[rcptnum]);
const char *oreceipient;
char *oreceipients=0;
const char *oreceipient_utf8;
if ( ctf->oreceipients[rcptnum] == 0 ||
ctf->oreceipients[rcptnum][0])
if ( ctf->oreceipients_utf8[rcptnum] == 0 ||
ctf->oreceipients_utf8[rcptnum][0])
{
oreceipient=ctf->oreceipients[rcptnum];
oreceipient_utf8=ctf->oreceipients_utf8[rcptnum];
}
else
{
oreceipient=oreceipients=dsnencodeorigaddr(
ctf->receipients[rcptnum]);
oreceipient_utf8=ctf->receipients[rcptnum];
}
++maxfd;
......@@ -492,7 +493,7 @@ char *oreceipients=0;
char *fwduser_ace=udomainace(fwduser);
fwdmsg(buf, l, sender, fwduser_ace,
oreceipient);
oreceipient_utf8);
free(fwduser_ace);
}
}
......@@ -574,14 +575,10 @@ char *oreceipients=0;
"Message delivered.",
COMCTLFILE_DELSUCCESS, " l");
}
if (oreceipients)
free (oreceipients);
return;
case EX_SOFTWARE:
ctlfile_append_reply(ctf, rcptnum,
"", COMCTLFILE_DELFAIL_NOTRACK, 0);
if (oreceipients)
free (oreceipients);
return;
......@@ -599,12 +596,8 @@ char *oreceipients=0;
default:
ctlfile_append_reply(ctf, rcptnum,
"", COMCTLFILE_DELDEFERRED, 0);
if (oreceipients)
free (oreceipients);
return;
}
ctlfile_append_reply(ctf, rcptnum, "", COMCTLFILE_DELFAIL, 0);
if (oreceipients)
free (oreceipients);
}
......@@ -2436,10 +2436,7 @@ static std::string checkrcpt(struct rcptinfo *my_rcptinfo,
if (*oaddress == 0)
{
char *p=dsnencodeorigaddr(address);
oaddressbuf=p;
free(p);
oaddressbuf=address;
oaddress=oaddressbuf.c_str();
}
......
......@@ -239,7 +239,7 @@ void SubmitFile::AddReceipient(const char *r,
if (ctlfile.fd() < 0)
openctl();
ctlfile << COMCTLFILE_RECEIPIENT << r << std::endl
<< COMCTLFILE_ORECEIPIENT << (orig ? orig:"") << std::endl
<< COMCTLFILE_ORECEIPIENTUTF8 << (orig ? orig:"") << std::endl
<< COMCTLFILE_DSN << (dsn ? dsn:"") << std::endl;
if (delivered)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment