Source from upstream; imap-2007f.tar.gz
MD5 2126fd125ea26b73b20f01fcd5940369
This commit is contained in:
40
src/ansilib/memmove.c
Normal file
40
src/ansilib/memmove.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Memory move
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Copy memory block
|
||||
* Accepts: destination pointer
|
||||
* source pointer
|
||||
* length
|
||||
* Returns: destination pointer
|
||||
*/
|
||||
|
||||
void *memmove (void *s,void *ct,size_t n)
|
||||
{
|
||||
bcopy (ct,s,n); /* they should have this one */
|
||||
return s;
|
||||
}
|
||||
49
src/ansilib/memmove2.c
Normal file
49
src/ansilib/memmove2.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Memory move when no bcopy()
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 11 May 1989
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Copy memory block
|
||||
* Accepts: destination pointer
|
||||
* source pointer
|
||||
* length
|
||||
* Returns: destination pointer
|
||||
*/
|
||||
|
||||
void *memmove (void *s,void *ct,size_t n)
|
||||
{
|
||||
char *dp,*sp;
|
||||
int i;
|
||||
unsigned long dest = (unsigned long) s;
|
||||
unsigned long src = (unsigned long) ct;
|
||||
if (((dest < src) && ((dest + n) < src)) ||
|
||||
((dest > src) && ((src + n) < dest))) return (void *) memcpy (s,ct,n);
|
||||
dp = (char *) s;
|
||||
sp = (char *) ct;
|
||||
if (dest < src) for (i = 0; i < n; ++i) dp[i] = sp[i];
|
||||
else if (dest > src) for (i = n - 1; i >= 0; --i) dp[i] = sp[i];
|
||||
return s;
|
||||
}
|
||||
40
src/ansilib/memset.c
Normal file
40
src/ansilib/memset.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Set memory
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
*
|
||||
* Date: 11 May 1989
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Set a block of memory
|
||||
* Accepts: destination pointer
|
||||
* value to set
|
||||
* length
|
||||
* Returns: destination pointer
|
||||
*/
|
||||
|
||||
void *memset (void *s,int c,size_t n)
|
||||
{
|
||||
if (c) while (n) s[--n] = c; /* this way if non-zero */
|
||||
else bzero (s,n); /* they should have this one */
|
||||
return s;
|
||||
}
|
||||
40
src/ansilib/strpbrk.c
Normal file
40
src/ansilib/strpbrk.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: String search for break character
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
*
|
||||
* Date: 11 May 1989
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Return pointer to first occurance in string of any delimiter
|
||||
* Accepts: source pointer
|
||||
* vector of delimiters pointer
|
||||
* Returns: pointer to delimiter or NIL if not found
|
||||
*/
|
||||
|
||||
char *strpbrk (char *cs,char *ct)
|
||||
{
|
||||
char *s;
|
||||
/* search for delimiter until end of string */
|
||||
for (; *cs; cs++) for (s = ct; *s; s++) if (*s == *cs) return cs;
|
||||
return NIL; /* not found */
|
||||
}
|
||||
45
src/ansilib/strstr.c
Normal file
45
src/ansilib/strstr.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Substring search
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
*
|
||||
* Date: 11 May 1989
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Return pointer to first occurance in string of a substring
|
||||
* Accepts: source pointer
|
||||
* substring pointer
|
||||
* Returns: pointer to substring in source or NIL if not found
|
||||
*/
|
||||
|
||||
char *strstr (char *cs,char *ct)
|
||||
{
|
||||
char *s;
|
||||
char *t;
|
||||
while (cs = strchr (cs,*ct)) {/* for each occurance of the first character */
|
||||
/* see if remainder of string matches */
|
||||
for (s = cs + 1, t = ct + 1; *t && *s == *t; s++, t++);
|
||||
if (!*t) return cs; /* if ran out of substring then have match */
|
||||
cs++; /* try from next character */
|
||||
}
|
||||
return NIL; /* not found */
|
||||
}
|
||||
67
src/ansilib/strtok.c
Normal file
67
src/ansilib/strtok.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: String return successive tokens
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
*
|
||||
* Date: 11 May 1989
|
||||
* Last Edited: 30 January 2007
|
||||
*/
|
||||
|
||||
/* Find token in string
|
||||
* Accepts: source pointer or NIL to use previous source
|
||||
* vector of token delimiters pointer
|
||||
* Returns: pointer to next token
|
||||
*/
|
||||
|
||||
static char *state = NIL; /* string to locate tokens */
|
||||
|
||||
char *strtok (char *s,char *ct)
|
||||
{
|
||||
return strtok_r (s,ct,&state);/* jacket into reentrant routine */
|
||||
}
|
||||
|
||||
|
||||
/* Find token in string (reentrant)
|
||||
* Accepts: source pointer or NIL to use previous source
|
||||
* vector of token delimiters pointer
|
||||
* returned state pointer
|
||||
* Returns: pointer to next token
|
||||
*/
|
||||
|
||||
char *strtok_r (char *s,char *ct,char **r)
|
||||
{
|
||||
char *t,*ts;
|
||||
if (!s) s = *r; /* use previous token if none specified */
|
||||
*r = NIL; /* default to no returned state */
|
||||
if (!(s && *s)) return NIL; /* no tokens left */
|
||||
/* find any leading delimiters */
|
||||
do for (t = ct, ts = NIL; *t; t++) if (*t == *s) {
|
||||
if (*(ts = ++s)) break; /* yes, restart search if more in string */
|
||||
return NIL; /* else no more tokens */
|
||||
} while (ts); /* continue until no more leading delimiters */
|
||||
/* can we find a new delimiter? */
|
||||
for (ts = s; *ts; ts++) for (t = ct; *t; t++) if (*t == *ts) {
|
||||
*ts++ = '\0'; /* yes, tie off token at that point */
|
||||
*r = ts; /* save subsequent tokens for future call */
|
||||
return s; /* return our token */
|
||||
}
|
||||
return s; /* return final token */
|
||||
}
|
||||
73
src/ansilib/strtoul.c
Normal file
73
src/ansilib/strtoul.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: String to unsigned long
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
*
|
||||
* Date: 14 February 1995
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/*
|
||||
* Turn a string unsigned long into the real thing
|
||||
* Accepts: source string
|
||||
* pointer to place to return end pointer
|
||||
* base
|
||||
* Returns: parsed unsigned long integer, end pointer is updated
|
||||
*/
|
||||
|
||||
unsigned long strtoul (char *t,char **endp,int base)
|
||||
{
|
||||
unsigned long value = 0; /* the accumulated value */
|
||||
int negative = 0; /* this a negative number? */
|
||||
unsigned char c,*s = t;
|
||||
if (base && (base < 2 || base > 36)) {
|
||||
errno = EINVAL; /* insist upon valid base */
|
||||
return value;
|
||||
}
|
||||
while (isspace (*s)) s++; /* skip leading whitespace */
|
||||
switch (*s) { /* check for leading sign char */
|
||||
case '-':
|
||||
negative = 1; /* yes, negative #. fall into '+' */
|
||||
case '+':
|
||||
s++; /* skip the sign character */
|
||||
}
|
||||
if (!base) { /* base not specified? */
|
||||
if (*s != '0') base = 10; /* must be decimal if doesn't start with 0 */
|
||||
/* starts with 0x? */
|
||||
else if (tolower (*++s) == 'x') {
|
||||
base = 16; /* yes, is hex */
|
||||
s++; /* skip the x */
|
||||
}
|
||||
else base = 8; /* ...or octal */
|
||||
}
|
||||
do { /* convert to numeric form if digit */
|
||||
if (isdigit (*s)) c = *s - '0';
|
||||
/* alphabetic conversion */
|
||||
else if (isalpha (*s)) c = *s - (isupper (*s) ? 'A' : 'a') + 10;
|
||||
else break; /* else no way it's valid */
|
||||
if (c >= base) break; /* digit out of range for base? */
|
||||
value = value * base + c; /* accumulate the digit */
|
||||
} while (*++s); /* loop until non-numeric character */
|
||||
if (tolower (*s) == 'l') s++; /* ignore 'l' or 'L' marker */
|
||||
if (endp) *endp = s; /* save users endp to after number */
|
||||
/* negate number if needed */
|
||||
return negative ? -value : value;
|
||||
}
|
||||
96
src/c-client/auth_ext.c
Normal file
96
src/c-client/auth_ext.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: EXTERNAL authenticator
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 6 April 2005
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
long auth_external_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user);
|
||||
char *auth_external_server (authresponse_t responder,int argc,char *argv[]);
|
||||
|
||||
AUTHENTICATOR auth_ext = { /* secure, has full auth, hidden */
|
||||
AU_SECURE | AU_AUTHUSER | AU_HIDE,
|
||||
"EXTERNAL", /* authenticator name */
|
||||
NIL, /* always valid */
|
||||
auth_external_client, /* client method */
|
||||
auth_external_server, /* server method */
|
||||
NIL /* next authenticator */
|
||||
};
|
||||
|
||||
/* Client authenticator
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* pointer to current trial count
|
||||
* returned user name
|
||||
* Returns: T if success, NIL otherwise, number of trials incremented if retry
|
||||
*/
|
||||
|
||||
long auth_external_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user)
|
||||
{
|
||||
void *challenge;
|
||||
unsigned long clen;
|
||||
long ret = NIL;
|
||||
*trial = 65535; /* never retry */
|
||||
if (challenge = (*challenger) (stream,&clen)) {
|
||||
fs_give ((void **) &challenge);
|
||||
/* send authorization id (empty string OK) */
|
||||
if ((*responder) (stream,strcpy (user,mb->user),strlen (mb->user))) {
|
||||
if (challenge = (*challenger) (stream,&clen))
|
||||
fs_give ((void **) &challenge);
|
||||
else ret = LONGT; /* check the authentication */
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Server authenticator
|
||||
* Accepts: responder function
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*/
|
||||
|
||||
char *auth_external_server (authresponse_t responder,int argc,char *argv[])
|
||||
{
|
||||
unsigned long len;
|
||||
char *authid;
|
||||
char *authenid = (char *) mail_parameters (NIL,GET_EXTERNALAUTHID,NIL);
|
||||
char *ret = NIL;
|
||||
/* get authorization identity */
|
||||
if (authenid && (authid = (*responder) ("",0,&len))) {
|
||||
/* note: responders null-terminate */
|
||||
if (*authid ? authserver_login (authid,authenid,argc,argv) :
|
||||
authserver_login (authenid,NIL,argc,argv)) ret = myusername ();
|
||||
fs_give ((void **) &authid);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
423
src/c-client/auth_gss.c
Normal file
423
src/c-client/auth_gss.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: GSSAPI authenticator
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 12 January 1998
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
long auth_gssapi_valid (void);
|
||||
long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user);
|
||||
long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
|
||||
authrespond_t responder,char *service,NETMBX *mb,
|
||||
void *stream,char *user,kinit_t ki);
|
||||
char *auth_gssapi_server (authresponse_t responder,int argc,char *argv[]);
|
||||
|
||||
|
||||
AUTHENTICATOR auth_gss = {
|
||||
AU_SECURE | AU_AUTHUSER, /* secure authenticator */
|
||||
"GSSAPI", /* authenticator name */
|
||||
auth_gssapi_valid, /* check if valid */
|
||||
auth_gssapi_client, /* client method */
|
||||
auth_gssapi_server, /* server method */
|
||||
NIL /* next authenticator */
|
||||
};
|
||||
|
||||
#define AUTH_GSSAPI_P_NONE 1
|
||||
#define AUTH_GSSAPI_P_INTEGRITY 2
|
||||
#define AUTH_GSSAPI_P_PRIVACY 4
|
||||
|
||||
#define AUTH_GSSAPI_C_MAXSIZE 8192
|
||||
|
||||
#define SERVER_LOG(x,y) syslog (LOG_ALERT,x,y)
|
||||
|
||||
/* Check if GSSAPI valid on this system
|
||||
* Returns: T if valid, NIL otherwise
|
||||
*/
|
||||
|
||||
long auth_gssapi_valid (void)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
OM_uint32 smn;
|
||||
gss_buffer_desc buf;
|
||||
gss_name_t name;
|
||||
/* make service name */
|
||||
sprintf (tmp,"%s@%s",(char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
|
||||
mylocalhost ());
|
||||
buf.length = strlen (buf.value = tmp);
|
||||
/* see if can build a name */
|
||||
if (gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&name) !=
|
||||
GSS_S_COMPLETE) return NIL;
|
||||
/* remove server method if no keytab */
|
||||
if (!kerberos_server_valid ()) auth_gss.server = NIL;
|
||||
gss_release_name (&smn,&name);/* finished with name */
|
||||
return LONGT;
|
||||
}
|
||||
|
||||
/* Client authenticator
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* pointer to current trial count
|
||||
* returned user name
|
||||
* Returns: T if success, NIL otherwise, number of trials incremented if retry
|
||||
*/
|
||||
|
||||
long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user)
|
||||
{
|
||||
gss_buffer_desc chal;
|
||||
kinit_t ki = (kinit_t) mail_parameters (NIL,GET_KINIT,NIL);
|
||||
long ret = NIL;
|
||||
*trial = 65535; /* never retry */
|
||||
/* get initial (empty) challenge */
|
||||
if (chal.value = (*challenger) (stream,(unsigned long *) &chal.length)) {
|
||||
if (chal.length) { /* abort if challenge non-empty */
|
||||
mm_log ("Server bug: non-empty initial GSSAPI challenge",WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
else if (mb->authuser[0] && strcmp (mb->authuser,myusername ())) {
|
||||
mm_log ("Can't use Kerberos: invalid /authuser",WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
else ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
|
||||
stream,user,ki);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Client authenticator worker function
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* returned user name
|
||||
* kinit function pointer if should retry with kinit
|
||||
* Returns: T if success, NIL otherwise
|
||||
*/
|
||||
|
||||
long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
|
||||
authrespond_t responder,char *service,NETMBX *mb,
|
||||
void *stream,char *user,kinit_t ki)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
OM_uint32 smj,smn,dsmj,dsmn;
|
||||
OM_uint32 mctx = 0;
|
||||
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
||||
gss_buffer_desc resp,buf;
|
||||
long i;
|
||||
int conf;
|
||||
gss_qop_t qop;
|
||||
gss_name_t crname = NIL;
|
||||
blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
|
||||
void *data;
|
||||
long ret = NIL;
|
||||
sprintf (tmp,"%s@%s",service,mb->host);
|
||||
buf.length = strlen (buf.value = tmp);
|
||||
/* get service name */
|
||||
if (gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&crname) !=
|
||||
GSS_S_COMPLETE) {
|
||||
mm_log ("Can't import Kerberos service name",WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
}
|
||||
else {
|
||||
data = (*bn) (BLOCK_SENSITIVE,NIL);
|
||||
/* negotiate with KDC */
|
||||
smj = gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,crname,NIL,
|
||||
GSS_C_INTEG_FLAG | GSS_C_MUTUAL_FLAG |
|
||||
GSS_C_REPLAY_FLAG,0,GSS_C_NO_CHANNEL_BINDINGS,
|
||||
GSS_C_NO_BUFFER,NIL,&resp,NIL,NIL);
|
||||
(*bn) (BLOCK_NONSENSITIVE,data);
|
||||
|
||||
/* while continuation needed */
|
||||
while (smj == GSS_S_CONTINUE_NEEDED) {
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
/* send response, get next challenge */
|
||||
i = (*responder) (stream,resp.value,resp.length) &&
|
||||
(chal.value = (*challenger) (stream,(unsigned long *) &chal.length));
|
||||
gss_release_buffer (&smn,&resp);
|
||||
if (i) { /* negotiate continuation with KDC */
|
||||
data = (*bn) (BLOCK_SENSITIVE,NIL);
|
||||
switch (smj = /* make sure continuation going OK */
|
||||
gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,
|
||||
crname,GSS_C_NO_OID,GSS_C_INTEG_FLAG |
|
||||
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,0,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,&chal,NIL,
|
||||
&resp,NIL,NIL)) {
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
case GSS_S_COMPLETE:
|
||||
break;
|
||||
default: /* error, don't need context any more */
|
||||
gss_delete_sec_context (&smn,&ctx,NIL);
|
||||
}
|
||||
(*bn) (BLOCK_NONSENSITIVE,data);
|
||||
}
|
||||
else { /* error in continuation */
|
||||
mm_log ("Error in negotiating Kerberos continuation",WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
/* don't need context any more */
|
||||
gss_delete_sec_context (&smn,&ctx,NIL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (smj) { /* done - deal with final condition */
|
||||
case GSS_S_COMPLETE:
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
/* get prot mechanisms and max size */
|
||||
if ((*responder) (stream,resp.value ? resp.value : "",resp.length) &&
|
||||
(chal.value = (*challenger) (stream,(unsigned long *)&chal.length))&&
|
||||
(gss_unwrap (&smn,ctx,&chal,&resp,&conf,&qop) == GSS_S_COMPLETE) &&
|
||||
(resp.length >= 4) && (*((char *) resp.value) & AUTH_GSSAPI_P_NONE)){
|
||||
/* make copy of flags and length */
|
||||
memcpy (tmp,resp.value,4);
|
||||
gss_release_buffer (&smn,&resp);
|
||||
/* no session protection */
|
||||
tmp[0] = AUTH_GSSAPI_P_NONE;
|
||||
/* install user name */
|
||||
strcpy (tmp+4,strcpy (user,mb->user[0] ? mb->user : myusername ()));
|
||||
buf.value = tmp; buf.length = strlen (user) + 4;
|
||||
/* successful negotiation */
|
||||
switch (smj = gss_wrap (&smn,ctx,NIL,qop,&buf,&conf,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
if ((*responder) (stream,resp.value,resp.length)) ret = T;
|
||||
gss_release_buffer (&smn,&resp);
|
||||
break;
|
||||
default:
|
||||
do switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
mctx = 0;
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
sprintf (tmp,"Unknown gss_wrap failure: %s",(char *) resp.value);
|
||||
mm_log (tmp,WARN);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
sprintf (tmp,"GSSAPI mechanism status: %s",(char *) resp.value);
|
||||
mm_log (tmp,WARN);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
(*responder) (stream,NIL,0);
|
||||
}
|
||||
}
|
||||
/* flush final challenge */
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
/* don't need context any more */
|
||||
gss_delete_sec_context (&smn,&ctx,NIL);
|
||||
break;
|
||||
|
||||
case GSS_S_CREDENTIALS_EXPIRED:
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
/* retry if application kinits */
|
||||
if (ki && (*ki) (mb->host,"Kerberos credentials expired"))
|
||||
ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
|
||||
stream,user,NIL);
|
||||
else { /* application can't kinit */
|
||||
sprintf (tmp,"Kerberos credentials expired (try running kinit) for %s",
|
||||
mb->host);
|
||||
mm_log (tmp,WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
}
|
||||
break;
|
||||
case GSS_S_FAILURE:
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE: /* end of message, can kinit? */
|
||||
if (ki && kerberos_try_kinit (smn) &&
|
||||
(*ki) (mb->host,(char *) resp.value)) {
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
|
||||
stream,user,NIL);
|
||||
break; /* done */
|
||||
}
|
||||
else (*responder) (stream,NIL,0);
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
sprintf (tmp,kerberos_try_kinit (smn) ?
|
||||
"Kerberos error: %.80s (try running kinit) for %.80s" :
|
||||
"GSSAPI failure: %s for %.80s",(char *) resp.value,mb->host);
|
||||
mm_log (tmp,WARN);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
} while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
break;
|
||||
|
||||
default: /* miscellaneous errors */
|
||||
if (chal.value) fs_give ((void **) &chal.value);
|
||||
do switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
mctx = 0;
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
sprintf (tmp,"Unknown GSSAPI failure: %s",(char *) resp.value);
|
||||
mm_log (tmp,WARN);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
sprintf (tmp,"GSSAPI mechanism status: %s",(char *) resp.value);
|
||||
mm_log (tmp,WARN);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
(*responder) (stream,NIL,0);
|
||||
break;
|
||||
}
|
||||
/* finished with credentials name */
|
||||
if (crname) gss_release_name (&smn,&crname);
|
||||
}
|
||||
return ret; /* return status */
|
||||
}
|
||||
|
||||
/* Server authenticator
|
||||
* Accepts: responder function
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*/
|
||||
|
||||
char *auth_gssapi_server (authresponse_t responder,int argc,char *argv[])
|
||||
{
|
||||
char *ret = NIL;
|
||||
char tmp[MAILTMPLEN];
|
||||
unsigned long maxsize = htonl (AUTH_GSSAPI_C_MAXSIZE);
|
||||
int conf;
|
||||
OM_uint32 smj,smn,dsmj,dsmn,flags;
|
||||
OM_uint32 mctx = 0;
|
||||
gss_name_t crname,name;
|
||||
gss_OID mech;
|
||||
gss_buffer_desc chal,resp,buf;
|
||||
gss_cred_id_t crd;
|
||||
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
||||
gss_qop_t qop = GSS_C_QOP_DEFAULT;
|
||||
/* make service name */
|
||||
sprintf (tmp,"%s@%s",(char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
|
||||
tcp_serverhost ());
|
||||
buf.length = strlen (buf.value = tmp);
|
||||
/* acquire credentials */
|
||||
if ((gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&crname)) ==
|
||||
GSS_S_COMPLETE) {
|
||||
if ((smj = gss_acquire_cred (&smn,crname,0,NIL,GSS_C_ACCEPT,&crd,NIL,NIL))
|
||||
== GSS_S_COMPLETE) {
|
||||
if (resp.value = (*responder) ("",0,(unsigned long *) &resp.length)) {
|
||||
do { /* negotiate authentication */
|
||||
smj = gss_accept_sec_context (&smn,&ctx,crd,&resp,
|
||||
GSS_C_NO_CHANNEL_BINDINGS,&name,&mech,
|
||||
&chal,&flags,NIL,NIL);
|
||||
/* don't need response any more */
|
||||
fs_give ((void **) &resp.value);
|
||||
switch (smj) { /* how did it go? */
|
||||
case GSS_S_COMPLETE: /* successful */
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
if (chal.value) { /* send challenge, get next response */
|
||||
resp.value = (*responder) (chal.value,chal.length,
|
||||
(unsigned long *) &resp.length);
|
||||
gss_release_buffer (&smn,&chal);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (resp.value && resp.length && (smj == GSS_S_CONTINUE_NEEDED));
|
||||
|
||||
/* successful exchange? */
|
||||
if ((smj == GSS_S_COMPLETE) &&
|
||||
(gss_display_name (&smn,name,&buf,&mech) == GSS_S_COMPLETE)) {
|
||||
/* send security and size */
|
||||
memcpy (resp.value = tmp,(void *) &maxsize,resp.length = 4);
|
||||
tmp[0] = AUTH_GSSAPI_P_NONE;
|
||||
if (gss_wrap (&smn,ctx,NIL,qop,&resp,&conf,&chal) == GSS_S_COMPLETE){
|
||||
resp.value = (*responder) (chal.value,chal.length,
|
||||
(unsigned long *) &resp.length);
|
||||
gss_release_buffer (&smn,&chal);
|
||||
if (gss_unwrap (&smn,ctx,&resp,&chal,&conf,&qop)==GSS_S_COMPLETE) {
|
||||
/* client request valid */
|
||||
if (chal.value && (chal.length > 4) &&
|
||||
(chal.length < (MAILTMPLEN - 1)) &&
|
||||
memcpy (tmp,chal.value,chal.length) &&
|
||||
(tmp[0] & AUTH_GSSAPI_P_NONE)) {
|
||||
/* tie off authorization ID */
|
||||
tmp[chal.length] = '\0';
|
||||
ret = kerberos_login (tmp+4,buf.value,argc,argv);
|
||||
}
|
||||
/* done with user name */
|
||||
gss_release_buffer (&smn,&chal);
|
||||
}
|
||||
/* finished with response */
|
||||
fs_give ((void **) &resp.value);
|
||||
}
|
||||
/* don't need name buffer any more */
|
||||
gss_release_buffer (&smn,&buf);
|
||||
}
|
||||
/* don't need client name any more */
|
||||
gss_release_name (&smn,&name);
|
||||
/* don't need context any more */
|
||||
if (ctx != GSS_C_NO_CONTEXT) gss_delete_sec_context (&smn,&ctx,NIL);
|
||||
}
|
||||
/* finished with credentials */
|
||||
gss_release_cred (&smn,&crd);
|
||||
}
|
||||
|
||||
else { /* can't acquire credentials! */
|
||||
if (gss_display_name (&dsmn,crname,&buf,&mech) == GSS_S_COMPLETE)
|
||||
SERVER_LOG ("Failed to acquire credentials for %s",buf.value);
|
||||
if (smj != GSS_S_FAILURE) do
|
||||
switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
mctx = 0;
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
SERVER_LOG ("Unknown GSSAPI failure: %s",resp.value);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
|
||||
GSS_C_NO_OID,&mctx,&resp)) {
|
||||
case GSS_S_COMPLETE:
|
||||
case GSS_S_CONTINUE_NEEDED:
|
||||
SERVER_LOG ("GSSAPI mechanism status: %s",resp.value);
|
||||
gss_release_buffer (&dsmn,&resp);
|
||||
}
|
||||
while (dsmj == GSS_S_CONTINUE_NEEDED);
|
||||
}
|
||||
/* finished with credentials name */
|
||||
gss_release_name (&smn,&crname);
|
||||
}
|
||||
return ret; /* return status */
|
||||
}
|
||||
117
src/c-client/auth_log.c
Normal file
117
src/c-client/auth_log.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Login authenticator
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 5 December 1995
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
long auth_login_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user);
|
||||
char *auth_login_server (authresponse_t responder,int argc,char *argv[]);
|
||||
|
||||
AUTHENTICATOR auth_log = {
|
||||
AU_HIDE, /* hidden */
|
||||
"LOGIN", /* authenticator name */
|
||||
NIL, /* always valid */
|
||||
auth_login_client, /* client method */
|
||||
auth_login_server, /* server method */
|
||||
NIL /* next authenticator */
|
||||
};
|
||||
|
||||
#define PWD_USER "User Name"
|
||||
#define PWD_PWD "Password"
|
||||
|
||||
/* Client authenticator
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* pointer to current trial count
|
||||
* returned user name
|
||||
* Returns: T if success, NIL otherwise, number of trials incremented if retry
|
||||
*/
|
||||
|
||||
long auth_login_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user)
|
||||
{
|
||||
char pwd[MAILTMPLEN];
|
||||
void *challenge;
|
||||
unsigned long clen;
|
||||
long ret = NIL;
|
||||
/* get user name prompt */
|
||||
if (challenge = (*challenger) (stream,&clen)) {
|
||||
fs_give ((void **) &challenge);
|
||||
pwd[0] = NIL; /* prompt user */
|
||||
mm_login (mb,user,pwd,*trial);
|
||||
if (!pwd[0]) { /* user requested abort */
|
||||
(*responder) (stream,NIL,0);
|
||||
*trial = 0; /* cancel subsequent attempts */
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
/* send user name */
|
||||
else if ((*responder) (stream,user,strlen (user)) &&
|
||||
(challenge = (*challenger) (stream,&clen))) {
|
||||
fs_give ((void **) &challenge);
|
||||
/* send password */
|
||||
if ((*responder) (stream,pwd,strlen (pwd))) {
|
||||
if (challenge = (*challenger) (stream,&clen))
|
||||
fs_give ((void **) &challenge);
|
||||
else {
|
||||
++*trial; /* can try again if necessary */
|
||||
ret = LONGT; /* check the authentication */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memset (pwd,0,MAILTMPLEN); /* erase password */
|
||||
if (!ret) *trial = 65535; /* don't retry if bad protocol */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Server authenticator
|
||||
* Accepts: responder function
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*/
|
||||
|
||||
char *auth_login_server (authresponse_t responder,int argc,char *argv[])
|
||||
{
|
||||
char *ret = NIL;
|
||||
char *user,*pass,*authuser;
|
||||
if (user = (*responder) (PWD_USER,sizeof (PWD_USER),NIL)) {
|
||||
if (pass = (*responder) (PWD_PWD,sizeof (PWD_PWD),NIL)) {
|
||||
/* delimit user from possible admin */
|
||||
if (authuser = strchr (user,'*')) *authuser++ = '\0';
|
||||
if (server_login (user,pass,authuser,argc,argv)) ret = myusername ();
|
||||
fs_give ((void **) &pass);
|
||||
}
|
||||
fs_give ((void **) &user);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
495
src/c-client/auth_md5.c
Normal file
495
src/c-client/auth_md5.c
Normal file
@@ -0,0 +1,495 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: CRAM-MD5 authenticator
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 21 October 1998
|
||||
* Last Edited: 30 January 2007
|
||||
*/
|
||||
|
||||
/* MD5 context */
|
||||
|
||||
#define MD5BLKLEN 64 /* MD5 block length */
|
||||
#define MD5DIGLEN 16 /* MD5 digest length */
|
||||
|
||||
typedef struct {
|
||||
unsigned long chigh; /* high 32bits of byte count */
|
||||
unsigned long clow; /* low 32bits of byte count */
|
||||
unsigned long state[4]; /* state (ABCD) */
|
||||
unsigned char buf[MD5BLKLEN]; /* input buffer */
|
||||
unsigned char *ptr; /* buffer position */
|
||||
} MD5CONTEXT;
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
long auth_md5_valid (void);
|
||||
long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user);
|
||||
char *auth_md5_server (authresponse_t responder,int argc,char *argv[]);
|
||||
char *auth_md5_pwd (char *user);
|
||||
char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
|
||||
char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl);
|
||||
void md5_init (MD5CONTEXT *ctx);
|
||||
void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len);
|
||||
void md5_final (unsigned char *digest,MD5CONTEXT *ctx);
|
||||
static void md5_transform (unsigned long *state,unsigned char *block);
|
||||
static void md5_encode (unsigned char *dst,unsigned long *src,int len);
|
||||
static void md5_decode (unsigned long *dst,unsigned char *src,int len);
|
||||
|
||||
|
||||
/* Authenticator linkage */
|
||||
|
||||
AUTHENTICATOR auth_md5 = {
|
||||
AU_SECURE, /* secure authenticator */
|
||||
"CRAM-MD5", /* authenticator name */
|
||||
auth_md5_valid, /* check if valid */
|
||||
auth_md5_client, /* client method */
|
||||
auth_md5_server, /* server method */
|
||||
NIL /* next authenticator */
|
||||
};
|
||||
|
||||
/* Check if CRAM-MD5 valid on this system
|
||||
* Returns: T, always
|
||||
*/
|
||||
|
||||
long auth_md5_valid (void)
|
||||
{
|
||||
struct stat sbuf;
|
||||
/* server forbids MD5 if no MD5 enable file */
|
||||
if (stat (MD5ENABLE,&sbuf)) auth_md5.server = NIL;
|
||||
return T; /* MD5 is otherwise valid */
|
||||
}
|
||||
|
||||
|
||||
/* Client authenticator
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* pointer to current trial count
|
||||
* returned user name
|
||||
* Returns: T if success, NIL otherwise, number of trials incremented if retry
|
||||
*/
|
||||
|
||||
long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user)
|
||||
{
|
||||
char pwd[MAILTMPLEN];
|
||||
void *challenge;
|
||||
unsigned long clen;
|
||||
long ret = NIL;
|
||||
/* get challenge */
|
||||
if (challenge = (*challenger) (stream,&clen)) {
|
||||
pwd[0] = NIL; /* prompt user */
|
||||
mm_login (mb,user,pwd,*trial);
|
||||
if (!pwd[0]) { /* user requested abort */
|
||||
fs_give ((void **) &challenge);
|
||||
(*responder) (stream,NIL,0);
|
||||
*trial = 0; /* cancel subsequent attempts */
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
else { /* got password, build response */
|
||||
sprintf (pwd,"%.65s %.33s",user,hmac_md5 (challenge,clen,
|
||||
pwd,strlen (pwd)));
|
||||
fs_give ((void **) &challenge);
|
||||
/* send credentials, allow retry if OK */
|
||||
if ((*responder) (stream,pwd,strlen (pwd))) {
|
||||
if (challenge = (*challenger) (stream,&clen))
|
||||
fs_give ((void **) &challenge);
|
||||
else {
|
||||
++*trial; /* can try again if necessary */
|
||||
ret = LONGT; /* check the authentication */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memset (pwd,0,MAILTMPLEN); /* erase password in case not overwritten */
|
||||
if (!ret) *trial = 65535; /* don't retry if bad protocol */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Server authenticator
|
||||
* Accepts: responder function
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*
|
||||
* This is much hairier than it needs to be due to the necessary of zapping
|
||||
* the password data.
|
||||
*/
|
||||
|
||||
static int md5try = MAXLOGINTRIALS;
|
||||
|
||||
char *auth_md5_server (authresponse_t responder,int argc,char *argv[])
|
||||
{
|
||||
char *ret = NIL;
|
||||
char *p,*u,*user,*authuser,*hash,chal[MAILTMPLEN];
|
||||
unsigned long cl,pl;
|
||||
/* generate challenge */
|
||||
sprintf (chal,"<%lu.%lu@%s>",(unsigned long) getpid (),
|
||||
(unsigned long) time (0),mylocalhost ());
|
||||
/* send challenge, get user and hash */
|
||||
if (user = (*responder) (chal,cl = strlen (chal),NIL)) {
|
||||
/* got user, locate hash */
|
||||
if (hash = strrchr (user,' ')) {
|
||||
*hash++ = '\0'; /* tie off user */
|
||||
/* see if authentication user */
|
||||
if (authuser = strchr (user,'*')) *authuser++ = '\0';
|
||||
/* get password */
|
||||
if (p = auth_md5_pwd ((authuser && *authuser) ? authuser : user)) {
|
||||
pl = strlen (p);
|
||||
u = (md5try && !strcmp (hash,hmac_md5 (chal,cl,p,pl))) ? user : NIL;
|
||||
memset (p,0,pl); /* erase sensitive information */
|
||||
fs_give ((void **) &p); /* flush erased password */
|
||||
/* now log in for real */
|
||||
if (u && authserver_login (u,authuser,argc,argv)) ret = myusername ();
|
||||
else if (md5try) --md5try;
|
||||
}
|
||||
}
|
||||
fs_give ((void **) &user);
|
||||
}
|
||||
if (!ret) sleep (3); /* slow down possible cracker */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return MD5 password for user
|
||||
* Accepts: user name
|
||||
* Returns: plaintext password if success, else NIL
|
||||
*
|
||||
* This is much hairier than it needs to be due to the necessary of zapping
|
||||
* the password data. That's why we don't use stdio here.
|
||||
*/
|
||||
|
||||
char *auth_md5_pwd (char *user)
|
||||
{
|
||||
struct stat sbuf;
|
||||
int fd = open (MD5ENABLE,O_RDONLY,NIL);
|
||||
unsigned char *s,*t,*buf,*lusr,*lret;
|
||||
char *r;
|
||||
char *ret = NIL;
|
||||
if (fd >= 0) { /* found the file? */
|
||||
fstat (fd,&sbuf); /* yes, slurp it into memory */
|
||||
read (fd,buf = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
|
||||
/* see if any uppercase characters in user */
|
||||
for (s = user; *s && ((*s < 'A') || (*s > 'Z')); s++);
|
||||
/* yes, make lowercase copy */
|
||||
lusr = *s ? lcase (cpystr (user)) : NIL;
|
||||
for (s = strtok_r ((char *) buf,"\015\012",&r),lret = NIL; s;
|
||||
s = ret ? NIL : strtok_r (NIL,"\015\012",&r))
|
||||
/* must be valid entry line */
|
||||
if (*s && (*s != '#') && (t = strchr (s,'\t')) && t[1]) {
|
||||
*t++ = '\0'; /* found tab, tie off user, point to pwd */
|
||||
if (!strcmp (s,user)) ret = cpystr (t);
|
||||
else if (lusr && !lret) if (!strcmp (s,lusr)) lret = t;
|
||||
}
|
||||
/* accept case-independent name */
|
||||
if (!ret && lret) ret = cpystr (lret);
|
||||
/* don't need lowercase copy any more */
|
||||
if (lusr) fs_give ((void **) &lusr);
|
||||
/* erase sensitive information from buffer */
|
||||
memset (buf,0,sbuf.st_size + 1);
|
||||
fs_give ((void **) &buf); /* flush the buffer */
|
||||
close (fd); /* don't need file any longer */
|
||||
}
|
||||
return ret; /* return password */
|
||||
}
|
||||
|
||||
/* APOP server login
|
||||
* Accepts: challenge
|
||||
* desired user name
|
||||
* purported MD5
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*/
|
||||
|
||||
char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[])
|
||||
{
|
||||
int i,j;
|
||||
char *ret = NIL;
|
||||
char *s,*authuser,tmp[MAILTMPLEN];
|
||||
unsigned char digest[MD5DIGLEN];
|
||||
MD5CONTEXT ctx;
|
||||
char *hex = "0123456789abcdef";
|
||||
/* see if authentication user */
|
||||
if (authuser = strchr (user,'*')) *authuser++ = '\0';
|
||||
/* get password */
|
||||
if (s = auth_md5_pwd ((authuser && *authuser) ? authuser : user)) {
|
||||
md5_init (&ctx); /* initialize MD5 context */
|
||||
/* build string to get MD5 digest */
|
||||
sprintf (tmp,"%.128s%.128s",chal,s);
|
||||
memset (s,0,strlen (s)); /* erase sensitive information */
|
||||
fs_give ((void **) &s); /* flush erased password */
|
||||
md5_update (&ctx,(unsigned char *) tmp,strlen (tmp));
|
||||
memset (tmp,0,MAILTMPLEN); /* erase sensitive information */
|
||||
md5_final (digest,&ctx);
|
||||
/* convert to printable hex */
|
||||
for (i = 0, s = tmp; i < MD5DIGLEN; i++) {
|
||||
*s++ = hex[(j = digest[i]) >> 4];
|
||||
*s++ = hex[j & 0xf];
|
||||
}
|
||||
*s = '\0'; /* tie off hash text */
|
||||
memset (digest,0,MD5DIGLEN);/* erase sensitive information */
|
||||
if (md5try && !strcmp (md5,tmp) &&
|
||||
authserver_login (user,authuser,argc,argv))
|
||||
ret = cpystr (myusername ());
|
||||
else if (md5try) --md5try;
|
||||
memset (tmp,0,MAILTMPLEN); /* erase sensitive information */
|
||||
}
|
||||
if (!ret) sleep (3); /* slow down possible cracker */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 2104 HMAC hashing
|
||||
* Accepts: text to hash
|
||||
* text length
|
||||
* key
|
||||
* key length
|
||||
* Returns: hash as text, always
|
||||
*/
|
||||
|
||||
char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl)
|
||||
{
|
||||
int i,j;
|
||||
static char hshbuf[2*MD5DIGLEN + 1];
|
||||
char *s;
|
||||
MD5CONTEXT ctx;
|
||||
char *hex = "0123456789abcdef";
|
||||
unsigned char digest[MD5DIGLEN],k_ipad[MD5BLKLEN+1],k_opad[MD5BLKLEN+1];
|
||||
if (kl > MD5BLKLEN) { /* key longer than pad length? */
|
||||
md5_init (&ctx); /* yes, set key as MD5(key) */
|
||||
md5_update (&ctx,(unsigned char *) key,kl);
|
||||
md5_final (digest,&ctx);
|
||||
key = (char *) digest;
|
||||
kl = MD5DIGLEN;
|
||||
}
|
||||
memcpy (k_ipad,key,kl); /* store key in pads */
|
||||
memset (k_ipad+kl,0,(MD5BLKLEN+1)-kl);
|
||||
memcpy (k_opad,k_ipad,MD5BLKLEN+1);
|
||||
/* XOR key with ipad and opad values */
|
||||
for (i = 0; i < MD5BLKLEN; i++) {
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
md5_init (&ctx); /* inner MD5: hash ipad and text */
|
||||
md5_update (&ctx,k_ipad,MD5BLKLEN);
|
||||
md5_update (&ctx,(unsigned char *) text,tl);
|
||||
md5_final (digest,&ctx);
|
||||
md5_init (&ctx); /* outer MD5: hash opad and inner results */
|
||||
md5_update (&ctx,k_opad,MD5BLKLEN);
|
||||
md5_update (&ctx,digest,MD5DIGLEN);
|
||||
md5_final (digest,&ctx);
|
||||
/* convert to printable hex */
|
||||
for (i = 0, s = hshbuf; i < MD5DIGLEN; i++) {
|
||||
*s++ = hex[(j = digest[i]) >> 4];
|
||||
*s++ = hex[j & 0xf];
|
||||
}
|
||||
*s = '\0'; /* tie off hash text */
|
||||
return hshbuf;
|
||||
}
|
||||
|
||||
/* Everything after this point is derived from the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm
|
||||
*/
|
||||
|
||||
/* You may wonder why these strange "a &= 0xffffffff;" statements are here.
|
||||
* This is to ensure correct results on machines with a unsigned long size of
|
||||
* larger than 32 bits.
|
||||
*/
|
||||
|
||||
#define RND1(a,b,c,d,x,s,ac) \
|
||||
a += ((b & c) | (d & ~b)) + x + (unsigned long) ac; \
|
||||
a &= 0xffffffff; \
|
||||
a = b + ((a << s) | (a >> (32 - s)));
|
||||
|
||||
#define RND2(a,b,c,d,x,s,ac) \
|
||||
a += ((b & d) | (c & ~d)) + x + (unsigned long) ac; \
|
||||
a &= 0xffffffff; \
|
||||
a = b + ((a << s) | (a >> (32 - s)));
|
||||
|
||||
#define RND3(a,b,c,d,x,s,ac) \
|
||||
a += (b ^ c ^ d) + x + (unsigned long) ac; \
|
||||
a &= 0xffffffff; \
|
||||
a = b + ((a << s) | (a >> (32 - s)));
|
||||
|
||||
#define RND4(a,b,c,d,x,s,ac) \
|
||||
a += (c ^ (b | ~d)) + x + (unsigned long) ac; \
|
||||
a &= 0xffffffff; \
|
||||
a = b + ((a << s) | (a >> (32 - s)));
|
||||
|
||||
/* Initialize MD5 context
|
||||
* Accepts: context to initialize
|
||||
*/
|
||||
|
||||
void md5_init (MD5CONTEXT *ctx)
|
||||
{
|
||||
ctx->clow = ctx->chigh = 0; /* initialize byte count to zero */
|
||||
/* initialization constants */
|
||||
ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89;
|
||||
ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476;
|
||||
ctx->ptr = ctx->buf; /* reset buffer pointer */
|
||||
}
|
||||
|
||||
|
||||
/* MD5 add data to context
|
||||
* Accepts: context
|
||||
* input data
|
||||
* length of data
|
||||
*/
|
||||
|
||||
void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len)
|
||||
{
|
||||
unsigned long i = (ctx->buf + MD5BLKLEN) - ctx->ptr;
|
||||
/* update double precision number of bytes */
|
||||
if ((ctx->clow += len) < len) ctx->chigh++;
|
||||
while (i <= len) { /* copy/transform data, 64 bytes at a time */
|
||||
memcpy (ctx->ptr,data,i); /* fill up 64 byte chunk */
|
||||
md5_transform (ctx->state,ctx->ptr = ctx->buf);
|
||||
data += i,len -= i,i = MD5BLKLEN;
|
||||
}
|
||||
memcpy (ctx->ptr,data,len); /* copy final bit of data in buffer */
|
||||
ctx->ptr += len; /* update buffer pointer */
|
||||
}
|
||||
|
||||
/* MD5 Finalization
|
||||
* Accepts: destination digest
|
||||
* context
|
||||
*/
|
||||
|
||||
void md5_final (unsigned char *digest,MD5CONTEXT *ctx)
|
||||
{
|
||||
unsigned long i,bits[2];
|
||||
bits[0] = ctx->clow << 3; /* calculate length in bits (before padding) */
|
||||
bits[1] = (ctx->chigh << 3) + (ctx->clow >> 29);
|
||||
*ctx->ptr++ = 0x80; /* padding byte */
|
||||
if ((i = (ctx->buf + MD5BLKLEN) - ctx->ptr) < 8) {
|
||||
memset (ctx->ptr,0,i); /* pad out buffer with zeros */
|
||||
md5_transform (ctx->state,ctx->buf);
|
||||
/* pad out with zeros, leaving 8 bytes */
|
||||
memset (ctx->buf,0,MD5BLKLEN - 8);
|
||||
ctx->ptr = ctx->buf + MD5BLKLEN - 8;
|
||||
}
|
||||
else if (i -= 8) { /* need to pad this buffer? */
|
||||
memset (ctx->ptr,0,i); /* yes, pad out with zeros, leaving 8 bytes */
|
||||
ctx->ptr += i;
|
||||
}
|
||||
md5_encode (ctx->ptr,bits,2); /* make LSB-first length */
|
||||
md5_transform (ctx->state,ctx->buf);
|
||||
/* store state in digest */
|
||||
md5_encode (digest,ctx->state,4);
|
||||
/* erase context */
|
||||
memset (ctx,0,sizeof (MD5CONTEXT));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation
|
||||
* Accepts: state vector
|
||||
* current 64-byte block
|
||||
*/
|
||||
|
||||
static void md5_transform (unsigned long *state,unsigned char *block)
|
||||
{
|
||||
unsigned long a = state[0],b = state[1],c = state[2],d = state[3],x[16];
|
||||
md5_decode (x,block,16); /* decode into 16 longs */
|
||||
/* round 1 */
|
||||
RND1 (a,b,c,d,x[ 0], 7,0xd76aa478); RND1 (d,a,b,c,x[ 1],12,0xe8c7b756);
|
||||
RND1 (c,d,a,b,x[ 2],17,0x242070db); RND1 (b,c,d,a,x[ 3],22,0xc1bdceee);
|
||||
RND1 (a,b,c,d,x[ 4], 7,0xf57c0faf); RND1 (d,a,b,c,x[ 5],12,0x4787c62a);
|
||||
RND1 (c,d,a,b,x[ 6],17,0xa8304613); RND1 (b,c,d,a,x[ 7],22,0xfd469501);
|
||||
RND1 (a,b,c,d,x[ 8], 7,0x698098d8); RND1 (d,a,b,c,x[ 9],12,0x8b44f7af);
|
||||
RND1 (c,d,a,b,x[10],17,0xffff5bb1); RND1 (b,c,d,a,x[11],22,0x895cd7be);
|
||||
RND1 (a,b,c,d,x[12], 7,0x6b901122); RND1 (d,a,b,c,x[13],12,0xfd987193);
|
||||
RND1 (c,d,a,b,x[14],17,0xa679438e); RND1 (b,c,d,a,x[15],22,0x49b40821);
|
||||
/* round 2 */
|
||||
RND2 (a,b,c,d,x[ 1], 5,0xf61e2562); RND2 (d,a,b,c,x[ 6], 9,0xc040b340);
|
||||
RND2 (c,d,a,b,x[11],14,0x265e5a51); RND2 (b,c,d,a,x[ 0],20,0xe9b6c7aa);
|
||||
RND2 (a,b,c,d,x[ 5], 5,0xd62f105d); RND2 (d,a,b,c,x[10], 9, 0x2441453);
|
||||
RND2 (c,d,a,b,x[15],14,0xd8a1e681); RND2 (b,c,d,a,x[ 4],20,0xe7d3fbc8);
|
||||
RND2 (a,b,c,d,x[ 9], 5,0x21e1cde6); RND2 (d,a,b,c,x[14], 9,0xc33707d6);
|
||||
RND2 (c,d,a,b,x[ 3],14,0xf4d50d87); RND2 (b,c,d,a,x[ 8],20,0x455a14ed);
|
||||
RND2 (a,b,c,d,x[13], 5,0xa9e3e905); RND2 (d,a,b,c,x[ 2], 9,0xfcefa3f8);
|
||||
RND2 (c,d,a,b,x[ 7],14,0x676f02d9); RND2 (b,c,d,a,x[12],20,0x8d2a4c8a);
|
||||
/* round 3 */
|
||||
RND3 (a,b,c,d,x[ 5], 4,0xfffa3942); RND3 (d,a,b,c,x[ 8],11,0x8771f681);
|
||||
RND3 (c,d,a,b,x[11],16,0x6d9d6122); RND3 (b,c,d,a,x[14],23,0xfde5380c);
|
||||
RND3 (a,b,c,d,x[ 1], 4,0xa4beea44); RND3 (d,a,b,c,x[ 4],11,0x4bdecfa9);
|
||||
RND3 (c,d,a,b,x[ 7],16,0xf6bb4b60); RND3 (b,c,d,a,x[10],23,0xbebfbc70);
|
||||
RND3 (a,b,c,d,x[13], 4,0x289b7ec6); RND3 (d,a,b,c,x[ 0],11,0xeaa127fa);
|
||||
RND3 (c,d,a,b,x[ 3],16,0xd4ef3085); RND3 (b,c,d,a,x[ 6],23, 0x4881d05);
|
||||
RND3 (a,b,c,d,x[ 9], 4,0xd9d4d039); RND3 (d,a,b,c,x[12],11,0xe6db99e5);
|
||||
RND3 (c,d,a,b,x[15],16,0x1fa27cf8); RND3 (b,c,d,a,x[ 2],23,0xc4ac5665);
|
||||
/* round 4 */
|
||||
RND4 (a,b,c,d,x[ 0], 6,0xf4292244); RND4 (d,a,b,c,x[ 7],10,0x432aff97);
|
||||
RND4 (c,d,a,b,x[14],15,0xab9423a7); RND4 (b,c,d,a,x[ 5],21,0xfc93a039);
|
||||
RND4 (a,b,c,d,x[12], 6,0x655b59c3); RND4 (d,a,b,c,x[ 3],10,0x8f0ccc92);
|
||||
RND4 (c,d,a,b,x[10],15,0xffeff47d); RND4 (b,c,d,a,x[ 1],21,0x85845dd1);
|
||||
RND4 (a,b,c,d,x[ 8], 6,0x6fa87e4f); RND4 (d,a,b,c,x[15],10,0xfe2ce6e0);
|
||||
RND4 (c,d,a,b,x[ 6],15,0xa3014314); RND4 (b,c,d,a,x[13],21,0x4e0811a1);
|
||||
RND4 (a,b,c,d,x[ 4], 6,0xf7537e82); RND4 (d,a,b,c,x[11],10,0xbd3af235);
|
||||
RND4 (c,d,a,b,x[ 2],15,0x2ad7d2bb); RND4 (b,c,d,a,x[ 9],21,0xeb86d391);
|
||||
/* update state */
|
||||
state[0] += a; state[1] += b; state[2] += c; state[3] += d;
|
||||
memset (x,0,sizeof (x)); /* erase sensitive data */
|
||||
}
|
||||
|
||||
/* You may wonder why these strange "& 0xff" maskings are here. This is to
|
||||
* ensure correct results on machines with a char size of larger than 8 bits.
|
||||
* For example, the KCC compiler on the PDP-10 uses 9-bit chars.
|
||||
*/
|
||||
|
||||
/* MD5 encode unsigned long into LSB-first bytes
|
||||
* Accepts: destination pointer
|
||||
* source
|
||||
* length of source
|
||||
*/
|
||||
|
||||
static void md5_encode (unsigned char *dst,unsigned long *src,int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
*dst++ = (unsigned char) (src[i] & 0xff);
|
||||
*dst++ = (unsigned char) ((src[i] >> 8) & 0xff);
|
||||
*dst++ = (unsigned char) ((src[i] >> 16) & 0xff);
|
||||
*dst++ = (unsigned char) ((src[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* MD5 decode LSB-first bytes into unsigned long
|
||||
* Accepts: destination pointer
|
||||
* source
|
||||
* length of destination
|
||||
*/
|
||||
|
||||
static void md5_decode (unsigned long *dst,unsigned char *src,int len)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0, j = 0; i < len; i++, j += 4)
|
||||
dst[i] = ((unsigned long) (src[j] & 0xff)) |
|
||||
(((unsigned long) (src[j+1] & 0xff)) << 8) |
|
||||
(((unsigned long) (src[j+2] & 0xff)) << 16) |
|
||||
(((unsigned long) (src[j+3] & 0xff)) << 24);
|
||||
}
|
||||
133
src/c-client/auth_pla.c
Normal file
133
src/c-client/auth_pla.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Plain authenticator
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 22 September 1998
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user);
|
||||
char *auth_plain_server (authresponse_t responder,int argc,char *argv[]);
|
||||
|
||||
AUTHENTICATOR auth_pla = {
|
||||
AU_AUTHUSER | AU_HIDE, /* allow authuser, hidden */
|
||||
"PLAIN", /* authenticator name */
|
||||
NIL, /* always valid */
|
||||
auth_plain_client, /* client method */
|
||||
auth_plain_server, /* server method */
|
||||
NIL /* next authenticator */
|
||||
};
|
||||
|
||||
/* Client authenticator
|
||||
* Accepts: challenger function
|
||||
* responder function
|
||||
* SASL service name
|
||||
* parsed network mailbox structure
|
||||
* stream argument for functions
|
||||
* pointer to current trial count
|
||||
* returned user name
|
||||
* Returns: T if success, NIL otherwise, number of trials incremented if retry
|
||||
*/
|
||||
|
||||
long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
|
||||
char *service,NETMBX *mb,void *stream,
|
||||
unsigned long *trial,char *user)
|
||||
{
|
||||
char *u,pwd[MAILTMPLEN];
|
||||
void *challenge;
|
||||
unsigned long clen;
|
||||
long ret = NIL;
|
||||
/* snarl if not SSL/TLS session */
|
||||
if (!mb->sslflag && !mb->tlsflag)
|
||||
mm_log ("SECURITY PROBLEM: insecure server advertised AUTH=PLAIN",WARN);
|
||||
/* get initial (empty) challenge */
|
||||
if (challenge = (*challenger) (stream,&clen)) {
|
||||
fs_give ((void **) &challenge);
|
||||
if (clen) { /* abort if challenge non-empty */
|
||||
mm_log ("Server bug: non-empty initial PLAIN challenge",WARN);
|
||||
(*responder) (stream,NIL,0);
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
pwd[0] = NIL; /* prompt user if empty challenge */
|
||||
mm_login (mb,user,pwd,*trial);
|
||||
if (!pwd[0]) { /* empty challenge or user requested abort */
|
||||
(*responder) (stream,NIL,0);
|
||||
*trial = 0; /* cancel subsequent attempts */
|
||||
ret = LONGT; /* will get a BAD response back */
|
||||
}
|
||||
else {
|
||||
unsigned long rlen =
|
||||
strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2;
|
||||
char *response = (char *) fs_get (rlen);
|
||||
char *t = response; /* copy authorization id */
|
||||
if (mb->authuser[0]) for (u = user; *u; *t++ = *u++);
|
||||
*t++ = '\0'; /* delimiting NUL */
|
||||
/* copy authentication id */
|
||||
for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++);
|
||||
*t++ = '\0'; /* delimiting NUL */
|
||||
/* copy password */
|
||||
for (u = pwd; *u; *t++ = *u++);
|
||||
/* send credentials */
|
||||
if ((*responder) (stream,response,rlen)) {
|
||||
if (challenge = (*challenger) (stream,&clen))
|
||||
fs_give ((void **) &challenge);
|
||||
else {
|
||||
++*trial; /* can try again if necessary */
|
||||
ret = LONGT; /* check the authentication */
|
||||
}
|
||||
}
|
||||
memset (response,0,rlen); /* erase credentials */
|
||||
fs_give ((void **) &response);
|
||||
}
|
||||
}
|
||||
memset (pwd,0,MAILTMPLEN); /* erase password */
|
||||
if (!ret) *trial = 65535; /* don't retry if bad protocol */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Server authenticator
|
||||
* Accepts: responder function
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: authenticated user name or NIL
|
||||
*/
|
||||
|
||||
char *auth_plain_server (authresponse_t responder,int argc,char *argv[])
|
||||
{
|
||||
char *ret = NIL;
|
||||
char *user,*aid,*pass;
|
||||
unsigned long len;
|
||||
/* get user name */
|
||||
if (aid = (*responder) ("",0,&len)) {
|
||||
/* note: responders null-terminate */
|
||||
if ((((unsigned long) ((user = aid + strlen (aid) + 1) - aid)) < len) &&
|
||||
(((unsigned long) ((pass = user + strlen (user) + 1) - aid)) < len) &&
|
||||
(((unsigned long) ((pass + strlen (pass)) - aid)) == len) &&
|
||||
(*aid ? server_login (aid,pass,user,argc,argv) :
|
||||
server_login (user,pass,NIL,argc,argv))) ret = myusername ();
|
||||
fs_give ((void **) &aid);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
55
src/c-client/c-client.h
Normal file
55
src/c-client/c-client.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: c-client master include for application programs
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 19 May 2000
|
||||
* Last Edited: 6 December 2006
|
||||
*/
|
||||
|
||||
#ifndef __CCLIENT_H /* nobody should include this twice... */
|
||||
#define __CCLIENT_H
|
||||
|
||||
#ifdef __cplusplus /* help out people who use C++ compilers */
|
||||
extern "C" {
|
||||
/* If you use gcc, you may also have to use -fno-operator-names */
|
||||
#define private cclientPrivate /* private to c-client */
|
||||
#define and cclientAnd /* C99 doesn't realize that ISO 646 is dead */
|
||||
#define or cclientOr
|
||||
#define not cclientNot
|
||||
#endif
|
||||
|
||||
#include "mail.h" /* primary interfaces */
|
||||
#include "osdep.h" /* OS-dependent routines */
|
||||
#include "rfc822.h" /* RFC822 and MIME routines */
|
||||
#include "smtp.h" /* SMTP sending routines */
|
||||
#include "nntp.h" /* NNTP sending routines */
|
||||
#include "utf8.h" /* Unicode and charset routines */
|
||||
#include "utf8aux.h" /* Unicode auxillary routines */
|
||||
#include "misc.h" /* miscellaneous utility routines */
|
||||
|
||||
#ifdef __cplusplus /* undo the C++ mischief */
|
||||
#undef private
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
45
src/c-client/env.h
Normal file
45
src/c-client/env.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Environment routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* UW Technology
|
||||
* University of Washington
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 13 February 2008
|
||||
*/
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
long pmatch_full (unsigned char *s,unsigned char *pat,unsigned char delim);
|
||||
long dmatch (unsigned char *s,unsigned char *pat,unsigned char delim);
|
||||
void *env_parameters (long function,void *value);
|
||||
void rfc822_date (char *date);
|
||||
void rfc822_timezone (char *s,void *t);
|
||||
void internal_date (char *date);
|
||||
long server_input_wait (long seconds);
|
||||
void server_init (char *server,char *service,char *sasl,
|
||||
void *clkint,void *kodint,void *hupint,void *trmint,
|
||||
void *staint);
|
||||
long server_login (char *user,char *pass,char *authuser,int argc,char *argv[]);
|
||||
long authserver_login (char *user,char *authuser,int argc,char *argv[]);
|
||||
long anonymous_login (int argc,char *argv[]);
|
||||
char *mylocalhost (void);
|
||||
char *myhomedir (void);
|
||||
char *mailboxfile (char *dst,char *name);
|
||||
MAILSTREAM *default_proto (long type);
|
||||
91
src/c-client/flstring.c
Normal file
91
src/c-client/flstring.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: File string routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 15 April 1997
|
||||
* Last Edited: 6 December 2006
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mail.h"
|
||||
#include "flstring.h"
|
||||
|
||||
/* String driver for stdio file strings */
|
||||
|
||||
static void file_string_init (STRING *s,void *data,unsigned long size);
|
||||
static char file_string_next (STRING *s);
|
||||
static void file_string_setpos (STRING *s,unsigned long i);
|
||||
|
||||
STRINGDRIVER file_string = {
|
||||
file_string_init, /* initialize string structure */
|
||||
file_string_next, /* get next byte in string structure */
|
||||
file_string_setpos /* set position in string structure */
|
||||
};
|
||||
|
||||
|
||||
/* Initialize mail string structure for file
|
||||
* Accepts: string structure
|
||||
* pointer to string
|
||||
* size of string
|
||||
*/
|
||||
|
||||
static void file_string_init (STRING *s,void *data,unsigned long size)
|
||||
{
|
||||
s->data = data; /* note file descriptor */
|
||||
/* big enough for one byte */
|
||||
s->chunk = s->curpos = (char *) &s->data1;
|
||||
s->size = size; /* data size */
|
||||
s->cursize = s->chunksize = 1;/* always call stdio */
|
||||
file_string_setpos (s,0); /* initial offset is 0 */
|
||||
}
|
||||
|
||||
|
||||
/* Get next character from string
|
||||
* Accepts: string structure
|
||||
* Returns: character, string structure chunk refreshed
|
||||
*/
|
||||
|
||||
static char file_string_next (STRING *s)
|
||||
{
|
||||
char ret = *s->curpos;
|
||||
s->offset++; /* advance position */
|
||||
s->cursize = 1; /* reset size */
|
||||
*s->curpos = (char) getc ((FILE *) s->data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Set string pointer position
|
||||
* Accepts: string structure
|
||||
* new position
|
||||
*/
|
||||
|
||||
static void file_string_setpos (STRING *s,unsigned long i)
|
||||
{
|
||||
s->offset = i; /* note new offset */
|
||||
fseek ((FILE *) s->data,i,SEEK_SET);
|
||||
/* in case using returnstringstruct hack */
|
||||
s->chunk = s->curpos = (char *) &s->data1;
|
||||
*s->curpos = (char) getc ((FILE *) s->data);
|
||||
}
|
||||
30
src/c-client/flstring.h
Normal file
30
src/c-client/flstring.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: File string routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 15 April 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
extern STRINGDRIVER file_string;
|
||||
34
src/c-client/fs.h
Normal file
34
src/c-client/fs.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Free storage management routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void *fs_get (size_t size);
|
||||
void fs_resize (void **block,size_t size);
|
||||
void fs_give (void **block);
|
||||
32
src/c-client/ftl.h
Normal file
32
src/c-client/ftl.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Crash management routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void fatal (char *string);
|
||||
5670
src/c-client/imap4r1.c
Normal file
5670
src/c-client/imap4r1.c
Normal file
File diff suppressed because it is too large
Load Diff
281
src/c-client/imap4r1.h
Normal file
281
src/c-client/imap4r1.h
Normal file
@@ -0,0 +1,281 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Interactive Mail Access Protocol 4rev1 (IMAP4R1) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 14 October 1988
|
||||
* Last Edited: 5 September 2007
|
||||
*/
|
||||
|
||||
|
||||
/* This include file is provided for applications which need to look under
|
||||
* the covers at the IMAP driver and in particular want to do different
|
||||
* operations depending upon the IMAP server's protocol level and
|
||||
* capabilities. It is NOT included in the normal c-client.h application
|
||||
* export, and most applications do NOT need the definitions in this file.
|
||||
*
|
||||
* As of October 15, 2003, it is believed that:
|
||||
*
|
||||
* Version RFC Status Known Implementations
|
||||
* ------- --- ------ ---------------------
|
||||
* IMAP1 none extinct experimental TOPS-20 server
|
||||
* IMAP2 1064 extinct old TOPS-20, SUMEX servers
|
||||
* IMAP2 1176 rare TOPS-20, old UW servers
|
||||
* IMAP2bis expired I-D uncommon old UW, Cyrus servers
|
||||
* IMAP3 1203 extinct none (never implemented)
|
||||
* IMAP4 1730 rare old UW, Cyrus, Netscape servers
|
||||
* IMAP4rev1 2060, 3501 ubiquitous UW, Cyrus, and many others
|
||||
*
|
||||
* Most client implementations will only interoperate with an IMAP4rev1
|
||||
* server. c-client based client implementations can interoperate with IMAP2,
|
||||
* IMAP2bis, IMAP4, and IMAP4rev1 servers, but only if they are very careful.
|
||||
*
|
||||
* The LEVELxxx() macros in this file enable the client to determine the
|
||||
* server protocol level and capabilities. This file also contains a few
|
||||
* backdoor calls into the IMAP driver.
|
||||
*/
|
||||
|
||||
/* Server protocol level and capabilities */
|
||||
|
||||
typedef struct imap_cap {
|
||||
unsigned int rfc1176 : 1; /* server is RFC-1176 IMAP2 */
|
||||
unsigned int imap2bis : 1; /* server is IMAP2bis */
|
||||
unsigned int imap4 : 1; /* server is IMAP4 (RFC 1730) */
|
||||
unsigned int imap4rev1 : 1; /* server is IMAP4rev1 */
|
||||
unsigned int acl : 1; /* server has ACL (RFC 2086) */
|
||||
unsigned int quota : 1; /* server has QUOTA (RFC 2087) */
|
||||
unsigned int litplus : 1; /* server has LITERAL+ (RFC 2088) */
|
||||
unsigned int idle : 1; /* server has IDLE (RFC 2177) */
|
||||
unsigned int mbx_ref : 1; /* server has mailbox referrals (RFC 2193) */
|
||||
unsigned int log_ref : 1; /* server has login referrals (RFC 2221) */
|
||||
unsigned int authanon : 1; /* server has anonymous SASL (RFC 2245) */
|
||||
unsigned int namespace :1; /* server has NAMESPACE (RFC 2342) */
|
||||
unsigned int uidplus : 1; /* server has UIDPLUS (RFC 2359) */
|
||||
unsigned int starttls : 1; /* server has STARTTLS (RFC 2595) */
|
||||
/* server disallows LOGIN command (RFC 2595) */
|
||||
unsigned int logindisabled : 1;
|
||||
unsigned int id : 1; /* server has ID (RFC 2971) */
|
||||
unsigned int children : 1; /* server has CHILDREN (RFC 3348) */
|
||||
unsigned int multiappend : 1; /* server has multi-APPEND (RFC 3502) ;*/
|
||||
unsigned int binary : 1; /* server has BINARY (RFC 3516) */
|
||||
unsigned int unselect : 1; /* server has UNSELECT */
|
||||
unsigned int sasl_ir : 1; /* server has SASL-IR initial response */
|
||||
unsigned int sort : 1; /* server has SORT */
|
||||
unsigned int scan : 1; /* server has SCAN */
|
||||
unsigned int urlauth : 1; /* server has URLAUTH (RFC 4467) */
|
||||
unsigned int catenate : 1; /* server has CATENATE (RFC 4469) */
|
||||
unsigned int condstore : 1; /* server has CONDSTORE (RFC 4551) */
|
||||
unsigned int esearch : 1; /* server has ESEARCH (RFC 4731) */
|
||||
unsigned int within : 1; /* server has WITHIN (RFC 5032) */
|
||||
unsigned int extlevel; /* extension data level supported by server */
|
||||
/* supported authenticators */
|
||||
unsigned int auth : MAXAUTHENTICATORS;
|
||||
THREADER *threader; /* list of threaders */
|
||||
} IMAPCAP;
|
||||
|
||||
/* IMAP4rev1 level or better */
|
||||
|
||||
#define LEVELIMAP4rev1(stream) imap_cap (stream)->imap4rev1
|
||||
|
||||
#define LEVELSTATUS LEVELIMAP4rev1
|
||||
|
||||
|
||||
/* IMAP4 level or better (not including RFC 1730 design mistakes) */
|
||||
|
||||
#define LEVELIMAP4(stream) (imap_cap (stream)->imap4rev1 || \
|
||||
imap_cap (stream)->imap4)
|
||||
|
||||
|
||||
/* IMAP4 RFC-1730 level */
|
||||
|
||||
#define LEVEL1730(stream) imap_cap (stream)->imap4
|
||||
|
||||
|
||||
/* IMAP2bis level or better */
|
||||
|
||||
#define LEVELIMAP2bis(stream) imap_cap (stream)->imap2bis
|
||||
|
||||
|
||||
/* IMAP2 RFC-1176 level or better */
|
||||
|
||||
#define LEVEL1176(stream) imap_cap (stream)->rfc1176
|
||||
|
||||
|
||||
/* IMAP2 RFC-1064 or better */
|
||||
|
||||
#define LEVEL1064(stream) 1
|
||||
|
||||
/* Has ACL extension */
|
||||
|
||||
#define LEVELACL(stream) imap_cap (stream)->acl
|
||||
|
||||
|
||||
/* Has QUOTA extension */
|
||||
|
||||
#define LEVELQUOTA(stream) imap_cap (stream)->quota
|
||||
|
||||
|
||||
/* Has LITERALPLUS extension */
|
||||
|
||||
#define LEVELLITERALPLUS(stream) imap_cap (stream)->litplus
|
||||
|
||||
|
||||
/* Has IDLE extension */
|
||||
|
||||
#define LEVELIDLE(stream) imap_cap (stream)->idle
|
||||
|
||||
|
||||
/* Has mailbox referrals */
|
||||
|
||||
#define LEVELMBX_REF(stream) imap_cap (stream)->mbx_ref
|
||||
|
||||
|
||||
/* Has login referrals */
|
||||
|
||||
#define LEVELLOG_REF(stream) imap_cap (stream)->log_ref
|
||||
|
||||
|
||||
/* Has AUTH=ANONYMOUS extension */
|
||||
|
||||
#define LEVELANONYMOUS(stream) imap_cap (stream)->authanon
|
||||
|
||||
|
||||
/* Has NAMESPACE extension */
|
||||
|
||||
#define LEVELNAMESPACE(stream) imap_cap (stream)->namespace
|
||||
|
||||
|
||||
/* Has UIDPLUS extension */
|
||||
|
||||
#define LEVELUIDPLUS(stream) imap_cap (stream)->uidplus
|
||||
|
||||
|
||||
/* Has STARTTLS extension */
|
||||
|
||||
#define LEVELSTARTTLS(stream) imap_cap (stream)->starttls
|
||||
|
||||
|
||||
/* Has LOGINDISABLED extension */
|
||||
|
||||
#define LEVELLOGINDISABLED(stream) imap_cap (stream)->logindisabled
|
||||
|
||||
/* Has ID extension */
|
||||
|
||||
#define LEVELID(stream) imap_cap (stream)->id
|
||||
|
||||
|
||||
/* Has CHILDREN extension */
|
||||
|
||||
#define LEVELCHILDREN(stream) imap_cap (stream)->children
|
||||
|
||||
|
||||
/* Has MULTIAPPEND extension */
|
||||
|
||||
#define LEVELMULTIAPPEND(stream) imap_cap (stream)->multiappend
|
||||
|
||||
|
||||
/* Has BINARY extension */
|
||||
|
||||
#define LEVELBINARY(stream) imap_cap (stream)->binary
|
||||
|
||||
|
||||
/* Has UNSELECT extension */
|
||||
|
||||
#define LEVELUNSELECT(stream) imap_cap (stream)->unselect
|
||||
|
||||
|
||||
/* Has SASL initial response extension */
|
||||
|
||||
#define LEVELSASLIR(stream) imap_cap (stream)->sasl_ir
|
||||
|
||||
|
||||
/* Has SORT extension */
|
||||
|
||||
#define LEVELSORT(stream) imap_cap (stream)->sort
|
||||
|
||||
|
||||
/* Has at least one THREAD extension */
|
||||
|
||||
#define LEVELTHREAD(stream) ((imap_cap (stream)->threader) ? T : NIL)
|
||||
|
||||
|
||||
/* Has SCAN extension */
|
||||
|
||||
#define LEVELSCAN(stream) imap_cap (stream)->scan
|
||||
|
||||
|
||||
/* Has URLAUTH extension */
|
||||
|
||||
#define LEVELURLAUTH(stream) imap_cap (stream)->urlauth
|
||||
|
||||
|
||||
/* Has CATENATE extension */
|
||||
|
||||
#define LEVELCATENATE(stream) imap_cap (stream)->catenate
|
||||
|
||||
|
||||
/* Has CONDSTORE extension */
|
||||
|
||||
#define LEVELCONDSTORE(stream) imap_cap (stream)->condstore
|
||||
|
||||
|
||||
/* Has ESEARCH extension */
|
||||
|
||||
#define LEVELESEARCH(stream) imap_cap (stream)->esearch
|
||||
|
||||
|
||||
/* Has WITHIN extension */
|
||||
|
||||
#define LEVELWITHIN(stream) imap_cap (stream)->within
|
||||
|
||||
/* Body structure extension levels */
|
||||
|
||||
/* These are in BODYSTRUCTURE order. Note that multipart bodies do not have
|
||||
* body-fld-md5. This is alright, since all subsequent body structure
|
||||
* extensions are in both singlepart and multipart bodies. If that ever
|
||||
* changes, this will have to be split.
|
||||
*/
|
||||
|
||||
#define BODYEXTMD5 1 /* body-fld-md5 */
|
||||
#define BODYEXTDSP 2 /* body-fld-dsp */
|
||||
#define BODYEXTLANG 3 /* body-fld-lang */
|
||||
#define BODYEXTLOC 4 /* body-fld-loc */
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
IMAPCAP *imap_cap (MAILSTREAM *stream);
|
||||
char *imap_host (MAILSTREAM *stream);
|
||||
long imap_cache (MAILSTREAM *stream,unsigned long msgno,char *seg,
|
||||
STRINGLIST *stl,SIZEDTEXT *text);
|
||||
|
||||
|
||||
/* Temporary */
|
||||
|
||||
long imap_setacl (MAILSTREAM *stream,char *mailbox,char *id,char *rights);
|
||||
long imap_deleteacl (MAILSTREAM *stream,char *mailbox,char *id);
|
||||
long imap_getacl (MAILSTREAM *stream,char *mailbox);
|
||||
long imap_listrights (MAILSTREAM *stream,char *mailbox,char *id);
|
||||
long imap_myrights (MAILSTREAM *stream,char *mailbox);
|
||||
long imap_setquota (MAILSTREAM *stream,char *qroot,STRINGLIST *limits);
|
||||
long imap_getquota (MAILSTREAM *stream,char *qroot);
|
||||
long imap_getquotaroot (MAILSTREAM *stream,char *mailbox);
|
||||
6331
src/c-client/mail.c
Normal file
6331
src/c-client/mail.c
Normal file
File diff suppressed because it is too large
Load Diff
1837
src/c-client/mail.h
Normal file
1837
src/c-client/mail.h
Normal file
File diff suppressed because it is too large
Load Diff
475
src/c-client/misc.c
Normal file
475
src/c-client/misc.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Miscellaneous utility routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 5 July 1988
|
||||
* Last Edited: 6 December 2006
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the NationalInstitutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include "c-client.h"
|
||||
|
||||
/* Convert ASCII string to all uppercase
|
||||
* Accepts: string pointer
|
||||
* Returns: string pointer
|
||||
*
|
||||
* Don't use islower/toupper since this function must be ASCII only.
|
||||
*/
|
||||
|
||||
unsigned char *ucase (unsigned char *s)
|
||||
{
|
||||
unsigned char *t;
|
||||
/* if lowercase covert to upper */
|
||||
for (t = s; *t; t++) if ((*t >= 'a') && (*t <= 'z')) *t -= ('a' - 'A');
|
||||
return s; /* return string */
|
||||
}
|
||||
|
||||
|
||||
/* Convert string to all lowercase
|
||||
* Accepts: string pointer
|
||||
* Returns: string pointer
|
||||
*
|
||||
* Don't use isupper/tolower since this function must be ASCII only.
|
||||
*/
|
||||
|
||||
unsigned char *lcase (unsigned char *s)
|
||||
{
|
||||
unsigned char *t;
|
||||
/* if uppercase covert to lower */
|
||||
for (t = s; *t; t++) if ((*t >= 'A') && (*t <= 'Z')) *t += ('a' - 'A');
|
||||
return s; /* return string */
|
||||
}
|
||||
|
||||
/* Copy string to free storage
|
||||
* Accepts: source string
|
||||
* Returns: free storage copy of string
|
||||
*/
|
||||
|
||||
char *cpystr (const char *string)
|
||||
{
|
||||
return string ? strcpy ((char *) fs_get (1 + strlen (string)),string) : NIL;
|
||||
}
|
||||
|
||||
|
||||
/* Copy text/size to free storage as sized text
|
||||
* Accepts: destination sized text
|
||||
* pointer to source text
|
||||
* size of source text
|
||||
* Returns: text as a char *
|
||||
*/
|
||||
|
||||
char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size)
|
||||
{
|
||||
/* flush old space */
|
||||
if (dst->data) fs_give ((void **) &dst->data);
|
||||
/* copy data in sized text */
|
||||
memcpy (dst->data = (unsigned char *)
|
||||
fs_get ((size_t) (dst->size = size) + 1),text,(size_t) size);
|
||||
dst->data[size] = '\0'; /* tie off text */
|
||||
return (char *) dst->data; /* convenience return */
|
||||
}
|
||||
|
||||
/* Copy sized text to free storage as sized text
|
||||
* Accepts: destination sized text
|
||||
* source sized text
|
||||
* Returns: text as a char *
|
||||
*/
|
||||
|
||||
char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src)
|
||||
{
|
||||
/* flush old space */
|
||||
if (dst->data) fs_give ((void **) &dst->data);
|
||||
/* copy data in sized text */
|
||||
memcpy (dst->data = (unsigned char *)
|
||||
fs_get ((size_t) (dst->size = src->size) + 1),
|
||||
src->data,(size_t) src->size);
|
||||
dst->data[dst->size] = '\0'; /* tie off text */
|
||||
return (char *) dst->data; /* convenience return */
|
||||
}
|
||||
|
||||
|
||||
/* Copy stringstruct to free storage as sized text
|
||||
* Accepts: destination sized text
|
||||
* source stringstruct
|
||||
* Returns: text as a char *
|
||||
*/
|
||||
|
||||
char *textcpystring (SIZEDTEXT *text,STRING *bs)
|
||||
{
|
||||
unsigned long i = 0;
|
||||
/* clear old space */
|
||||
if (text->data) fs_give ((void **) &text->data);
|
||||
/* make free storage space in sized text */
|
||||
text->data = (unsigned char *) fs_get ((size_t) (text->size = SIZE (bs)) +1);
|
||||
while (i < text->size) text->data[i++] = SNX (bs);
|
||||
text->data[i] = '\0'; /* tie off text */
|
||||
return (char *) text->data; /* convenience return */
|
||||
}
|
||||
|
||||
|
||||
/* Copy stringstruct from offset to free storage as sized text
|
||||
* Accepts: destination sized text
|
||||
* source stringstruct
|
||||
* offset into stringstruct
|
||||
* size of source text
|
||||
* Returns: text as a char *
|
||||
*/
|
||||
|
||||
char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long i = 0;
|
||||
/* clear old space */
|
||||
if (text->data) fs_give ((void **) &text->data);
|
||||
SETPOS (bs,offset); /* offset the string */
|
||||
/* make free storage space in sized text */
|
||||
text->data = (unsigned char *) fs_get ((size_t) (text->size = size) + 1);
|
||||
while (i < size) text->data[i++] = SNX (bs);
|
||||
text->data[i] = '\0'; /* tie off text */
|
||||
return (char *) text->data; /* convenience return */
|
||||
}
|
||||
|
||||
/* Returns index of rightmost bit in word
|
||||
* Accepts: pointer to a 32 bit value
|
||||
* Returns: -1 if word is 0, else index of rightmost bit
|
||||
*
|
||||
* Bit is cleared in the word
|
||||
*/
|
||||
|
||||
unsigned long find_rightmost_bit (unsigned long *valptr)
|
||||
{
|
||||
unsigned long value = *valptr;
|
||||
unsigned long bit = 0;
|
||||
if (!(value & 0xffffffff)) return 0xffffffff;
|
||||
/* binary search for rightmost bit */
|
||||
if (!(value & 0xffff)) value >>= 16, bit += 16;
|
||||
if (!(value & 0xff)) value >>= 8, bit += 8;
|
||||
if (!(value & 0xf)) value >>= 4, bit += 4;
|
||||
if (!(value & 0x3)) value >>= 2, bit += 2;
|
||||
if (!(value & 0x1)) value >>= 1, bit += 1;
|
||||
*valptr ^= (1 << bit); /* clear specified bit */
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
||||
/* Return minimum of two integers
|
||||
* Accepts: integer 1
|
||||
* integer 2
|
||||
* Returns: minimum
|
||||
*/
|
||||
|
||||
long min (long i,long j)
|
||||
{
|
||||
return ((i < j) ? i : j);
|
||||
}
|
||||
|
||||
|
||||
/* Return maximum of two integers
|
||||
* Accepts: integer 1
|
||||
* integer 2
|
||||
* Returns: maximum
|
||||
*/
|
||||
|
||||
long max (long i,long j)
|
||||
{
|
||||
return ((i > j) ? i : j);
|
||||
}
|
||||
|
||||
/* Search, case-insensitive for ASCII characters
|
||||
* Accepts: base string
|
||||
* length of base string
|
||||
* pattern string
|
||||
* length of pattern string
|
||||
* Returns: T if pattern exists inside base, else NIL
|
||||
*/
|
||||
|
||||
long search (unsigned char *base,long basec,unsigned char *pat,long patc)
|
||||
{
|
||||
long i,j,k;
|
||||
int c;
|
||||
unsigned char mask[256];
|
||||
static unsigned char alphatab[256] = {
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
|
||||
223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
|
||||
255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
|
||||
223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
|
||||
};
|
||||
/* validate arguments */
|
||||
if (base && (basec > 0) && pat && (basec >= patc)) {
|
||||
if (patc <= 0) return T; /* empty pattern always succeeds */
|
||||
memset (mask,0,256); /* initialize search validity mask */
|
||||
for (i = 0; i < patc; i++) if (!mask[c = pat[i]]) {
|
||||
/* mark single character if non-alphabetic */
|
||||
if (alphatab[c] & 0x20) mask[c] = T;
|
||||
/* else mark both cases */
|
||||
else mask[c & 0xdf] = mask[c | 0x20] = T;
|
||||
}
|
||||
/* Boyer-Moore type search */
|
||||
for (i = --patc; i < basec; i += (mask[c] ? 1 : (j + 1)))
|
||||
for (j = patc,c = base[k = i]; !((c ^ pat[j]) & alphatab[c]);
|
||||
j--,c = base[--k])
|
||||
if (!j) return T; /* found a match! */
|
||||
}
|
||||
return NIL; /* pattern not found */
|
||||
}
|
||||
|
||||
/* Boyer-Moore string search
|
||||
* Accepts: base string
|
||||
* length of base string
|
||||
* pattern string
|
||||
* length of pattern string
|
||||
* Returns: T if pattern exists inside base, else NIL
|
||||
*/
|
||||
|
||||
long ssearch (unsigned char *base,long basec,unsigned char *pat,long patc)
|
||||
{
|
||||
long i,j,k;
|
||||
int c;
|
||||
unsigned char mask[256];
|
||||
/* validate arguments */
|
||||
if (base && (basec > 0) && pat && (basec >= patc)) {
|
||||
if (patc <= 0) return T; /* empty pattern always succeeds */
|
||||
memset (mask,0,256); /* initialize search validity mask */
|
||||
for (i = 0; i < patc; i++) mask[pat[i]] = T;
|
||||
/* Boyer-Moore type search */
|
||||
for (i = --patc, c = pat[i]; i < basec; i += (mask[c] ? 1 : (j + 1)))
|
||||
for (j = patc,c = base[k = i]; (c == pat[j]); j--,c = base[--k])
|
||||
if (!j) return T; /* found a match! */
|
||||
}
|
||||
return NIL; /* pattern not found */
|
||||
}
|
||||
|
||||
/* Create a hash table
|
||||
* Accepts: size of new table (note: should be a prime)
|
||||
* Returns: hash table
|
||||
*/
|
||||
|
||||
HASHTAB *hash_create (size_t size)
|
||||
{
|
||||
size_t i = sizeof (size_t) + size * sizeof (HASHENT *);
|
||||
HASHTAB *ret = (HASHTAB *) memset (fs_get (i),0,i);
|
||||
ret->size = size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Destroy hash table
|
||||
* Accepts: hash table
|
||||
*/
|
||||
|
||||
void hash_destroy (HASHTAB **hashtab)
|
||||
{
|
||||
if (*hashtab) {
|
||||
hash_reset (*hashtab); /* reset hash table */
|
||||
fs_give ((void **) hashtab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Reset hash table
|
||||
* Accepts: hash table
|
||||
*/
|
||||
|
||||
void hash_reset (HASHTAB *hashtab)
|
||||
{
|
||||
size_t i;
|
||||
HASHENT *ent,*nxt;
|
||||
/* free each hash entry */
|
||||
for (i = 0; i < hashtab->size; i++) if (ent = hashtab->table[i])
|
||||
for (hashtab->table[i] = NIL; ent; ent = nxt) {
|
||||
nxt = ent->next; /* get successor */
|
||||
fs_give ((void **) &ent); /* flush this entry */
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate index into hash table
|
||||
* Accepts: hash table
|
||||
* entry name
|
||||
* Returns: index
|
||||
*/
|
||||
|
||||
unsigned long hash_index (HASHTAB *hashtab,char *key)
|
||||
{
|
||||
unsigned long i,ret;
|
||||
/* polynomial of letters of the word */
|
||||
for (ret = 0; i = (unsigned int) *key++; ret += i) ret *= HASHMULT;
|
||||
return ret % (unsigned long) hashtab->size;
|
||||
}
|
||||
|
||||
|
||||
/* Look up name in hash table
|
||||
* Accepts: hash table
|
||||
* key
|
||||
* Returns: associated data
|
||||
*/
|
||||
|
||||
void **hash_lookup (HASHTAB *hashtab,char *key)
|
||||
{
|
||||
HASHENT *ret;
|
||||
for (ret = hashtab->table[hash_index (hashtab,key)]; ret; ret = ret->next)
|
||||
if (!strcmp (key,ret->name)) return ret->data;
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* Add entry to hash table
|
||||
* Accepts: hash table
|
||||
* key
|
||||
* associated data
|
||||
* number of extra data slots
|
||||
* Returns: hash entry
|
||||
* Caller is responsible for ensuring that entry isn't already in table
|
||||
*/
|
||||
|
||||
HASHENT *hash_add (HASHTAB *hashtab,char *key,void *data,long extra)
|
||||
{
|
||||
unsigned long i = hash_index (hashtab,key);
|
||||
size_t j = sizeof (HASHENT) + (extra * sizeof (void *));
|
||||
HASHENT *ret = (HASHENT *) memset (fs_get (j),0,j);
|
||||
ret->next = hashtab->table[i];/* insert as new head in this index */
|
||||
ret->name = key; /* set up hash key */
|
||||
ret->data[0] = data; /* and first data */
|
||||
return hashtab->table[i] = ret;
|
||||
}
|
||||
|
||||
|
||||
/* Look up name in hash table
|
||||
* Accepts: hash table
|
||||
* key
|
||||
* associated data
|
||||
* number of extra data slots
|
||||
* Returns: associated data
|
||||
*/
|
||||
|
||||
void **hash_lookup_and_add (HASHTAB *hashtab,char *key,void *data,long extra)
|
||||
{
|
||||
HASHENT *ret;
|
||||
unsigned long i = hash_index (hashtab,key);
|
||||
size_t j = sizeof (HASHENT) + (extra * sizeof (void *));
|
||||
for (ret = hashtab->table[i]; ret; ret = ret->next)
|
||||
if (!strcmp (key,ret->name)) return ret->data;
|
||||
ret = (HASHENT *) memset (fs_get (j),0,j);
|
||||
ret->next = hashtab->table[i];/* insert as new head in this index */
|
||||
ret->name = key; /* set up hash key */
|
||||
ret->data[0] = data; /* and first data */
|
||||
return (hashtab->table[i] = ret)->data;
|
||||
}
|
||||
|
||||
/* Convert two hex characters into byte
|
||||
* Accepts: char for high nybble
|
||||
* char for low nybble
|
||||
* Returns: byte
|
||||
*
|
||||
* Arguments must be isxdigit validated
|
||||
*/
|
||||
|
||||
unsigned char hex2byte (unsigned char c1,unsigned char c2)
|
||||
{
|
||||
/* merge the two nybbles */
|
||||
return ((c1 -= (isdigit (c1) ? '0' : ((c1 <= 'Z') ? 'A' : 'a') - 10)) << 4) +
|
||||
(c2 - (isdigit (c2) ? '0' : ((c2 <= 'Z') ? 'A' : 'a') - 10));
|
||||
}
|
||||
|
||||
|
||||
/* Compare two unsigned longs
|
||||
* Accepts: first value
|
||||
* second value
|
||||
* Returns: -1 if l1 < l2, 0 if l1 == l2, 1 if l1 > l2
|
||||
*/
|
||||
|
||||
int compare_ulong (unsigned long l1,unsigned long l2)
|
||||
{
|
||||
if (l1 < l2) return -1;
|
||||
if (l1 > l2) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Compare two unsigned chars, case-independent
|
||||
* Accepts: first value
|
||||
* second value
|
||||
* Returns: -1 if c1 < c2, 0 if c1 == c2, 1 if c1 > c2
|
||||
*
|
||||
* Don't use isupper/tolower since this function must be ASCII only.
|
||||
*/
|
||||
|
||||
int compare_uchar (unsigned char c1,unsigned char c2)
|
||||
{
|
||||
return compare_ulong (((c1 >= 'A') && (c1 <= 'Z')) ? c1 + ('a' - 'A') : c1,
|
||||
((c2 >= 'A') && (c2 <= 'Z')) ? c2 + ('a' - 'A') : c2);
|
||||
}
|
||||
|
||||
/* Compare two case-independent ASCII strings
|
||||
* Accepts: first string
|
||||
* second string
|
||||
* Returns: -1 if s1 < s2, 0 if s1 == s2, 1 if s1 > s2
|
||||
*/
|
||||
|
||||
int compare_cstring (unsigned char *s1,unsigned char *s2)
|
||||
{
|
||||
int i;
|
||||
if (!s1) return s2 ? -1 : 0; /* empty string cases */
|
||||
else if (!s2) return 1;
|
||||
for (; *s1 && *s2; s1++,s2++) if (i = (compare_uchar (*s1,*s2))) return i;
|
||||
if (*s1) return 1; /* first string is longer */
|
||||
return *s2 ? -1 : 0; /* second string longer : strings identical */
|
||||
}
|
||||
|
||||
|
||||
/* Compare case-independent string with sized text
|
||||
* Accepts: first string
|
||||
* sized text
|
||||
* Returns: -1 if s1 < s2, 0 if s1 == s2, 1 if s1 > s2
|
||||
*/
|
||||
|
||||
int compare_csizedtext (unsigned char *s1,SIZEDTEXT *s2)
|
||||
{
|
||||
int i;
|
||||
unsigned char *s;
|
||||
unsigned long j;
|
||||
if (!s1) return s2 ? -1 : 0; /* null string cases */
|
||||
else if (!s2) return 1;
|
||||
for (s = (char *) s2->data,j = s2->size; *s1 && j; ++s1,++s,--j)
|
||||
if (i = (compare_uchar (*s1,*s))) return i;
|
||||
if (*s1) return 1; /* first string is longer */
|
||||
return j ? -1 : 0; /* second string longer : strings identical */
|
||||
}
|
||||
110
src/c-client/misc.h
Normal file
110
src/c-client/misc.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Miscellaneous utility routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 5 July 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the NationalInstitutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
/* Hash table operations */
|
||||
|
||||
#define HASHMULT 29 /* hash polynomial multiplier */
|
||||
|
||||
#define HASHENT struct hash_entry
|
||||
|
||||
HASHENT {
|
||||
HASHENT *next; /* next entry with same hash code */
|
||||
char *name; /* name of this hash entry */
|
||||
void *data[1]; /* data of this hash entry */
|
||||
};
|
||||
|
||||
|
||||
#define HASHTAB struct hash_table
|
||||
|
||||
HASHTAB {
|
||||
size_t size; /* size of this table */
|
||||
HASHENT *table[1]; /* table */
|
||||
};
|
||||
|
||||
|
||||
/* KLUDGE ALERT!!!
|
||||
*
|
||||
* Yes, write() is overridden here instead of in osdep. This
|
||||
* is because misc.h is one of the last files that most things #include, so
|
||||
* this should avoid problems with some system #include file.
|
||||
*/
|
||||
|
||||
#define write safe_write
|
||||
|
||||
|
||||
/* Some C compilers have these as macros */
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
|
||||
/* And some C libraries have these as int functions */
|
||||
|
||||
#define min Min
|
||||
#define max Max
|
||||
|
||||
|
||||
/* Compatibility definitions */
|
||||
|
||||
#define pmatch(s,pat) \
|
||||
pmatch_full (s,pat,NIL)
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
unsigned char *ucase (unsigned char *string);
|
||||
unsigned char *lcase (unsigned char *string);
|
||||
char *cpystr (const char *string);
|
||||
char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size);
|
||||
char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src);
|
||||
char *textcpystring (SIZEDTEXT *text,STRING *bs);
|
||||
char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset,
|
||||
unsigned long size);
|
||||
unsigned long find_rightmost_bit (unsigned long *valptr);
|
||||
long min (long i,long j);
|
||||
long max (long i,long j);
|
||||
long search (unsigned char *base,long basec,unsigned char *pat,long patc);
|
||||
long ssearch (unsigned char *base,long basec,unsigned char *pat,long patc);
|
||||
HASHTAB *hash_create (size_t size);
|
||||
void hash_destroy (HASHTAB **hashtab);
|
||||
void hash_reset (HASHTAB *hashtab);
|
||||
unsigned long hash_index (HASHTAB *hashtab,char *key);
|
||||
void **hash_lookup (HASHTAB *hashtab,char *key);
|
||||
HASHENT *hash_add (HASHTAB *hashtab,char *key,void *data,long extra);
|
||||
void **hash_lookup_and_add (HASHTAB *hashtab,char *key,void *data,long extra);
|
||||
unsigned char hex2byte (unsigned char c1,unsigned char c2);
|
||||
int compare_ulong (unsigned long l1,unsigned long l2);
|
||||
int compare_uchar (unsigned char c1,unsigned char c2);
|
||||
int compare_cstring (unsigned char *s1,unsigned char *s2);
|
||||
int compare_csizedtext (unsigned char *s1,SIZEDTEXT *s2);
|
||||
104
src/c-client/netmsg.c
Normal file
104
src/c-client/netmsg.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Network message (SMTP/NNTP/POP2/POP3) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 8 June 1995
|
||||
* Last Edited: 6 December 2006
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
extern int errno; /* just in case */
|
||||
#include "c-client.h"
|
||||
#include "netmsg.h"
|
||||
#include "flstring.h"
|
||||
|
||||
/* Network message read
|
||||
* Accepts: file
|
||||
* number of bytes to read
|
||||
* buffer address
|
||||
* Returns: T if success, NIL otherwise
|
||||
*/
|
||||
|
||||
long netmsg_read (void *stream,unsigned long count,char *buffer)
|
||||
{
|
||||
return (fread (buffer,(size_t) 1,(size_t) count,(FILE *) stream) == count) ?
|
||||
T : NIL;
|
||||
}
|
||||
|
||||
/* Slurp dot-terminated text from NET
|
||||
* Accepts: NET stream
|
||||
* place to return size
|
||||
* place to return header size
|
||||
* Returns: file descriptor
|
||||
*/
|
||||
|
||||
FILE *netmsg_slurp (NETSTREAM *stream,unsigned long *size,unsigned long *hsiz)
|
||||
{
|
||||
unsigned long i;
|
||||
char *s,*t,tmp[MAILTMPLEN];
|
||||
FILE *f = tmpfile ();
|
||||
if (!f) {
|
||||
sprintf (tmp,".%lx.%lx",(unsigned long) time (0),(unsigned long)getpid ());
|
||||
if (f = fopen (tmp,"wb+")) unlink (tmp);
|
||||
else {
|
||||
sprintf (tmp,"Unable to create scratch file: %.80s",strerror (errno));
|
||||
MM_LOG (tmp,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
*size = 0; /* initially emtpy */
|
||||
if (hsiz) *hsiz = 0;
|
||||
while (s = net_getline (stream)) {
|
||||
if (*s == '.') { /* possible end of text? */
|
||||
if (s[1]) t = s + 1; /* pointer to true start of line */
|
||||
else {
|
||||
fs_give ((void **) &s); /* free the line */
|
||||
break; /* end of data */
|
||||
}
|
||||
}
|
||||
else t = s; /* want the entire line */
|
||||
if (f) { /* copy it to the file */
|
||||
i = strlen (t); /* size of line */
|
||||
if ((fwrite (t,(size_t) 1,(size_t) i,f) == i) &&
|
||||
(fwrite ("\015\012",(size_t) 1,(size_t) 2,f) == 2)) {
|
||||
*size += i + 2; /* tally up size of data */
|
||||
/* note header position */
|
||||
if (!i && hsiz && !*hsiz) *hsiz = *size;
|
||||
}
|
||||
else {
|
||||
sprintf (tmp,"Error writing scratch file at byte %lu",*size);
|
||||
MM_LOG (tmp,ERROR);
|
||||
fclose (f); /* forget it */
|
||||
f = NIL; /* failure now */
|
||||
}
|
||||
}
|
||||
fs_give ((void **) &s); /* free the line */
|
||||
}
|
||||
/* if making a file, rewind to start of file */
|
||||
if (f) fseek (f,(unsigned long) 0,SEEK_SET);
|
||||
/* header consumes entire message */
|
||||
if (hsiz && !*hsiz) *hsiz = *size;
|
||||
return f; /* return the file descriptor */
|
||||
}
|
||||
32
src/c-client/netmsg.h
Normal file
32
src/c-client/netmsg.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Network message (SMTP/NNTP/POP2/POP3) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 8 June 1995
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
/* stream must be void* for use as readfn_t */
|
||||
long netmsg_read (void *stream,unsigned long count,char *buffer);
|
||||
FILE *netmsg_slurp (NETSTREAM *stream,unsigned long *size,unsigned long *hsiz);
|
||||
510
src/c-client/newsrc.c
Normal file
510
src/c-client/newsrc.c
Normal file
@@ -0,0 +1,510 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Newsrc manipulation routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 12 September 1994
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "c-client.h"
|
||||
#include "newsrc.h"
|
||||
|
||||
#ifndef OLDFILESUFFIX
|
||||
#define OLDFILESUFFIX ".old"
|
||||
#endif
|
||||
|
||||
/* Error message
|
||||
* Accepts: message format
|
||||
* additional message string
|
||||
* message level
|
||||
* Returns: NIL, always
|
||||
*/
|
||||
|
||||
long newsrc_error (char *fmt,char *text,long errflg)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
sprintf (tmp,fmt,text);
|
||||
MM_LOG (tmp,errflg);
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
/* Write error message
|
||||
* Accepts: newsrc name
|
||||
* file designator
|
||||
* file designator
|
||||
* Returns: NIL, always
|
||||
*/
|
||||
|
||||
long newsrc_write_error (char *name,FILE *f1,FILE *f2)
|
||||
{
|
||||
if (f1) fclose (f1); /* close file designators */
|
||||
if (f2) fclose (f2);
|
||||
return newsrc_error ("Error writing to %.80s",name,ERROR);
|
||||
}
|
||||
|
||||
|
||||
/* Create newsrc file in local form
|
||||
* Accepts: MAIL stream
|
||||
* notification flag
|
||||
* Returns: file designator of newsrc
|
||||
*/
|
||||
|
||||
FILE *newsrc_create (MAILSTREAM *stream,int notify)
|
||||
{
|
||||
char *newsrc = (char *) mail_parameters (stream,GET_NEWSRC,stream);
|
||||
FILE *f = fopen (newsrc,"wb");
|
||||
if (!f) newsrc_error ("Unable to create news state %.80s",newsrc,ERROR);
|
||||
else if (notify) newsrc_error ("Creating news state %.80s",newsrc,WARN);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Write new state in newsrc
|
||||
* Accepts: file designator of newsrc
|
||||
* group
|
||||
* new subscription status character
|
||||
* newline convention
|
||||
* Returns: T if successful, NIL otherwise
|
||||
*/
|
||||
|
||||
long newsrc_newstate (FILE *f,char *group,char state,char *nl)
|
||||
{
|
||||
long ret = (f && (fputs (group,f) != EOF) && ((putc (state,f)) != EOF) &&
|
||||
((putc (' ',f)) != EOF) && (fputs (nl,f) != EOF)) ? LONGT : NIL;
|
||||
if (fclose (f) == EOF) ret = NIL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Write messages in newsrc
|
||||
* Accepts: file designator of newsrc
|
||||
* MAIL stream
|
||||
* message number/newsgroup message map
|
||||
* newline convention
|
||||
* Returns: T if successful, NIL otherwise
|
||||
*/
|
||||
|
||||
long newsrc_newmessages (FILE *f,MAILSTREAM *stream,char *nl)
|
||||
{
|
||||
unsigned long i,j,k;
|
||||
char tmp[MAILTMPLEN];
|
||||
MESSAGECACHE *elt;
|
||||
int c = ' ';
|
||||
if (stream->nmsgs) { /* have any messages? */
|
||||
for (i = 1,j = k = (mail_elt (stream,i)->private.uid > 1) ? 1 : 0;
|
||||
i <= stream->nmsgs; ++i) {
|
||||
/* deleted message? */
|
||||
if ((elt = mail_elt (stream,i))->deleted) {
|
||||
k = elt->private.uid; /* this is the top of the current range */
|
||||
if (!j) j = k; /* if no range in progress, start one */
|
||||
}
|
||||
else if (j) { /* unread message, ending a range */
|
||||
/* calculate end of range */
|
||||
if (k = elt->private.uid - 1) {
|
||||
/* dump range */
|
||||
sprintf (tmp,(j == k) ? "%c%ld" : "%c%ld-%ld",c,j,k);
|
||||
if (fputs (tmp,f) == EOF) return NIL;
|
||||
c = ','; /* need a comma after the first time */
|
||||
}
|
||||
j = 0; /* no more range in progress */
|
||||
}
|
||||
}
|
||||
if (j) { /* dump trailing range */
|
||||
sprintf (tmp,(j == k) ? "%c%ld" : "%c%ld-%ld",c,j,k);
|
||||
if (fputs (tmp,f) == EOF) return NIL;
|
||||
}
|
||||
}
|
||||
/* write trailing newline, return */
|
||||
return (fputs (nl,f) == EOF) ? NIL : LONGT;
|
||||
}
|
||||
|
||||
/* List subscribed newsgroups
|
||||
* Accepts: MAIL stream
|
||||
* prefix to append name
|
||||
* pattern to search
|
||||
*/
|
||||
|
||||
void newsrc_lsub (MAILSTREAM *stream,char *pattern)
|
||||
{
|
||||
char *s,*t,*lcl,name[MAILTMPLEN];
|
||||
int c = ' ';
|
||||
int showuppers = pattern[strlen (pattern) - 1] == '%';
|
||||
FILE *f = fopen ((char *) mail_parameters (stream,GET_NEWSRC,stream),"rb");
|
||||
if (f) { /* got file? */
|
||||
/* remote name? */
|
||||
if (*(lcl = strcpy (name,pattern)) == '{') lcl = strchr (lcl,'}') + 1;
|
||||
if (*lcl == '#') lcl += 6; /* namespace format name? */
|
||||
while (c != EOF) { /* yes, read newsrc */
|
||||
for (s = lcl; (s < (name + MAILTMPLEN - 1)) && ((c = getc (f)) != EOF) &&
|
||||
(c != ':') && (c != '!') && (c != '\015') && (c != '\012');
|
||||
*s++ = c);
|
||||
if (c == ':') { /* found a subscribed newsgroup? */
|
||||
*s = '\0'; /* yes, tie off name */
|
||||
/* report if match */
|
||||
if (pmatch_full (name,pattern,'.')) mm_lsub (stream,'.',name,NIL);
|
||||
else while (showuppers && (t = strrchr (lcl,'.'))) {
|
||||
*t = '\0'; /* tie off the name */
|
||||
if (pmatch_full (name,pattern,'.'))
|
||||
mm_lsub (stream,'.',name,LATT_NOSELECT);
|
||||
}
|
||||
}
|
||||
while ((c != '\015') && (c != '\012') && (c != EOF)) c = getc (f);
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update subscription status of newsrc
|
||||
* Accepts: MAIL stream
|
||||
* group
|
||||
* new subscription status character
|
||||
* Returns: T if successful, NIL otherwise
|
||||
*/
|
||||
|
||||
long newsrc_update (MAILSTREAM *stream,char *group,char state)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
char *newsrc = (char *) mail_parameters (stream,GET_NEWSRC,stream);
|
||||
long ret = NIL;
|
||||
FILE *f = fopen (newsrc,"r+b");
|
||||
if (f) { /* update existing file */
|
||||
int c = 0;
|
||||
char *s,nl[3];
|
||||
long pos = 0;
|
||||
nl[0] = nl[1] = nl[2]='\0'; /* no newline known yet */
|
||||
do { /* read newsrc */
|
||||
for (s = tmp; (s < (tmp + MAILTMPLEN - 1)) && ((c = getc (f)) != EOF) &&
|
||||
(c != ':') && (c != '!') && (c != '\015') && (c != '\012');
|
||||
*s++ = c) pos = ftell (f);
|
||||
*s = '\0'; /* tie off name */
|
||||
/* found the newsgroup? */
|
||||
if (((c == ':') || (c == '!')) && !strcmp (tmp,group)) {
|
||||
if (c == state) { /* already at that state? */
|
||||
if (c == ':') newsrc_error("Already subscribed to %.80s",group,WARN);
|
||||
ret = LONGT; /* noop the update */
|
||||
}
|
||||
/* write the character */
|
||||
else if (!fseek (f,pos,0)) ret = ((putc (state,f)) == EOF) ? NIL:LONGT;
|
||||
if (fclose (f) == EOF) ret = NIL;
|
||||
f = NIL; /* done with file */
|
||||
break;
|
||||
}
|
||||
/* gobble remainder of this line */
|
||||
while ((c != '\015') && (c != '\012') && (c != EOF)) c = getc (f);
|
||||
/* need to know about newlines and found it? */
|
||||
if (!nl[0] && ((c == '\015') || (c == '\012')) && ((nl[0]=c) == '\015')){
|
||||
/* sniff and see if an LF */
|
||||
if ((c = getc (f)) == '\012') nl[1] = c;
|
||||
else ungetc (c,f); /* nope, push it back */
|
||||
}
|
||||
} while (c != EOF);
|
||||
|
||||
if (f) { /* still haven't written it yet? */
|
||||
if (nl[0]) { /* know its newline convention? */
|
||||
fseek (f,0L,2); /* yes, seek to end of file */
|
||||
ret = newsrc_newstate (f,group,state,nl);
|
||||
}
|
||||
else { /* can't find a newline convention */
|
||||
fclose (f); /* punt the file */
|
||||
/* can't win if read something */
|
||||
if (pos) newsrc_error ("Unknown newline convention in %.80s",
|
||||
newsrc,ERROR);
|
||||
/* file must have been empty, rewrite it */
|
||||
else ret = newsrc_newstate(newsrc_create(stream,NIL),group,state,"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* create new file */
|
||||
else ret = newsrc_newstate (newsrc_create (stream,T),group,state,"\n");
|
||||
return ret; /* return with update status */
|
||||
}
|
||||
|
||||
/* Update newsgroup status in stream
|
||||
* Accepts: newsgroup name
|
||||
* MAIL stream
|
||||
* Returns: number of recent messages
|
||||
*/
|
||||
|
||||
long newsrc_read (char *group,MAILSTREAM *stream)
|
||||
{
|
||||
int c = 0;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
unsigned long i,j;
|
||||
MESSAGECACHE *elt;
|
||||
unsigned long m = 1,recent = 0,unseen = 0;
|
||||
FILE *f = fopen ((char *) mail_parameters (stream,GET_NEWSRC,stream),"rb");
|
||||
if (f) do { /* read newsrc */
|
||||
for (s = tmp; (s < (tmp + MAILTMPLEN - 1)) && ((c = getc (f)) != EOF) &&
|
||||
(c != ':') && (c != '!') && (c != '\015') && (c != '\012'); *s++ = c);
|
||||
*s = '\0'; /* tie off name */
|
||||
if ((c==':') || (c=='!')) { /* found newsgroup? */
|
||||
if (strcmp (tmp,group)) /* group name match? */
|
||||
while ((c != '\015') && (c != '\012') && (c != EOF)) c = getc (f);
|
||||
else { /* yes, skip leading whitespace */
|
||||
while ((c = getc (f)) == ' ');
|
||||
/* only if unprocessed messages */
|
||||
if (stream->nmsgs) while (f && (m <= stream->nmsgs)) {
|
||||
/* collect a number */
|
||||
if (isdigit (c)) { /* better have a number */
|
||||
for (i = 0,j = 0; isdigit (c); c = getc (f)) i = i*10 + (c-'0');
|
||||
if (c == '-') for (c = getc (f); isdigit (c); c = getc (f))
|
||||
j = j*10 +(c-'0');/* collect second value if range */
|
||||
if (!unseen && (mail_elt (stream,m)->private.uid < i)) unseen = m;
|
||||
/* skip messages before first value */
|
||||
while ((m <= stream->nmsgs) &&
|
||||
((elt = mail_elt (stream,m))->private.uid < i) && m++)
|
||||
elt->valid = T;
|
||||
/* do all messages in range */
|
||||
while ((m <= stream->nmsgs) && (elt = mail_elt (stream,m)) &&
|
||||
(j ? ((elt->private.uid >= i) && (elt->private.uid <= j)) :
|
||||
(elt->private.uid == i)) && m++)
|
||||
elt->valid = elt->deleted = T;
|
||||
}
|
||||
|
||||
switch (c) { /* what is the delimiter? */
|
||||
case ',': /* more to come */
|
||||
c = getc (f); /* get first character of number */
|
||||
break;
|
||||
default: /* bogus character */
|
||||
sprintf (tmp,"Bogus character 0x%x in news state",(unsigned int)c);
|
||||
MM_LOG (tmp,ERROR);
|
||||
case EOF: case '\015': case '\012':
|
||||
fclose (f); /* all done - close the file */
|
||||
f = NIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* empty newsgroup */
|
||||
while ((c != '\015') && (c != '\012') && (c != EOF)) c = getc (f);
|
||||
fclose (f); /* all done - close the file */
|
||||
f = NIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (f && (c != EOF)); /* until file closed or EOF */
|
||||
if (f) { /* still have file open? */
|
||||
sprintf (tmp,"No state for newsgroup %.80s found, reading as new",group);
|
||||
MM_LOG (tmp,WARN);
|
||||
fclose (f); /* close the file */
|
||||
}
|
||||
if (m <= stream->nmsgs) { /* any messages beyond newsrc range? */
|
||||
if (!unseen) unseen = m; /* then this must be the first unseen one */
|
||||
do {
|
||||
elt = mail_elt (stream,m++);
|
||||
elt->valid = elt->recent = T;
|
||||
++recent; /* count another recent message */
|
||||
}
|
||||
while (m <= stream->nmsgs);
|
||||
}
|
||||
if (unseen) { /* report first unseen message */
|
||||
sprintf (tmp,"[UNSEEN] %lu is first unseen message in %.80s",unseen,group);
|
||||
MM_NOTIFY (stream,tmp,(long) NIL);
|
||||
}
|
||||
return recent;
|
||||
}
|
||||
|
||||
/* Update newsgroup entry in newsrc
|
||||
* Accepts: newsgroup name
|
||||
* MAIL stream
|
||||
* Returns: T if successful, NIL otherwise
|
||||
*/
|
||||
|
||||
long newsrc_write (char *group,MAILSTREAM *stream)
|
||||
{
|
||||
long ret = NIL;
|
||||
int c = 0,d = EOF;
|
||||
char *newsrc = (char *) mail_parameters (stream,GET_NEWSRC,stream);
|
||||
char *s,tmp[MAILTMPLEN],backup[MAILTMPLEN],nl[3];
|
||||
FILE *f,*bf;
|
||||
nl[0] = nl[1] = nl[2] = '\0'; /* no newline known yet */
|
||||
if (f = fopen (newsrc,"rb")) {/* have existing newsrc file? */
|
||||
if (!(bf = fopen ((strcat (strcpy (backup,newsrc),OLDFILESUFFIX)),"wb"))) {
|
||||
fclose (f); /* punt input file */
|
||||
return newsrc_error("Can't create backup news state %.80s",backup,ERROR);
|
||||
}
|
||||
/* copy to backup file */
|
||||
while ((c = getc (f)) != EOF) {
|
||||
/* need to know about newlines and found it? */
|
||||
if (!nl[0] && ((c == '\015') || (c == '\012')) && ((nl[0]=c) == '\015')){
|
||||
/* sniff and see if an LF */
|
||||
if ((c = getc (f)) == '\012') nl[1] = c;
|
||||
ungetc (c,f); /* push it back */
|
||||
}
|
||||
/* write to backup file */
|
||||
if ((d = putc (c,bf)) == EOF) {
|
||||
fclose (f); /* punt input file */
|
||||
return newsrc_error ("Error writing backup news state %.80s",
|
||||
newsrc,ERROR);
|
||||
}
|
||||
}
|
||||
fclose (f); /* close existing file */
|
||||
if (fclose (bf) == EOF) /* and backup file */
|
||||
return newsrc_error ("Error closing backup news state %.80s",
|
||||
newsrc,ERROR);
|
||||
if (d == EOF) { /* open for write if empty file */
|
||||
if (f = newsrc_create (stream,NIL)) bf = NIL;
|
||||
else return NIL;
|
||||
}
|
||||
else if (!nl[0]) /* make sure newlines valid */
|
||||
return newsrc_error ("Unknown newline convention in %.80s",newsrc,ERROR);
|
||||
/* now read backup file */
|
||||
else if (!(bf = fopen (backup,"rb")))
|
||||
return newsrc_error ("Error reading backup news state %.80s",
|
||||
backup,ERROR);
|
||||
/* open newsrc for writing */
|
||||
else if (!(f = fopen (newsrc,"wb"))) {
|
||||
fclose (bf); /* punt backup */
|
||||
return newsrc_error ("Can't rewrite news state %.80s",newsrc,ERROR);
|
||||
}
|
||||
}
|
||||
else { /* create new newsrc file */
|
||||
if (f = newsrc_create (stream,T)) bf = NIL;
|
||||
else return NIL; /* can't create newsrc */
|
||||
}
|
||||
|
||||
while (bf) { /* read newsrc */
|
||||
for (s = tmp; (s < (tmp + MAILTMPLEN - 1)) && ((c = getc (bf)) != EOF) &&
|
||||
(c != ':') && (c != '!') && (c != '\015') && (c != '\012'); *s++ = c);
|
||||
*s = '\0'; /* tie off name */
|
||||
/* saw correct end of group delimiter? */
|
||||
if (tmp[0] && ((c == ':') || (c == '!'))) {
|
||||
/* yes, write newsgroup name and delimiter */
|
||||
if ((tmp[0] && (fputs (tmp,f) == EOF)) || ((putc (c,f)) == EOF))
|
||||
return newsrc_write_error (newsrc,bf,f);
|
||||
if (!strcmp (tmp,group)) {/* found correct group? */
|
||||
/* yes, write new status */
|
||||
if (!newsrc_newmessages (f,stream,nl[0] ? nl : "\n"))
|
||||
return newsrc_write_error (newsrc,bf,f);
|
||||
/* skip past old data */
|
||||
while (((c = getc (bf)) != EOF) && (c != '\015') && (c != '\012'));
|
||||
/* skip past newline */
|
||||
while ((c == '\015') || (c == '\012')) c = getc (bf);
|
||||
while (c != EOF) { /* copy remainder of file */
|
||||
if (putc (c,f) == EOF) return newsrc_write_error (newsrc,bf,f);
|
||||
c = getc (bf); /* get next character */
|
||||
}
|
||||
/* done with file */
|
||||
if (fclose (f) == EOF) return newsrc_write_error (newsrc,bf,NIL);
|
||||
f = NIL;
|
||||
}
|
||||
/* copy remainder of line */
|
||||
else while (((c = getc (bf)) != EOF) && (c != '\015') && (c != '\012'))
|
||||
if (putc (c,f) == EOF) return newsrc_write_error (newsrc,bf,f);
|
||||
if (c == '\015') { /* write CR if seen */
|
||||
if (putc (c,f) == EOF) return newsrc_write_error (newsrc,bf,f);
|
||||
/* sniff to see if LF */
|
||||
if (((c = getc (bf)) != EOF) && (c != '\012')) ungetc (c,bf);
|
||||
}
|
||||
/* write LF if seen */
|
||||
if ((c == '\012') && (putc (c,f) == EOF))
|
||||
return newsrc_write_error (newsrc,bf,f);
|
||||
}
|
||||
if (c == EOF) { /* hit end of file? */
|
||||
fclose (bf); /* yup, close the file */
|
||||
bf = NIL;
|
||||
}
|
||||
}
|
||||
if (f) { /* still have newsrc file open? */
|
||||
ret = ((fputs (group,f) != EOF) && ((putc (':',f)) != EOF) &&
|
||||
newsrc_newmessages (f,stream,nl[0] ? nl : "\n")) ? LONGT : NIL;
|
||||
if (fclose (f) == EOF) ret = newsrc_write_error (newsrc,NIL,NIL);
|
||||
}
|
||||
else ret = LONGT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get newsgroup state as text stream
|
||||
* Accepts: MAIL stream
|
||||
* newsgroup name
|
||||
* Returns: string containing newsgroup state, or NIL if not found
|
||||
*/
|
||||
|
||||
char *newsrc_state (MAILSTREAM *stream,char *group)
|
||||
{
|
||||
int c = 0;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
long pos;
|
||||
size_t size;
|
||||
FILE *f = fopen ((char *) mail_parameters (stream,GET_NEWSRC,stream),"rb");
|
||||
if (f) do { /* read newsrc */
|
||||
for (s = tmp; (s < (tmp + MAILTMPLEN - 1)) && ((c = getc (f)) != EOF) &&
|
||||
(c != ':') && (c != '!') && (c != '\015') && (c != '\012'); *s++ = c);
|
||||
*s = '\0'; /* tie off name */
|
||||
if ((c==':') || (c=='!')) { /* found newsgroup? */
|
||||
if (strcmp (tmp,group)) /* group name match? */
|
||||
while ((c != '\015') && (c != '\012') && (c != EOF)) c = getc (f);
|
||||
else { /* yes, skip leading whitespace */
|
||||
do pos = ftell (f);
|
||||
while ((c = getc (f)) == ' ');
|
||||
/* count characters in state */
|
||||
for (size = 0; (c != '\015') && (c != '\012') && (c != EOF); size++)
|
||||
c = getc (f);
|
||||
/* now copy it */
|
||||
s = (char *) fs_get (size + 1);
|
||||
fseek (f,pos,SEEK_SET);
|
||||
fread (s,(size_t) 1,size,f);
|
||||
s[size] = '\0'; /* tie off string */
|
||||
fclose (f); /* all done - close the file */
|
||||
return s;
|
||||
}
|
||||
}
|
||||
} while (f && (c != EOF)); /* until file closed or EOF */
|
||||
sprintf (tmp,"No state for newsgroup %.80s found",group);
|
||||
MM_LOG (tmp,WARN);
|
||||
if (f) fclose (f); /* close the file */
|
||||
return NIL; /* not found return */
|
||||
}
|
||||
|
||||
/* Check UID in newsgroup state
|
||||
* Accepts: newsgroup state string
|
||||
* uid
|
||||
* returned recent count
|
||||
* returned unseen count
|
||||
*/
|
||||
|
||||
void newsrc_check_uid (unsigned char *state,unsigned long uid,
|
||||
unsigned long *recent,unsigned long *unseen)
|
||||
{
|
||||
unsigned long i,j;
|
||||
while (*state) { /* until run out of state string */
|
||||
/* collect a number */
|
||||
for (i = 0; isdigit (*state); i = i*10 + (*state++ - '0'));
|
||||
if (*state != '-') j = i; /* coerce single mesage into range */
|
||||
else { /* have a range */
|
||||
for (j = 0; isdigit (*++state); j = j*10 + (*state - '0'));
|
||||
if (!j) j = i; /* guard against -0 */
|
||||
if (j < i) return; /* bogon if end less than start */
|
||||
}
|
||||
if (*state == ',') state++; /* skip past comma */
|
||||
else if (*state) return; /* otherwise it's a bogon */
|
||||
if (uid <= j) { /* covered by upper bound? */
|
||||
if (uid < i) ++*unseen; /* unseen if not covered by lower bound */
|
||||
return; /* don't need to look further */
|
||||
}
|
||||
}
|
||||
++*unseen; /* not found in any range, message is unseen */
|
||||
++*recent; /* and recent */
|
||||
}
|
||||
43
src/c-client/newsrc.h
Normal file
43
src/c-client/newsrc.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Newsrc manipulation routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 12 September 1994
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
long newsrc_error (char *fmt,char *text,long errflg);
|
||||
long newsrc_write_error (char *name,FILE *f1,FILE *f2);
|
||||
FILE *newsrc_create (MAILSTREAM *stream,int notify);
|
||||
long newsrc_newstate (FILE *f,char *group,char state,char *nl);
|
||||
long newsrc_newmessages (FILE *f,MAILSTREAM *stream,char *nl);
|
||||
void newsrc_lsub (MAILSTREAM *stream,char *pattern);
|
||||
long newsrc_update (MAILSTREAM *stream,char *group,char state);
|
||||
long newsrc_read (char *group,MAILSTREAM *stream);
|
||||
long newsrc_write (char *group,MAILSTREAM *stream);
|
||||
char *newsrc_state (MAILSTREAM *stream,char *group);
|
||||
void newsrc_check_uid (unsigned char *state,unsigned long uid,
|
||||
unsigned long *recent,unsigned long *unseen);
|
||||
34
src/c-client/nl.h
Normal file
34
src/c-client/nl.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Newline routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
unsigned long strcrlfcpy (unsigned char **dst,unsigned long *dstl,
|
||||
unsigned char *src,unsigned long srcl);
|
||||
unsigned long strcrlflen (STRING *s);
|
||||
2224
src/c-client/nntp.c
Normal file
2224
src/c-client/nntp.c
Normal file
File diff suppressed because it is too large
Load Diff
56
src/c-client/nntp.h
Normal file
56
src/c-client/nntp.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Network News Transfer Protocol (NNTP) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 10 February 1992
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Constants (should be in nntp.c) */
|
||||
|
||||
#define NNTPTCPPORT (long) 119 /* assigned TCP contact port */
|
||||
|
||||
|
||||
/* NNTP open options
|
||||
* For compatibility with the past, NOP_DEBUG must always be 1.
|
||||
*/
|
||||
|
||||
#define NOP_DEBUG (long) 0x1 /* debug protocol negotiations */
|
||||
#define NOP_READONLY (long) 0x2 /* read-only open */
|
||||
#define NOP_TRYSSL (long) 0x4 /* try SSL first */
|
||||
/* reserved for application use */
|
||||
#define NOP_RESERVED (unsigned long) 0xff000000
|
||||
|
||||
|
||||
/* Compatibility support names */
|
||||
|
||||
#define nntp_open(hostlist,options) \
|
||||
nntp_open_full (NIL,hostlist,"nntp",NIL,options)
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
SENDSTREAM *nntp_open_full (NETDRIVER *dv,char **hostlist,char *service,
|
||||
unsigned long port,long options);
|
||||
SENDSTREAM *nntp_close (SENDSTREAM *stream);
|
||||
long nntp_mail (SENDSTREAM *stream,ENVELOPE *msg,BODY *body);
|
||||
1091
src/c-client/pop3.c
Normal file
1091
src/c-client/pop3.c
Normal file
File diff suppressed because it is too large
Load Diff
2369
src/c-client/rfc822.c
Normal file
2369
src/c-client/rfc822.c
Normal file
File diff suppressed because it is too large
Load Diff
127
src/c-client/rfc822.h
Normal file
127
src/c-client/rfc822.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: RFC 2822 and MIME routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 27 July 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the NationalInstitutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
#define MAXGROUPDEPTH 50 /* RFC [2]822 doesn't allow any group nesting */
|
||||
#define MAXMIMEDEPTH 50 /* more than any sane MIMEgram */
|
||||
|
||||
/* Output buffering for RFC [2]822 */
|
||||
|
||||
typedef long (*soutr_t) (void *stream,char *string);
|
||||
typedef long (*rfc822out_t) (char *tmp,ENVELOPE *env,BODY *body,soutr_t f,
|
||||
void *s,long ok8bit);
|
||||
|
||||
typedef struct rfc822buffer {
|
||||
soutr_t f; /* I/O flush routine */
|
||||
void *s; /* stream for I/O routine */
|
||||
char *beg; /* start of buffer */
|
||||
char *cur; /* current buffer pointer */
|
||||
char *end; /* end of buffer */
|
||||
} RFC822BUFFER;
|
||||
|
||||
typedef long (*rfc822outfull_t) (RFC822BUFFER *buf,ENVELOPE *env,BODY *body,
|
||||
long ok8bit);
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
char *rfc822_default_subtype (unsigned short type);
|
||||
void rfc822_parse_msg_full (ENVELOPE **en,BODY **bdy,char *s,unsigned long i,
|
||||
STRING *bs,char *host,unsigned long depth,
|
||||
unsigned long flags);
|
||||
void rfc822_parse_content (BODY *body,STRING *bs,char *h,unsigned long depth,
|
||||
unsigned long flags);
|
||||
void rfc822_parse_content_header (BODY *body,char *name,char *s);
|
||||
void rfc822_parse_parameter (PARAMETER **par,char *text);
|
||||
void rfc822_parse_adrlist (ADDRESS **lst,char *string,char *host);
|
||||
ADDRESS *rfc822_parse_address (ADDRESS **lst,ADDRESS *last,char **string,
|
||||
char *defaulthost,unsigned long depth);
|
||||
ADDRESS *rfc822_parse_group (ADDRESS **lst,ADDRESS *last,char **string,
|
||||
char *defaulthost,unsigned long depth);
|
||||
ADDRESS *rfc822_parse_mailbox (char **string,char *defaulthost);
|
||||
long rfc822_phraseonly (char *end);
|
||||
ADDRESS *rfc822_parse_routeaddr (char *string,char **ret,char *defaulthost);
|
||||
ADDRESS *rfc822_parse_addrspec (char *string,char **ret,char *defaulthost);
|
||||
char *rfc822_parse_domain (char *string,char **end);
|
||||
char *rfc822_parse_phrase (char *string);
|
||||
char *rfc822_parse_word (char *string,const char *delimiters);
|
||||
char *rfc822_cpy (char *src);
|
||||
char *rfc822_quote (char *src);
|
||||
ADDRESS *rfc822_cpy_adr (ADDRESS *adr);
|
||||
void rfc822_skipws (char **s);
|
||||
char *rfc822_skip_comment (char **s,long trim);
|
||||
|
||||
long rfc822_output_full (RFC822BUFFER *buf,ENVELOPE *env,BODY *body,long ok8);
|
||||
long rfc822_output_flush (RFC822BUFFER *buf);
|
||||
long rfc822_output_header (RFC822BUFFER *buf,ENVELOPE *env,BODY *body,
|
||||
const char *specials,long flags);
|
||||
long rfc822_output_header_line (RFC822BUFFER *buf,char *type,long resent,
|
||||
char *text);
|
||||
long rfc822_output_address_line (RFC822BUFFER *buf,char *type,long resent,
|
||||
ADDRESS *adr,const char *specials);
|
||||
long rfc822_output_address_list (RFC822BUFFER *buf,ADDRESS *adr,long pretty,
|
||||
const char *specials);
|
||||
long rfc822_output_address (RFC822BUFFER *buf,ADDRESS *adr);
|
||||
long rfc822_output_cat (RFC822BUFFER *buf,char *src,const char *specials);
|
||||
long rfc822_output_parameter (RFC822BUFFER *buf,PARAMETER *param);
|
||||
long rfc822_output_stringlist (RFC822BUFFER *buf,STRINGLIST *stl);
|
||||
long rfc822_output_body_header (RFC822BUFFER *buf,BODY *body);
|
||||
void rfc822_encode_body_7bit (ENVELOPE *env,BODY *body);
|
||||
void rfc822_encode_body_8bit (ENVELOPE *env,BODY *body);
|
||||
long rfc822_output_text (RFC822BUFFER *buf,BODY *body);
|
||||
void *rfc822_base64 (unsigned char *src,unsigned long srcl,unsigned long *len);
|
||||
unsigned char *rfc822_binary (void *src,unsigned long srcl,unsigned long *len);
|
||||
unsigned char *rfc822_qprint (unsigned char *src,unsigned long srcl,
|
||||
unsigned long *len);
|
||||
unsigned char *rfc822_8bit (unsigned char *src,unsigned long srcl,
|
||||
unsigned long *len);
|
||||
|
||||
/* Legacy routines for compatibility with the past */
|
||||
|
||||
void rfc822_header (char *header,ENVELOPE *env,BODY *body);
|
||||
void rfc822_header_line (char **header,char *type,ENVELOPE *env,char *text);
|
||||
void rfc822_address_line (char **header,char *type,ENVELOPE *env,ADDRESS *adr);
|
||||
char *rfc822_write_address_full (char *dest,ADDRESS *adr,char *base);
|
||||
void rfc822_address (char *dest,ADDRESS *adr);
|
||||
void rfc822_cat (char *dest,char *src,const char *specials);
|
||||
void rfc822_write_body_header (char **header,BODY *body);
|
||||
long rfc822_output (char *t,ENVELOPE *env,BODY *body,soutr_t f,void *s,
|
||||
long ok8bit);
|
||||
long rfc822_output_body (BODY *body,soutr_t f,void *s);
|
||||
|
||||
|
||||
#define rfc822_write_address(dest,adr) \
|
||||
rfc822_write_address_full (dest,adr,NIL)
|
||||
|
||||
#define rfc822_parse_msg(en,bdy,s,i,bs,host,flags) \
|
||||
rfc822_parse_msg_full (en,bdy,s,i,bs,host,0,flags)
|
||||
129
src/c-client/smanager.c
Normal file
129
src/c-client/smanager.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Subscription Manager
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 3 December 1992
|
||||
* Last Edited: 6 December 2006
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "c-client.h"
|
||||
|
||||
/* Subscribe to mailbox
|
||||
* Accepts: mailbox name
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long sm_subscribe (char *mailbox)
|
||||
{
|
||||
FILE *f;
|
||||
char *s,db[MAILTMPLEN],tmp[MAILTMPLEN];
|
||||
/* canonicalize INBOX */
|
||||
if (!compare_cstring (mailbox,"INBOX")) mailbox = "INBOX";
|
||||
SUBSCRIPTIONFILE (db); /* open subscription database */
|
||||
if (f = fopen (db,"r")) { /* make sure not already there */
|
||||
while (fgets (tmp,MAILTMPLEN,f)) {
|
||||
if (s = strchr (tmp,'\n')) *s = '\0';
|
||||
if (!strcmp (tmp,mailbox)) {/* already subscribed? */
|
||||
sprintf (tmp,"Already subscribed to mailbox %.80s",mailbox);
|
||||
MM_LOG (tmp,ERROR);
|
||||
fclose (f);
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
fclose (f);
|
||||
}
|
||||
if (!(f = fopen (db,"a"))) { /* append new entry */
|
||||
MM_LOG ("Can't append to subscription database",ERROR);
|
||||
return NIL;
|
||||
}
|
||||
fprintf (f,"%s\n",mailbox);
|
||||
return (fclose (f) == EOF) ? NIL : T;
|
||||
}
|
||||
|
||||
/* Unsubscribe from mailbox
|
||||
* Accepts: mailbox name
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long sm_unsubscribe (char *mailbox)
|
||||
{
|
||||
FILE *f,*tf;
|
||||
char *s,tmp[MAILTMPLEN],old[MAILTMPLEN],newname[MAILTMPLEN];
|
||||
int found = NIL;
|
||||
/* canonicalize INBOX */
|
||||
if (!compare_cstring (mailbox,"INBOX")) mailbox = "INBOX";
|
||||
SUBSCRIPTIONFILE (old); /* make file names */
|
||||
SUBSCRIPTIONTEMP (newname);
|
||||
if (!(f = fopen (old,"r"))) /* open subscription database */
|
||||
MM_LOG ("No subscriptions",ERROR);
|
||||
else if (!(tf = fopen (newname,"w"))) {
|
||||
MM_LOG ("Can't create subscription temporary file",ERROR);
|
||||
fclose (f);
|
||||
}
|
||||
else {
|
||||
while (fgets (tmp,MAILTMPLEN,f)) {
|
||||
if (s = strchr (tmp,'\n')) *s = '\0';
|
||||
if (strcmp (tmp,mailbox)) fprintf (tf,"%s\n",tmp);
|
||||
else found = T; /* found the name */
|
||||
}
|
||||
fclose (f);
|
||||
if (fclose (tf) == EOF)
|
||||
MM_LOG ("Can't write subscription temporary file",ERROR);
|
||||
else if (!found) {
|
||||
sprintf (tmp,"Not subscribed to mailbox %.80s",mailbox);
|
||||
MM_LOG (tmp,ERROR); /* error if at end */
|
||||
}
|
||||
else if (!unlink (old) && !rename (newname,old)) return LONGT;
|
||||
else MM_LOG ("Can't update subscription database",ERROR);
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* Read subscription database
|
||||
* Accepts: pointer to subscription database handle (handle NIL if first time)
|
||||
* Returns: character string for subscription database or NIL if done
|
||||
*/
|
||||
|
||||
static char sbname[MAILTMPLEN];
|
||||
|
||||
char *sm_read (void **sdb)
|
||||
{
|
||||
FILE *f = (FILE *) *sdb;
|
||||
char *s;
|
||||
if (!f) { /* first time through? */
|
||||
SUBSCRIPTIONFILE (sbname); /* open subscription database */
|
||||
/* make sure not already there */
|
||||
if (f = fopen (sbname,"r")) *sdb = (void *) f;
|
||||
else return NIL;
|
||||
}
|
||||
if (fgets (sbname,MAILTMPLEN,f)) {
|
||||
if (s = strchr (sbname,'\n')) *s = '\0';
|
||||
return sbname;
|
||||
}
|
||||
fclose (f); /* all done */
|
||||
*sdb = NIL; /* zap sdb */
|
||||
return NIL;
|
||||
}
|
||||
793
src/c-client/smtp.c
Normal file
793
src/c-client/smtp.c
Normal file
@@ -0,0 +1,793 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Simple Mail Transfer Protocol (SMTP) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 27 July 1988
|
||||
* Last Edited: 28 January 2008
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the National Institutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "c-client.h"
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define SMTPSSLPORT (long) 465 /* former assigned SSL TCP contact port */
|
||||
#define SMTPGREET (long) 220 /* SMTP successful greeting */
|
||||
#define SMTPAUTHED (long) 235 /* SMTP successful authentication */
|
||||
#define SMTPOK (long) 250 /* SMTP OK code */
|
||||
#define SMTPAUTHREADY (long) 334/* SMTP ready for authentication */
|
||||
#define SMTPREADY (long) 354 /* SMTP ready for data */
|
||||
#define SMTPSOFTFATAL (long) 421/* SMTP soft fatal code */
|
||||
#define SMTPWANTAUTH (long) 505 /* SMTP authentication needed */
|
||||
#define SMTPWANTAUTH2 (long) 530/* SMTP authentication needed */
|
||||
#define SMTPUNAVAIL (long) 550 /* SMTP mailbox unavailable */
|
||||
#define SMTPHARDERROR (long) 554/* SMTP miscellaneous hard failure */
|
||||
|
||||
|
||||
/* Convenient access to protocol-specific data */
|
||||
|
||||
#define ESMTP stream->protocol.esmtp
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void *smtp_challenge (void *s,unsigned long *len);
|
||||
long smtp_response (void *s,char *response,unsigned long size);
|
||||
long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp);
|
||||
long smtp_rcpt (SENDSTREAM *stream,ADDRESS *adr,long *error);
|
||||
long smtp_send (SENDSTREAM *stream,char *command,char *args);
|
||||
long smtp_reply (SENDSTREAM *stream);
|
||||
long smtp_ehlo (SENDSTREAM *stream,char *host,NETMBX *mb);
|
||||
long smtp_fake (SENDSTREAM *stream,char *text);
|
||||
static long smtp_seterror (SENDSTREAM *stream,long code,char *text);
|
||||
long smtp_soutr (void *stream,char *s);
|
||||
|
||||
/* Mailer parameters */
|
||||
|
||||
static unsigned long smtp_maxlogintrials = MAXLOGINTRIALS;
|
||||
static long smtp_port = 0; /* default port override */
|
||||
static long smtp_sslport = 0;
|
||||
|
||||
|
||||
#ifndef RFC2821
|
||||
#define RFC2821 /* RFC 2821 compliance */
|
||||
#endif
|
||||
|
||||
/* SMTP limits, current as of RFC 2821 */
|
||||
|
||||
#define SMTPMAXLOCALPART 64
|
||||
#define SMTPMAXDOMAIN 255
|
||||
#define SMTPMAXPATH 256
|
||||
|
||||
|
||||
/* I have seen local parts of more than 64 octets, in spite of the SMTP
|
||||
* limits. So, we'll have a more generous limit that's still guaranteed
|
||||
* not to pop the buffer, and let the server worry about it. As of this
|
||||
* writing, it comes out to 240. Anyone with a mailbox name larger than
|
||||
* that is in serious need of a life or at least a new ISP! 23 June 1998
|
||||
*/
|
||||
|
||||
#define MAXLOCALPART ((MAILTMPLEN - (SMTPMAXDOMAIN + SMTPMAXPATH + 32)) / 2)
|
||||
|
||||
/* Mail Transfer Protocol manipulate driver parameters
|
||||
* Accepts: function code
|
||||
* function-dependent value
|
||||
* Returns: function-dependent return value
|
||||
*/
|
||||
|
||||
void *smtp_parameters (long function,void *value)
|
||||
{
|
||||
switch ((int) function) {
|
||||
case SET_MAXLOGINTRIALS:
|
||||
smtp_maxlogintrials = (unsigned long) value;
|
||||
break;
|
||||
case GET_MAXLOGINTRIALS:
|
||||
value = (void *) smtp_maxlogintrials;
|
||||
break;
|
||||
case SET_SMTPPORT:
|
||||
smtp_port = (long) value;
|
||||
break;
|
||||
case GET_SMTPPORT:
|
||||
value = (void *) smtp_port;
|
||||
break;
|
||||
case SET_SSLSMTPPORT:
|
||||
smtp_sslport = (long) value;
|
||||
break;
|
||||
case GET_SSLSMTPPORT:
|
||||
value = (void *) smtp_sslport;
|
||||
break;
|
||||
default:
|
||||
value = NIL; /* error case */
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Mail Transfer Protocol open connection
|
||||
* Accepts: network driver
|
||||
* service host list
|
||||
* port number
|
||||
* service name
|
||||
* SMTP open options
|
||||
* Returns: SEND stream on success, NIL on failure
|
||||
*/
|
||||
|
||||
SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service,
|
||||
unsigned long port,long options)
|
||||
{
|
||||
SENDSTREAM *stream = NIL;
|
||||
long reply;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
NETSTREAM *netstream;
|
||||
NETMBX mb;
|
||||
if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR);
|
||||
/* maximum domain name is 64 characters */
|
||||
else do if (strlen (*hostlist) < SMTPMAXDOMAIN) {
|
||||
sprintf (tmp,"{%.1000s}",*hostlist);
|
||||
if (!mail_valid_net_parse_work (tmp,&mb,service ? service : "smtp") ||
|
||||
mb.anoflag || mb.readonlyflag) {
|
||||
sprintf (tmp,"Invalid host specifier: %.80s",*hostlist);
|
||||
mm_log (tmp,ERROR);
|
||||
}
|
||||
else { /* light tryssl flag if requested */
|
||||
mb.trysslflag = (options & SOP_TRYSSL) ? T : NIL;
|
||||
/* explicit port overrides all */
|
||||
if (mb.port) port = mb.port;
|
||||
/* else /submit overrides port argument */
|
||||
else if (!compare_cstring (mb.service,"submit")) {
|
||||
port = SUBMITTCPPORT; /* override port, use IANA name */
|
||||
strcpy (mb.service,"submission");
|
||||
}
|
||||
/* else port argument overrides SMTP port */
|
||||
else if (!port) port = smtp_port ? smtp_port : SMTPTCPPORT;
|
||||
if (netstream = /* try to open ordinary connection */
|
||||
net_open (&mb,dv,port,
|
||||
(NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL),
|
||||
"*smtps",smtp_sslport ? smtp_sslport : SMTPSSLPORT)) {
|
||||
stream = (SENDSTREAM *) memset (fs_get (sizeof (SENDSTREAM)),0,
|
||||
sizeof (SENDSTREAM));
|
||||
stream->netstream = netstream;
|
||||
stream->host = cpystr ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ?
|
||||
net_host (netstream) : mb.host);
|
||||
stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL;
|
||||
if (options & SOP_SECURE) mb.secflag = T;
|
||||
/* get name of local host to use */
|
||||
s = compare_cstring ("localhost",mb.host) ?
|
||||
net_localhost (netstream) : "localhost";
|
||||
|
||||
do reply = smtp_reply (stream);
|
||||
while ((reply < 100) || (stream->reply[3] == '-'));
|
||||
if (reply != SMTPGREET){/* get SMTP greeting */
|
||||
sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply);
|
||||
mm_log (tmp,ERROR);
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
/* try EHLO first, then HELO */
|
||||
else if (((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) &&
|
||||
((reply = smtp_send (stream,"HELO",s)) != SMTPOK)) {
|
||||
sprintf (tmp,"SMTP hello failure: %.80s",stream->reply);
|
||||
mm_log (tmp,ERROR);
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
else {
|
||||
NETDRIVER *ssld =(NETDRIVER *)mail_parameters(NIL,GET_SSLDRIVER,NIL);
|
||||
sslstart_t stls = (sslstart_t) mail_parameters(NIL,GET_SSLSTART,NIL);
|
||||
ESMTP.ok = T; /* ESMTP server, start TLS if present */
|
||||
if (!dv && stls && ESMTP.service.starttls &&
|
||||
!mb.sslflag && !mb.notlsflag &&
|
||||
(smtp_send (stream,"STARTTLS",NIL) == SMTPGREET)) {
|
||||
mb.tlsflag = T; /* TLS OK, get into TLS at this end */
|
||||
stream->netstream->dtb = ssld;
|
||||
/* TLS started, negotiate it */
|
||||
if (!(stream->netstream->stream = (*stls)
|
||||
(stream->netstream->stream,mb.host,
|
||||
(mb.tlssslv23 ? NIL : NET_TLSCLIENT) |
|
||||
(mb.novalidate ? NET_NOVALIDATECERT:NIL)))){
|
||||
/* TLS negotiation failed after STARTTLS */
|
||||
sprintf (tmp,"Unable to negotiate TLS with this server: %.80s",
|
||||
mb.host);
|
||||
mm_log (tmp,ERROR);
|
||||
/* close without doing QUIT */
|
||||
if (stream->netstream) net_close (stream->netstream);
|
||||
stream->netstream = NIL;
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
/* TLS OK, re-negotiate EHLO */
|
||||
else if ((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) {
|
||||
sprintf (tmp,"SMTP EHLO failure after STARTTLS: %.80s",
|
||||
stream->reply);
|
||||
mm_log (tmp,ERROR);
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
else ESMTP.ok = T; /* TLS OK and EHLO successful */
|
||||
}
|
||||
else if (mb.tlsflag) {/* user specified /tls but can't do it */
|
||||
sprintf (tmp,"TLS unavailable with this server: %.80s",mb.host);
|
||||
mm_log (tmp,ERROR);
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
|
||||
/* remote name for authentication */
|
||||
if (stream && ((mb.secflag || mb.user[0]))) {
|
||||
if (ESMTP.auth) { /* use authenticator? */
|
||||
if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) {
|
||||
/* remote name for authentication */
|
||||
strncpy (mb.host,
|
||||
(long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ?
|
||||
net_remotehost (netstream) : net_host (netstream),
|
||||
NETMAXHOST-1);
|
||||
mb.host[NETMAXHOST-1] = '\0';
|
||||
}
|
||||
if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream);
|
||||
}
|
||||
else { /* no available authenticators? */
|
||||
sprintf (tmp,"%sSMTP authentication not available: %.80s",
|
||||
mb.secflag ? "Secure " : "",mb.host);
|
||||
mm_log (tmp,ERROR);
|
||||
stream = smtp_close (stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!stream && *++hostlist);
|
||||
if (stream) { /* set stream options if have a stream */
|
||||
if (options &(SOP_DSN | SOP_DSN_NOTIFY_FAILURE | SOP_DSN_NOTIFY_DELAY |
|
||||
SOP_DSN_NOTIFY_SUCCESS | SOP_DSN_RETURN_FULL)) {
|
||||
ESMTP.dsn.want = T;
|
||||
if (options & SOP_DSN_NOTIFY_FAILURE) ESMTP.dsn.notify.failure = T;
|
||||
if (options & SOP_DSN_NOTIFY_DELAY) ESMTP.dsn.notify.delay = T;
|
||||
if (options & SOP_DSN_NOTIFY_SUCCESS) ESMTP.dsn.notify.success = T;
|
||||
if (options & SOP_DSN_RETURN_FULL) ESMTP.dsn.full = T;
|
||||
}
|
||||
if (options & SOP_8BITMIME) ESMTP.eightbit.want = T;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
/* SMTP authenticate
|
||||
* Accepts: stream to login
|
||||
* parsed network mailbox structure
|
||||
* scratch buffer
|
||||
* place to return user name
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp)
|
||||
{
|
||||
unsigned long trial,auths;
|
||||
char *lsterr = NIL;
|
||||
char usr[MAILTMPLEN];
|
||||
AUTHENTICATOR *at;
|
||||
long ret = NIL;
|
||||
for (auths = ESMTP.auth, stream->saslcancel = NIL;
|
||||
!ret && stream->netstream && auths &&
|
||||
(at = mail_lookup_auth (find_rightmost_bit (&auths) + 1)); ) {
|
||||
if (lsterr) { /* previous authenticator failed? */
|
||||
sprintf (tmp,"Retrying using %s authentication after %.80s",
|
||||
at->name,lsterr);
|
||||
mm_log (tmp,NIL);
|
||||
fs_give ((void **) &lsterr);
|
||||
}
|
||||
trial = 0; /* initial trial count */
|
||||
tmp[0] = '\0'; /* empty buffer */
|
||||
if (stream->netstream) do {
|
||||
if (lsterr) {
|
||||
sprintf (tmp,"Retrying %s authentication after %.80s",at->name,lsterr);
|
||||
mm_log (tmp,WARN);
|
||||
fs_give ((void **) &lsterr);
|
||||
}
|
||||
stream->saslcancel = NIL;
|
||||
if (smtp_send (stream,"AUTH",at->name) == SMTPAUTHREADY) {
|
||||
/* hide client authentication responses */
|
||||
if (!(at->flags & AU_SECURE)) stream->sensitive = T;
|
||||
if ((*at->client) (smtp_challenge,smtp_response,"smtp",mb,stream,
|
||||
&trial,usr)) {
|
||||
if (stream->replycode == SMTPAUTHED) {
|
||||
ESMTP.auth = NIL; /* disable authenticators */
|
||||
ret = LONGT;
|
||||
}
|
||||
/* if main program requested cancellation */
|
||||
else if (!trial) mm_log ("SMTP Authentication cancelled",ERROR);
|
||||
}
|
||||
stream->sensitive = NIL;/* unhide */
|
||||
}
|
||||
/* remember response if error and no cancel */
|
||||
if (!ret && trial) lsterr = cpystr (stream->reply);
|
||||
} while (!ret && stream->netstream && trial &&
|
||||
(trial < smtp_maxlogintrials));
|
||||
}
|
||||
if (lsterr) { /* previous authenticator failed? */
|
||||
if (!stream->saslcancel) { /* don't do this if a cancel */
|
||||
sprintf (tmp,"Can not authenticate to SMTP server: %.80s",lsterr);
|
||||
mm_log (tmp,ERROR);
|
||||
}
|
||||
fs_give ((void **) &lsterr);
|
||||
}
|
||||
return ret; /* authentication failed */
|
||||
}
|
||||
|
||||
/* Get challenge to authenticator in binary
|
||||
* Accepts: stream
|
||||
* pointer to returned size
|
||||
* Returns: challenge or NIL if not challenge
|
||||
*/
|
||||
|
||||
void *smtp_challenge (void *s,unsigned long *len)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
void *ret = NIL;
|
||||
SENDSTREAM *stream = (SENDSTREAM *) s;
|
||||
if ((stream->replycode == SMTPAUTHREADY) &&
|
||||
!(ret = rfc822_base64 ((unsigned char *) stream->reply + 4,
|
||||
strlen (stream->reply + 4),len))) {
|
||||
sprintf (tmp,"SMTP SERVER BUG (invalid challenge): %.80s",stream->reply+4);
|
||||
mm_log (tmp,ERROR);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Send authenticator response in BASE64
|
||||
* Accepts: MAIL stream
|
||||
* string to send
|
||||
* length of string
|
||||
* Returns: T, always
|
||||
*/
|
||||
|
||||
long smtp_response (void *s,char *response,unsigned long size)
|
||||
{
|
||||
SENDSTREAM *stream = (SENDSTREAM *) s;
|
||||
unsigned long i,j;
|
||||
char *t,*u;
|
||||
if (response) { /* make CRLFless BASE64 string */
|
||||
if (size) {
|
||||
for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
|
||||
j < i; j++) if (t[j] > ' ') *u++ = t[j];
|
||||
*u = '\0'; /* tie off string */
|
||||
i = smtp_send (stream,t,NIL);
|
||||
fs_give ((void **) &t);
|
||||
}
|
||||
else i = smtp_send (stream,"",NIL);
|
||||
}
|
||||
else { /* abort requested */
|
||||
i = smtp_send (stream,"*",NIL);
|
||||
stream->saslcancel = T; /* mark protocol-requested SASL cancel */
|
||||
}
|
||||
return LONGT;
|
||||
}
|
||||
|
||||
/* Mail Transfer Protocol close connection
|
||||
* Accepts: SEND stream
|
||||
* Returns: NIL always
|
||||
*/
|
||||
|
||||
SENDSTREAM *smtp_close (SENDSTREAM *stream)
|
||||
{
|
||||
if (stream) { /* send "QUIT" */
|
||||
if (stream->netstream) { /* do close actions if have netstream */
|
||||
smtp_send (stream,"QUIT",NIL);
|
||||
if (stream->netstream) /* could have been closed during "QUIT" */
|
||||
net_close (stream->netstream);
|
||||
}
|
||||
/* clean up */
|
||||
if (stream->host) fs_give ((void **) &stream->host);
|
||||
if (stream->reply) fs_give ((void **) &stream->reply);
|
||||
if (ESMTP.dsn.envid) fs_give ((void **) &ESMTP.dsn.envid);
|
||||
if (ESMTP.atrn.domains) fs_give ((void **) &ESMTP.atrn.domains);
|
||||
fs_give ((void **) &stream);/* flush the stream */
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* Mail Transfer Protocol deliver mail
|
||||
* Accepts: SEND stream
|
||||
* delivery option (MAIL, SEND, SAML, SOML)
|
||||
* message envelope
|
||||
* message body
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long smtp_mail (SENDSTREAM *stream,char *type,ENVELOPE *env,BODY *body)
|
||||
{
|
||||
RFC822BUFFER buf;
|
||||
char tmp[SENDBUFLEN+1];
|
||||
long error = NIL;
|
||||
long retry = NIL;
|
||||
buf.f = smtp_soutr; /* initialize buffer */
|
||||
buf.s = stream->netstream;
|
||||
buf.end = (buf.beg = buf.cur = tmp) + SENDBUFLEN;
|
||||
tmp[SENDBUFLEN] = '\0'; /* must have additional null guard byte */
|
||||
if (!(env->to || env->cc || env->bcc)) {
|
||||
/* no recipients in request */
|
||||
smtp_seterror (stream,SMTPHARDERROR,"No recipients specified");
|
||||
return NIL;
|
||||
}
|
||||
do { /* make sure stream is in good shape */
|
||||
smtp_send (stream,"RSET",NIL);
|
||||
if (retry) { /* need to retry with authentication? */
|
||||
NETMBX mb;
|
||||
/* yes, build remote name for authentication */
|
||||
sprintf (tmp,"{%.200s/smtp%s}<none>",
|
||||
(long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ?
|
||||
((long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ?
|
||||
net_remotehost (stream->netstream) :
|
||||
net_host (stream->netstream)) :
|
||||
stream->host,
|
||||
(stream->netstream->dtb ==
|
||||
(NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL)) ?
|
||||
"/ssl" : "");
|
||||
mail_valid_net_parse (tmp,&mb);
|
||||
if (!smtp_auth (stream,&mb,tmp)) return NIL;
|
||||
retry = NIL; /* no retry at this point */
|
||||
}
|
||||
|
||||
strcpy (tmp,"FROM:<"); /* compose "MAIL FROM:<return-path>" */
|
||||
#ifdef RFC2821
|
||||
if (env->return_path && env->return_path->host &&
|
||||
!((strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) ||
|
||||
(strlen (env->return_path->host) > SMTPMAXDOMAIN))) {
|
||||
rfc822_cat (tmp,env->return_path->mailbox,NIL);
|
||||
sprintf (tmp + strlen (tmp),"@%s",env->return_path->host);
|
||||
}
|
||||
#else /* old code with A-D-L support */
|
||||
if (env->return_path && env->return_path->host &&
|
||||
!((env->return_path->adl &&
|
||||
(strlen (env->return_path->adl) > SMTPMAXPATH)) ||
|
||||
(strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) ||
|
||||
(strlen (env->return_path->host) > SMTPMAXDOMAIN)))
|
||||
rfc822_address (tmp,env->return_path);
|
||||
#endif
|
||||
strcat (tmp,">");
|
||||
if (ESMTP.ok) {
|
||||
if (ESMTP.eightbit.ok && ESMTP.eightbit.want)
|
||||
strcat (tmp," BODY=8BITMIME");
|
||||
if (ESMTP.dsn.ok && ESMTP.dsn.want) {
|
||||
strcat (tmp,ESMTP.dsn.full ? " RET=FULL" : " RET=HDRS");
|
||||
if (ESMTP.dsn.envid)
|
||||
sprintf (tmp + strlen (tmp)," ENVID=%.100s",ESMTP.dsn.envid);
|
||||
}
|
||||
}
|
||||
/* send "MAIL FROM" command */
|
||||
switch (smtp_send (stream,type,tmp)) {
|
||||
case SMTPUNAVAIL: /* mailbox unavailable? */
|
||||
case SMTPWANTAUTH: /* wants authentication? */
|
||||
case SMTPWANTAUTH2:
|
||||
if (ESMTP.auth) retry = T;/* yes, retry with authentication */
|
||||
case SMTPOK: /* looks good */
|
||||
break;
|
||||
default: /* other failure */
|
||||
return NIL;
|
||||
}
|
||||
/* negotiate the recipients */
|
||||
if (!retry && env->to) retry = smtp_rcpt (stream,env->to,&error);
|
||||
if (!retry && env->cc) retry = smtp_rcpt (stream,env->cc,&error);
|
||||
if (!retry && env->bcc) retry = smtp_rcpt (stream,env->bcc,&error);
|
||||
if (!retry && error) { /* any recipients failed? */
|
||||
smtp_send (stream,"RSET",NIL);
|
||||
smtp_seterror (stream,SMTPHARDERROR,"One or more recipients failed");
|
||||
return NIL;
|
||||
}
|
||||
} while (retry);
|
||||
/* negotiate data command */
|
||||
if (!(smtp_send (stream,"DATA",NIL) == SMTPREADY)) return NIL;
|
||||
/* send message data */
|
||||
if (!rfc822_output_full (&buf,env,body,
|
||||
ESMTP.eightbit.ok && ESMTP.eightbit.want)) {
|
||||
smtp_fake (stream,"SMTP connection broken (message data)");
|
||||
return NIL; /* can't do much else here */
|
||||
}
|
||||
/* send trailing dot */
|
||||
return (smtp_send (stream,".",NIL) == SMTPOK) ? LONGT : NIL;
|
||||
}
|
||||
|
||||
/* Simple Mail Transfer Protocol send VERBose
|
||||
* Accepts: SMTP stream
|
||||
* Returns: T if successful, else NIL
|
||||
*
|
||||
* Descriptive text formerly in [al]pine sources:
|
||||
* At worst, this command may cause the SMTP connection to get nuked. Modern
|
||||
* sendmail's recognize it, and possibly other SMTP implementations (the "ON"
|
||||
* arg is for PMDF). What's more, if it works, the reply code and accompanying
|
||||
* text may vary from server to server.
|
||||
*/
|
||||
|
||||
long smtp_verbose (SENDSTREAM *stream)
|
||||
{
|
||||
/* accept any 2xx reply code */
|
||||
return ((smtp_send (stream,"VERB","ON") / (long) 100) == 2) ? LONGT : NIL;
|
||||
}
|
||||
|
||||
/* Internal routines */
|
||||
|
||||
|
||||
/* Simple Mail Transfer Protocol send recipient
|
||||
* Accepts: SMTP stream
|
||||
* address list
|
||||
* pointer to error flag
|
||||
* Returns: T if should retry, else NIL
|
||||
*/
|
||||
|
||||
long smtp_rcpt (SENDSTREAM *stream,ADDRESS *adr,long *error)
|
||||
{
|
||||
char *s,tmp[2*MAILTMPLEN],orcpt[MAILTMPLEN];
|
||||
while (adr) { /* for each address on the list */
|
||||
/* clear any former error */
|
||||
if (adr->error) fs_give ((void **) &adr->error);
|
||||
if (adr->host) { /* ignore group syntax */
|
||||
/* enforce SMTP limits to protect the buffer */
|
||||
if (strlen (adr->mailbox) > MAXLOCALPART) {
|
||||
adr->error = cpystr ("501 Recipient name too long");
|
||||
*error = T;
|
||||
}
|
||||
else if ((strlen (adr->host) > SMTPMAXDOMAIN)) {
|
||||
adr->error = cpystr ("501 Recipient domain too long");
|
||||
*error = T;
|
||||
}
|
||||
#ifndef RFC2821 /* old code with A-D-L support */
|
||||
else if (adr->adl && (strlen (adr->adl) > SMTPMAXPATH)) {
|
||||
adr->error = cpystr ("501 Path too long");
|
||||
*error = T;
|
||||
}
|
||||
#endif
|
||||
|
||||
else {
|
||||
strcpy (tmp,"TO:<"); /* compose "RCPT TO:<return-path>" */
|
||||
#ifdef RFC2821
|
||||
rfc822_cat (tmp,adr->mailbox,NIL);
|
||||
sprintf (tmp + strlen (tmp),"@%s>",adr->host);
|
||||
#else /* old code with A-D-L support */
|
||||
rfc822_address (tmp,adr);
|
||||
strcat (tmp,">");
|
||||
#endif
|
||||
/* want notifications */
|
||||
if (ESMTP.ok && ESMTP.dsn.ok && ESMTP.dsn.want) {
|
||||
/* yes, start with prefix */
|
||||
strcat (tmp," NOTIFY=");
|
||||
s = tmp + strlen (tmp);
|
||||
if (ESMTP.dsn.notify.failure) strcat (s,"FAILURE,");
|
||||
if (ESMTP.dsn.notify.delay) strcat (s,"DELAY,");
|
||||
if (ESMTP.dsn.notify.success) strcat (s,"SUCCESS,");
|
||||
/* tie off last comma */
|
||||
if (*s) s[strlen (s) - 1] = '\0';
|
||||
else strcat (tmp,"NEVER");
|
||||
if (adr->orcpt.addr) {
|
||||
sprintf (orcpt,"%.498s;%.498s",
|
||||
adr->orcpt.type ? adr->orcpt.type : "rfc822",
|
||||
adr->orcpt.addr);
|
||||
sprintf (tmp + strlen (tmp)," ORCPT=%.500s",orcpt);
|
||||
}
|
||||
}
|
||||
switch (smtp_send (stream,"RCPT",tmp)) {
|
||||
case SMTPOK: /* looks good */
|
||||
break;
|
||||
case SMTPUNAVAIL: /* mailbox unavailable? */
|
||||
case SMTPWANTAUTH: /* wants authentication? */
|
||||
case SMTPWANTAUTH2:
|
||||
if (ESMTP.auth) return T;
|
||||
default: /* other failure */
|
||||
*error = T; /* note that an error occurred */
|
||||
adr->error = cpystr (stream->reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
adr = adr->next; /* do any subsequent recipients */
|
||||
}
|
||||
return NIL; /* no retry called for */
|
||||
}
|
||||
|
||||
/* Simple Mail Transfer Protocol send command
|
||||
* Accepts: SEND stream
|
||||
* text
|
||||
* Returns: reply code
|
||||
*/
|
||||
|
||||
long smtp_send (SENDSTREAM *stream,char *command,char *args)
|
||||
{
|
||||
long ret;
|
||||
char *s = (char *) fs_get (strlen (command) + (args ? strlen (args) + 1 : 0)
|
||||
+ 3);
|
||||
/* build the complete command */
|
||||
if (args) sprintf (s,"%s %s",command,args);
|
||||
else strcpy (s,command);
|
||||
if (stream->debug) mail_dlog (s,stream->sensitive);
|
||||
strcat (s,"\015\012");
|
||||
/* send the command */
|
||||
if (stream->netstream && net_soutr (stream->netstream,s)) {
|
||||
do stream->replycode = smtp_reply (stream);
|
||||
while ((stream->replycode < 100) || (stream->reply[3] == '-'));
|
||||
ret = stream->replycode;
|
||||
}
|
||||
else ret = smtp_fake (stream,"SMTP connection broken (command)");
|
||||
fs_give ((void **) &s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Simple Mail Transfer Protocol get reply
|
||||
* Accepts: SMTP stream
|
||||
* Returns: reply code
|
||||
*/
|
||||
|
||||
long smtp_reply (SENDSTREAM *stream)
|
||||
{
|
||||
smtpverbose_t pv = (smtpverbose_t) mail_parameters (NIL,GET_SMTPVERBOSE,NIL);
|
||||
long reply;
|
||||
/* flush old reply */
|
||||
if (stream->reply) fs_give ((void **) &stream->reply);
|
||||
/* get reply */
|
||||
if (stream->netstream && (stream->reply = net_getline (stream->netstream))) {
|
||||
if (stream->debug) mm_dlog (stream->reply);
|
||||
/* return response code */
|
||||
reply = atol (stream->reply);
|
||||
if (pv && (reply < 100)) (*pv) (stream->reply);
|
||||
}
|
||||
else reply = smtp_fake (stream,"SMTP connection broken (reply)");
|
||||
return reply;
|
||||
}
|
||||
|
||||
/* Simple Mail Transfer Protocol send EHLO
|
||||
* Accepts: SMTP stream
|
||||
* host name to use in EHLO
|
||||
* NETMBX structure
|
||||
* Returns: reply code
|
||||
*/
|
||||
|
||||
long smtp_ehlo (SENDSTREAM *stream,char *host,NETMBX *mb)
|
||||
{
|
||||
unsigned long i,j;
|
||||
long flags = (mb->secflag ? AU_SECURE : NIL) |
|
||||
(mb->authuser[0] ? AU_AUTHUSER : NIL);
|
||||
char *s,*t,*r,tmp[MAILTMPLEN];
|
||||
/* clear ESMTP data */
|
||||
memset (&ESMTP,0,sizeof (ESMTP));
|
||||
if (mb->loser) return 500; /* never do EHLO if a loser */
|
||||
sprintf (tmp,"EHLO %s",host); /* build the complete command */
|
||||
if (stream->debug) mm_dlog (tmp);
|
||||
strcat (tmp,"\015\012");
|
||||
/* send the command */
|
||||
if (!net_soutr (stream->netstream,tmp))
|
||||
return smtp_fake (stream,"SMTP connection broken (EHLO)");
|
||||
/* got an OK reply? */
|
||||
do if ((i = smtp_reply (stream)) == SMTPOK) {
|
||||
/* hack for AUTH= */
|
||||
if (stream->reply[4] && stream->reply[5] && stream->reply[6] &&
|
||||
stream->reply[7] && (stream->reply[8] == '=')) stream->reply[8] = ' ';
|
||||
/* get option code */
|
||||
if (!(s = strtok_r (stream->reply+4," ",&r)));
|
||||
/* have option, does it have a value */
|
||||
else if ((t = strtok_r (NIL," ",&r)) && *t) {
|
||||
/* EHLO options which take arguments */
|
||||
if (!compare_cstring (s,"SIZE")) {
|
||||
if (isdigit (*t)) ESMTP.size.limit = strtoul (t,&t,10);
|
||||
ESMTP.size.ok = T;
|
||||
}
|
||||
else if (!compare_cstring (s,"DELIVERBY")) {
|
||||
if (isdigit (*t)) ESMTP.deliverby.minby = strtoul (t,&t,10);
|
||||
ESMTP.deliverby.ok = T;
|
||||
}
|
||||
else if (!compare_cstring (s,"ATRN")) {
|
||||
ESMTP.atrn.domains = cpystr (t);
|
||||
ESMTP.atrn.ok = T;
|
||||
}
|
||||
else if (!compare_cstring (s,"AUTH"))
|
||||
do if ((j = mail_lookup_auth_name (t,flags)) &&
|
||||
(--j < MAXAUTHENTICATORS)) ESMTP.auth |= (1 << j);
|
||||
while ((t = strtok_r (NIL," ",&r)) && *t);
|
||||
}
|
||||
/* EHLO options which do not take arguments */
|
||||
else if (!compare_cstring (s,"SIZE")) ESMTP.size.ok = T;
|
||||
else if (!compare_cstring (s,"8BITMIME")) ESMTP.eightbit.ok = T;
|
||||
else if (!compare_cstring (s,"DSN")) ESMTP.dsn.ok = T;
|
||||
else if (!compare_cstring (s,"ATRN")) ESMTP.atrn.ok = T;
|
||||
else if (!compare_cstring (s,"SEND")) ESMTP.service.send = T;
|
||||
else if (!compare_cstring (s,"SOML")) ESMTP.service.soml = T;
|
||||
else if (!compare_cstring (s,"SAML")) ESMTP.service.saml = T;
|
||||
else if (!compare_cstring (s,"EXPN")) ESMTP.service.expn = T;
|
||||
else if (!compare_cstring (s,"HELP")) ESMTP.service.help = T;
|
||||
else if (!compare_cstring (s,"TURN")) ESMTP.service.turn = T;
|
||||
else if (!compare_cstring (s,"ETRN")) ESMTP.service.etrn = T;
|
||||
else if (!compare_cstring (s,"STARTTLS")) ESMTP.service.starttls = T;
|
||||
else if (!compare_cstring (s,"RELAY")) ESMTP.service.relay = T;
|
||||
else if (!compare_cstring (s,"PIPELINING")) ESMTP.service.pipe = T;
|
||||
else if (!compare_cstring (s,"ENHANCEDSTATUSCODES"))
|
||||
ESMTP.service.ensc = T;
|
||||
else if (!compare_cstring (s,"BINARYMIME")) ESMTP.service.bmime = T;
|
||||
else if (!compare_cstring (s,"CHUNKING")) ESMTP.service.chunk = T;
|
||||
}
|
||||
while ((i < 100) || (stream->reply[3] == '-'));
|
||||
/* disable LOGIN if PLAIN also advertised */
|
||||
if ((j = mail_lookup_auth_name ("PLAIN",NIL)) && (--j < MAXAUTHENTICATORS) &&
|
||||
(ESMTP.auth & (1 << j)) &&
|
||||
(j = mail_lookup_auth_name ("LOGIN",NIL)) && (--j < MAXAUTHENTICATORS))
|
||||
ESMTP.auth &= ~(1 << j);
|
||||
return i; /* return the response code */
|
||||
}
|
||||
|
||||
/* Simple Mail Transfer Protocol set fake error and abort
|
||||
* Accepts: SMTP stream
|
||||
* error text
|
||||
* Returns: SMTPSOFTFATAL, always
|
||||
*/
|
||||
|
||||
long smtp_fake (SENDSTREAM *stream,char *text)
|
||||
{
|
||||
if (stream->netstream) { /* close net connection if still open */
|
||||
net_close (stream->netstream);
|
||||
stream->netstream = NIL;
|
||||
}
|
||||
/* set last error */
|
||||
return smtp_seterror (stream,SMTPSOFTFATAL,text);
|
||||
}
|
||||
|
||||
|
||||
/* Simple Mail Transfer Protocol set error
|
||||
* Accepts: SMTP stream
|
||||
* SMTP error code
|
||||
* error text
|
||||
* Returns: error code
|
||||
*/
|
||||
|
||||
static long smtp_seterror (SENDSTREAM *stream,long code,char *text)
|
||||
{
|
||||
/* flush any old reply */
|
||||
if (stream->reply ) fs_give ((void **) &stream->reply);
|
||||
/* set up pseudo-reply string */
|
||||
stream->reply = (char *) fs_get (20+strlen (text));
|
||||
sprintf (stream->reply,"%ld %s",code,text);
|
||||
return code; /* return error code */
|
||||
}
|
||||
|
||||
|
||||
/* Simple Mail Transfer Protocol filter mail
|
||||
* Accepts: stream
|
||||
* string
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long smtp_soutr (void *stream,char *s)
|
||||
{
|
||||
char c,*t;
|
||||
/* "." on first line */
|
||||
if (s[0] == '.') net_sout (stream,".",1);
|
||||
/* find lines beginning with a "." */
|
||||
while (t = strstr (s,"\015\012.")) {
|
||||
c = *(t += 3); /* remember next character after "." */
|
||||
*t = '\0'; /* tie off string */
|
||||
/* output prefix */
|
||||
if (!net_sout (stream,s,t-s)) return NIL;
|
||||
*t = c; /* restore delimiter */
|
||||
s = t - 1; /* push pointer up to the "." */
|
||||
}
|
||||
/* output remainder of text */
|
||||
return *s ? net_soutr (stream,s) : T;
|
||||
}
|
||||
76
src/c-client/smtp.h
Normal file
76
src/c-client/smtp.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Simple Mail Transfer Protocol (SMTP) routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 27 July 1988
|
||||
* Last Edited: 15 August 2007
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the NationalInstitutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
/* Constants (should be in smtp.c) */
|
||||
|
||||
#define SMTPTCPPORT (long) 25 /* assigned TCP contact port */
|
||||
#define SUBMITTCPPORT (long) 587/* assigned TCP contact port */
|
||||
|
||||
|
||||
/* SMTP open options
|
||||
* For compatibility with the past, SOP_DEBUG must always be 1.
|
||||
*/
|
||||
|
||||
#define SOP_DEBUG (long) 1 /* debug protocol negotiations */
|
||||
#define SOP_DSN (long) 2 /* DSN requested */
|
||||
/* DSN notification, none set mean NEVER */
|
||||
#define SOP_DSN_NOTIFY_FAILURE (long) 4
|
||||
#define SOP_DSN_NOTIFY_DELAY (long) 8
|
||||
#define SOP_DSN_NOTIFY_SUCCESS (long) 16
|
||||
/* DSN return full msg vs. header */
|
||||
|
||||
#define SOP_DSN_RETURN_FULL (long) 32
|
||||
#define SOP_8BITMIME (long) 64 /* 8-bit MIME requested */
|
||||
#define SOP_SECURE (long) 256 /* don't do non-secure authentication */
|
||||
#define SOP_TRYSSL (long) 512 /* try SSL first */
|
||||
#define SOP_TRYALT SOP_TRYSSL /* old name */
|
||||
/* reserved for application use */
|
||||
#define SOP_RESERVED (unsigned long) 0xff000000
|
||||
|
||||
|
||||
/* Compatibility support names */
|
||||
|
||||
#define smtp_open(hostlist,options) \
|
||||
smtp_open_full (NIL,hostlist,"smtp",NIL,options)
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void *smtp_parameters (long function,void *value);
|
||||
SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service,
|
||||
unsigned long port,long options);
|
||||
SENDSTREAM *smtp_close (SENDSTREAM *stream);
|
||||
long smtp_mail (SENDSTREAM *stream,char *type,ENVELOPE *msg,BODY *body);
|
||||
long smtp_verbose (SENDSTREAM *stream);
|
||||
70
src/c-client/sslio.h
Normal file
70
src/c-client/sslio.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: SSL routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 7 February 2001
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* SSL driver */
|
||||
|
||||
struct ssl_driver { /* must parallel NETDRIVER in mail.h */
|
||||
SSLSTREAM *(*open) (char *host,char *service,unsigned long port);
|
||||
SSLSTREAM *(*aopen) (NETMBX *mb,char *service,char *usrbuf);
|
||||
char *(*getline) (SSLSTREAM *stream);
|
||||
long (*getbuffer) (SSLSTREAM *stream,unsigned long size,char *buffer);
|
||||
long (*soutr) (SSLSTREAM *stream,char *string);
|
||||
long (*sout) (SSLSTREAM *stream,char *string,unsigned long size);
|
||||
void (*close) (SSLSTREAM *stream);
|
||||
char *(*host) (SSLSTREAM *stream);
|
||||
char *(*remotehost) (SSLSTREAM *stream);
|
||||
unsigned long (*port) (SSLSTREAM *stream);
|
||||
char *(*localhost) (SSLSTREAM *stream);
|
||||
};
|
||||
|
||||
|
||||
/* SSL stdio stream */
|
||||
|
||||
typedef struct ssl_stdiostream {
|
||||
SSLSTREAM *sslstream; /* SSL stream */
|
||||
int octr; /* output counter */
|
||||
char *optr; /* output pointer */
|
||||
char obuf[SSLBUFLEN]; /* output buffer */
|
||||
} SSLSTDIOSTREAM;
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
SSLSTREAM *ssl_open (char *host,char *service,unsigned long port);
|
||||
SSLSTREAM *ssl_aopen (NETMBX *mb,char *service,char *usrbuf);
|
||||
char *ssl_getline (SSLSTREAM *stream);
|
||||
long ssl_getbuffer (SSLSTREAM *stream,unsigned long size,char *buffer);
|
||||
long ssl_getdata (SSLSTREAM *stream);
|
||||
long ssl_soutr (SSLSTREAM *stream,char *string);
|
||||
long ssl_sout (SSLSTREAM *stream,char *string,unsigned long size);
|
||||
void ssl_close (SSLSTREAM *stream);
|
||||
char *ssl_host (SSLSTREAM *stream);
|
||||
char *ssl_remotehost (SSLSTREAM *stream);
|
||||
unsigned long ssl_port (SSLSTREAM *stream);
|
||||
char *ssl_localhost (SSLSTREAM *stream);
|
||||
long ssl_server_input_wait (long seconds);
|
||||
59
src/c-client/tcp.h
Normal file
59
src/c-client/tcp.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: TCP/IP routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 31 January 2007
|
||||
*/
|
||||
|
||||
|
||||
/* Dummy definition overridden by TCP routines */
|
||||
|
||||
#ifndef TCPSTREAM
|
||||
#define TCPSTREAM void
|
||||
#endif
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void *tcp_parameters (long function,void *value);
|
||||
TCPSTREAM *tcp_open (char *host,char *service,unsigned long port);
|
||||
TCPSTREAM *tcp_aopen (NETMBX *mb,char *service,char *usrbuf);
|
||||
char *tcp_getline (TCPSTREAM *stream);
|
||||
long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *buffer);
|
||||
long tcp_getdata (TCPSTREAM *stream);
|
||||
long tcp_soutr (TCPSTREAM *stream,char *string);
|
||||
long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size);
|
||||
void tcp_close (TCPSTREAM *stream);
|
||||
char *tcp_host (TCPSTREAM *stream);
|
||||
char *tcp_remotehost (TCPSTREAM *stream);
|
||||
unsigned long tcp_port (TCPSTREAM *stream);
|
||||
char *tcp_localhost (TCPSTREAM *stream);
|
||||
char *tcp_clientaddr (void);
|
||||
char *tcp_clienthost (void);
|
||||
long tcp_clientport (void);
|
||||
char *tcp_serveraddr (void);
|
||||
char *tcp_serverhost (void);
|
||||
long tcp_serverport (void);
|
||||
char *tcp_canonical (char *name);
|
||||
long tcp_isclienthost (char *host);
|
||||
2554
src/c-client/utf8.c
Normal file
2554
src/c-client/utf8.c
Normal file
File diff suppressed because it is too large
Load Diff
584
src/c-client/utf8.h
Normal file
584
src/c-client/utf8.h
Normal file
@@ -0,0 +1,584 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: UTF-8 routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 11 June 1997
|
||||
* Last Edited: 17 January 2008
|
||||
*/
|
||||
|
||||
/* UTF-8 size and conversion routines from UCS-2 values (thus in the BMP).
|
||||
* Don't use these if UTF-16 data (surrogate pairs) are an issue.
|
||||
* For UCS-4 values, use the utf8_size() and utf8_put() functions.
|
||||
*/
|
||||
|
||||
#define UTF8_SIZE_BMP(c) ((c & 0xff80) ? ((c & 0xf800) ? 3 : 2) : 1)
|
||||
|
||||
#define UTF8_PUT_BMP(b,c) { \
|
||||
if (c & 0xff80) { /* non-ASCII? */ \
|
||||
if (c & 0xf800) { /* three byte code */ \
|
||||
*b++ = 0xe0 | (c >> 12); \
|
||||
*b++ = 0x80 | ((c >> 6) & 0x3f); \
|
||||
} \
|
||||
else *b++ = 0xc0 | ((c >> 6) & 0x3f); \
|
||||
*b++ = 0x80 | (c & 0x3f); \
|
||||
} \
|
||||
else *b++ = c; \
|
||||
}
|
||||
|
||||
/* utf8_text() flag values */
|
||||
|
||||
#define U8T_CASECANON 2 /* canonicalize case */
|
||||
#define U8T_DECOMPOSE 4 /* decompose */
|
||||
/* full canonicalization */
|
||||
#define U8T_CANONICAL (U8T_CASECANON | U8T_DECOMPOSE)
|
||||
|
||||
|
||||
/* utf8_get() return values */
|
||||
|
||||
/* 0x0000 - 0xffff BMP plane */
|
||||
#define U8GM_NONBMP 0xffff0000 /* mask for non-BMP values */
|
||||
/* 0x10000 - 0x10ffff extended planes */
|
||||
/* 0x110000 - 0x7ffffff non-Unicode */
|
||||
#define U8G_ERROR 0x80000000 /* error flag */
|
||||
#define U8G_BADCONT U8G_ERROR+1 /* continuation when not in progress */
|
||||
#define U8G_INCMPLT U8G_ERROR+2 /* incomplete UTF-8 character */
|
||||
#define U8G_NOTUTF8 U8G_ERROR+3 /* not a valid UTF-8 octet */
|
||||
#define U8G_ENDSTRG U8G_ERROR+4 /* end of string */
|
||||
#define U8G_ENDSTRI U8G_ERROR+5 /* end of string w/ incomplete UTF-8 char */
|
||||
#define U8G_SURROGA U8G_ERROR+6 /* surrogate codepoint */
|
||||
#define U8G_NOTUNIC U8G_ERROR+7 /* non-Unicode codepoint */
|
||||
|
||||
|
||||
/* ucs4_width() return values */
|
||||
|
||||
#define U4W_ERROR 0x80000000 /* error flags */
|
||||
#define U4W_NOTUNCD U4W_ERROR+1 /* not a Unicode char */
|
||||
#define U4W_PRIVATE U4W_ERROR+2 /* private-space plane */
|
||||
#define U4W_SSPCHAR U4W_ERROR+3 /* Supplementary Special-purpose Plane */
|
||||
#define U4W_UNASSGN U4W_ERROR+4 /* unassigned space plane */
|
||||
#define U4W_CONTROL U4W_ERROR+5 /* C0/C1 control */
|
||||
#define U4W_CTLSRGT U4W_CONTROL /* in case legacy code references this */
|
||||
|
||||
/* ISO-2022 engine states */
|
||||
|
||||
#define I2S_CHAR 0 /* character */
|
||||
#define I2S_ESC 1 /* previous character was ESC */
|
||||
#define I2S_MUL 2 /* previous character was multi-byte code */
|
||||
#define I2S_INT 3 /* previous character was intermediate */
|
||||
|
||||
|
||||
/* ISO-2022 Gn selections */
|
||||
|
||||
#define I2C_G0 0 /* G0 */
|
||||
#define I2C_G1 1 /* G1 */
|
||||
#define I2C_G2 2 /* G2 */
|
||||
#define I2C_G3 3 /* G3 */
|
||||
#define I2C_SG2 (2 << 2) /* single shift G2 */
|
||||
#define I2C_SG3 (3 << 2) /* single shift G2 */
|
||||
|
||||
|
||||
/* ISO-2022 octet definitions */
|
||||
|
||||
#define I2C_ESC 0x1b /* ESCape */
|
||||
|
||||
/* Intermediate character */
|
||||
#define I2C_STRUCTURE 0x20 /* announce code structure */
|
||||
#define I2C_C0 0x21 /* C0 */
|
||||
#define I2C_C1 0x22 /* C1 */
|
||||
#define I2C_CONTROL 0x23 /* single control function */
|
||||
#define I2C_MULTI 0x24 /* multi-byte character set */
|
||||
#define I2C_OTHER 0x25 /* other coding system */
|
||||
#define I2C_REVISED 0x26 /* revised registration */
|
||||
#define I2C_G0_94 0x28 /* G0 94-character set */
|
||||
#define I2C_G1_94 0x29 /* G1 94-character set */
|
||||
#define I2C_G2_94 0x2A /* G2 94-character set */
|
||||
#define I2C_G3_94 0x2B /* G3 94-character set */
|
||||
#define I2C_G0_96 0x2C /* (not in ISO-2022) G0 96-character set */
|
||||
#define I2C_G1_96 0x2D /* G1 96-character set */
|
||||
#define I2C_G2_96 0x2E /* G2 96-character set */
|
||||
#define I2C_G3_96 0x2F /* G3 96-character set */
|
||||
|
||||
/* Locking shifts */
|
||||
#define I2C_SI 0x0f /* lock shift to G0 (Shift In) */
|
||||
#define I2C_SO 0x0e /* lock shift to G1 (Shift Out) */
|
||||
/* prefixed by ESC */
|
||||
#define I2C_LS2 0x6e /* lock shift to G2 */
|
||||
#define I2C_LS3 0x6f /* lock shift to G3 */
|
||||
#define I2C_LS1R 0x7e /* lock shift GR to G1 */
|
||||
#define I2C_LS2R 0x7d /* lock shift GR to G2 */
|
||||
#define I2C_LS3R 0x7c /* lock shift GR to G3 */
|
||||
|
||||
/* Single shifts */
|
||||
#define I2C_SS2_ALT 0x8e /* single shift to G2 (SS2) */
|
||||
#define I2C_SS3_ALT 0x8f /* single shift to G3 (SS3) */
|
||||
#define I2C_SS2_ALT_7 0x19 /* single shift to G2 (SS2) */
|
||||
#define I2C_SS3_ALT_7 0x1d /* single shift to G3 (SS3) */
|
||||
/* prefixed by ESC */
|
||||
#define I2C_SS2 0x4e /* single shift to G2 (SS2) */
|
||||
#define I2C_SS3 0x4f /* single shift to G3 (SS3) */
|
||||
|
||||
/* 94 character sets */
|
||||
|
||||
/* 4/0 ISO 646 IRV */
|
||||
#define I2CS_94_BRITISH 0x41 /* 4/1 ISO 646 British */
|
||||
#define I2CS_94_ASCII 0x42 /* 4/2 ISO 646 USA (ASCII) */
|
||||
/* 4/3 NATS Finland/Sweden (primary) */
|
||||
/* 4/4 NATS Finland/Sweden (secondary) */
|
||||
/* 4/5 NATS Denmark/Norway (primary) */
|
||||
/* 4/6 NATS Denmark/Norway (secondary) */
|
||||
/* 4/7 ISO 646 Swedish SEN 850200 */
|
||||
/* 4/8 ISO 646 Swedish names */
|
||||
#define I2CS_94_JIS_BUGROM 0x48 /* 4/8 some buggy software does this */
|
||||
#define I2CS_94_JIS_KANA 0x49 /* 4/9 JIS X 0201-1976 right half */
|
||||
#define I2CS_94_JIS_ROMAN 0x4a /* 4/a JIS X 0201-1976 left half */
|
||||
/* 4/b ISO 646 German */
|
||||
/* 4/c ISO 646 Portuguese (Olivetti) */
|
||||
/* 4/d ISO 6438 African */
|
||||
/* 4/e ISO 5427 Cyrillic (Honeywell-Bull) */
|
||||
/* 4/f DIN 31624 extended bibliography */
|
||||
/* 5/0 ISO 5426-1980 Bibliography */
|
||||
/* 5/1 ISO 5427-1981 Cyrillic*/
|
||||
/* 5/2 ISO 646 French (withdrawn) */
|
||||
/* 5/3 ISO 5428-1980 Greek bibliography */
|
||||
/* 5/4 GB 1988-80 Chinese */
|
||||
/* 5/5 Latin-Greek (Honeywell-Bull) */
|
||||
/* 5/6 UK Viewdata/Teletext */
|
||||
/* 5/7 INIS (IRV subset) */
|
||||
/* 5/8 ISO 5428 Greek Bibliography */
|
||||
/* 5/9 ISO 646 Italian (Olivetti) */
|
||||
/* 5/a ISO 646 Spanish (Olivetti) */
|
||||
/* 5/b Greek (Olivetti) */
|
||||
/* 5/c Latin-Greek (Olivetti) */
|
||||
/* 5/d INIS non-standard extension */
|
||||
/* 5/e INIS Cyrillic extension */
|
||||
/* 5/f Arabic CODAR-U IERA */
|
||||
/* 6/0 ISO 646 Norwegian */
|
||||
/* 6/1 Norwegian version 2 (withdrawn) */
|
||||
/* 6/2 Videotex supplementary */
|
||||
/* 6/3 Videotex supplementary #2 */
|
||||
/* 6/4 Videotex supplementary #3 */
|
||||
/* 6/5 APL */
|
||||
/* 6/6 ISO 646 French */
|
||||
/* 6/7 ISO 646 Portuguese (IBM) */
|
||||
/* 6/8 ISO 646 Spanish (IBM) */
|
||||
/* 6/9 ISO 646 Hungarian */
|
||||
/* 6/a Greek ELOT (withdrawn) */
|
||||
/* 6/b ISO 9036 Arabic 7-bit */
|
||||
/* 6/c ISO 646 IRV supplementary set */
|
||||
/* 6/d JIS C6229-1984 OCR-A */
|
||||
/* 6/e JIS C6229-1984 OCR-B */
|
||||
/* 6/f JIS C6229-1984 OCR-B additional */
|
||||
/* 7/0 JIS C6229-1984 hand-printed */
|
||||
/* 7/1 JIS C6229-1984 additional hand-printd */
|
||||
/* 7/2 JIS C6229-1984 katakana hand-printed */
|
||||
/* 7/3 E13B Japanese graphic */
|
||||
/* 7/4 Supplementary Videotex (withdrawn) */
|
||||
/* 7/5 Teletex primary CCITT T.61 */
|
||||
/* 7/6 Teletex secondary CCITT T.61 */
|
||||
/* 7/7 CSA Z 243.4-1985 Alternate primary #1 */
|
||||
/* 7/8 CSA Z 243.4-1985 Alternate primary #2 */
|
||||
/* 7/9 Mosaic CCITT T.101 */
|
||||
/* 7/a Serbocroatian/Slovenian Latin */
|
||||
/* 7/b Serbocroatian Cyrillic */
|
||||
/* 7/c Supplementary CCITT T.101 */
|
||||
/* 7/d Macedonian Cyrillic */
|
||||
|
||||
/* 94 character sets - second intermediate byte */
|
||||
|
||||
/* 4/0 Greek primary CCITT */
|
||||
/* 4/1 Cuba */
|
||||
/* 4/2 ISO/IEC 646 invariant */
|
||||
/* 4/3 Irish Gaelic 7-bit */
|
||||
/* 4/4 Turkmen */
|
||||
|
||||
|
||||
/* 94x94 character sets */
|
||||
|
||||
#define I2CS_94x94_JIS_OLD 0x40 /* 4/0 JIS X 0208-1978 */
|
||||
#define I2CS_94x94_GB 0x41 /* 4/1 GB 2312 */
|
||||
#define I2CS_94x94_JIS_NEW 0x42 /* 4/2 JIS X 0208-1983 */
|
||||
#define I2CS_94x94_KSC 0x43 /* 4/3 KSC 5601 */
|
||||
#define I2CS_94x94_JIS_EXT 0x44 /* 4/4 JIS X 0212-1990 */
|
||||
/* 4/5 CCITT Chinese */
|
||||
/* 4/6 Blisssymbol Graphic */
|
||||
#define I2CS_94x94_CNS1 0x47 /* 4/7 CNS 11643 plane 1 */
|
||||
#define I2CS_94x94_CNS2 0x48 /* 4/8 CNS 11643 plane 2 */
|
||||
#define I2CS_94x94_CNS3 0x49 /* 4/9 CNS 11643 plane 3 */
|
||||
#define I2CS_94x94_CNS4 0x4a /* 4/a CNS 11643 plane 4 */
|
||||
#define I2CS_94x94_CNS5 0x4b /* 4/b CNS 11643 plane 5 */
|
||||
#define I2CS_94x94_CNS6 0x4c /* 4/c CNS 11643 plane 6 */
|
||||
#define I2CS_94x94_CNS7 0x4d /* 4/d CNS 11643 plane 7 */
|
||||
/* 4/e DPRK (North Korea) KGCII */
|
||||
/* 4/f JGCII plane 1 */
|
||||
/* 5/0 JGCII plane 2 */
|
||||
|
||||
/* 96 character sets */
|
||||
|
||||
#define I2CS_96_ISO8859_1 0x41 /* 4/1 Latin-1 (Western Europe) */
|
||||
#define I2CS_96_ISO8859_2 0x42 /* 4/2 Latin-2 (Czech, Slovak) */
|
||||
#define I2CS_96_ISO8859_3 0x43 /* 4/3 Latin-3 (Dutch, Turkish) */
|
||||
#define I2CS_96_ISO8859_4 0x44 /* 4/4 Latin-4 (Scandinavian) */
|
||||
/* 4/5 CSA Z 243.4-1985 */
|
||||
#define I2CS_96_ISO8859_7 0x46 /* 4/6 Greek */
|
||||
#define I2CS_96_ISO8859_6 0x47 /* 4/7 Arabic */
|
||||
#define I2CS_96_ISO8859_8 0x48 /* 4/8 Hebrew */
|
||||
/* 4/9 Czechoslovak CSN 369103 */
|
||||
/* 4/a Supplementary Latin and non-alpha */
|
||||
/* 4/b Technical */
|
||||
#define I2CS_96_ISO8859_5 0x4c /* 4/c Cyrillic */
|
||||
#define I2CS_96_ISO8859_9 0x4d /* 4/d Latin-5 (Finnish, Portuguese) */
|
||||
/* 4/e ISO 6937-2 residual */
|
||||
/* 4/f Basic Cyrillic */
|
||||
/* 5/0 Supplementary Latin 1, 2 and 5 */
|
||||
/* 5/1 Basic Box */
|
||||
/* 5/2 Supplementary ISO/IEC 6937 : 1992 */
|
||||
/* 5/3 CCITT Hebrew supplementary */
|
||||
#define I2CS_96_TIS620 0x54 /* 5/4 TIS 620 */
|
||||
/* 5/5 Arabic/French/German */
|
||||
#define I2CS_96_ISO8859_10 0x56 /* 5/6 Latin-6 (Northern Europe) */
|
||||
/* 5/7 ??? */
|
||||
/* 5/8 Sami (Lappish) supplementary */
|
||||
#define I2CS_96_ISO8859_13 0x59 /* 5/9 Latin-7 (Baltic) */
|
||||
#define I2CS_96_VSCII 0x5a /* 5/a Vietnamese */
|
||||
/* 5/b Technical #1 IEC 1289 */
|
||||
#define I2CS_96_ISO8859_14 0x5c /* 5/c Latin-8 (Celtic) */
|
||||
/* 5/d Sami supplementary Latin */
|
||||
/* 5/e Latin/Hebrew */
|
||||
/* 5/f Celtic supplementary Latin */
|
||||
/* 6/0 Uralic supplementary Cyrillic */
|
||||
/* 6/1 Volgaic supplementary Cyrillic */
|
||||
#define I2CS_96_ISO8859_15 0x62 /* 6/2 Latin-9 (Euro) */
|
||||
/* 6/3 Latin-1 with Euro */
|
||||
/* 6/4 Latin-4 with Euro */
|
||||
/* 6/5 Latin-7 with Euro */
|
||||
#define I2CS_96_ISO8859_16 0x66 /* 6/6 Latin-10 (Balkan) */
|
||||
/* 6/7 Ogham */
|
||||
/* 6/8 Sami supplementary Latin #2 */
|
||||
/* 7/d Supplementary Mosaic for CCITT 101 */
|
||||
|
||||
/* 96x96 character sets */
|
||||
|
||||
/* Types of character sets */
|
||||
|
||||
#define I2CS_94 0x000 /* 94 character set */
|
||||
#define I2CS_96 0x100 /* 96 character set */
|
||||
#define I2CS_MUL 0x200 /* multi-byte */
|
||||
#define I2CS_94x94 (I2CS_MUL | I2CS_94)
|
||||
#define I2CS_96x96 (I2CS_MUL | I2CS_96)
|
||||
|
||||
|
||||
/* Character set identifiers stored in Gn */
|
||||
|
||||
#define I2CS_BRITISH (I2CS_94 | I2CS_94_BRITISH)
|
||||
#define I2CS_ASCII (I2CS_94 | I2CS_94_ASCII)
|
||||
#define I2CS_JIS_BUGROM (I2CS_94 | I2CS_94_JIS_BUGROM)
|
||||
#define I2CS_JIS_KANA (I2CS_94 | I2CS_94_JIS_KANA)
|
||||
#define I2CS_JIS_ROMAN (I2CS_94 | I2CS_94_JIS_ROMAN)
|
||||
#define I2CS_JIS_OLD (I2CS_94x94 | I2CS_94x94_JIS_OLD)
|
||||
#define I2CS_GB (I2CS_94x94 | I2CS_94x94_GB)
|
||||
#define I2CS_JIS_NEW (I2CS_94x94 | I2CS_94x94_JIS_NEW)
|
||||
#define I2CS_KSC (I2CS_94x94 | I2CS_94x94_KSC)
|
||||
#define I2CS_JIS_EXT (I2CS_94x94 | I2CS_94x94_JIS_EXT)
|
||||
#define I2CS_CNS1 (I2CS_94x94 | I2CS_94x94_CNS1)
|
||||
#define I2CS_CNS2 (I2CS_94x94 | I2CS_94x94_CNS2)
|
||||
#define I2CS_CNS3 (I2CS_94x94 | I2CS_94x94_CNS3)
|
||||
#define I2CS_CNS4 (I2CS_94x94 | I2CS_94x94_CNS4)
|
||||
#define I2CS_CNS5 (I2CS_94x94 | I2CS_94x94_CNS5)
|
||||
#define I2CS_CNS6 (I2CS_94x94 | I2CS_94x94_CNS6)
|
||||
#define I2CS_CNS7 (I2CS_94x94 | I2CS_94x94_CNS7)
|
||||
#define I2CS_ISO8859_1 (I2CS_96 | I2CS_96_ISO8859_1)
|
||||
#define I2CS_ISO8859_2 (I2CS_96 | I2CS_96_ISO8859_2)
|
||||
#define I2CS_ISO8859_3 (I2CS_96 | I2CS_96_ISO8859_3)
|
||||
#define I2CS_ISO8859_4 (I2CS_96 | I2CS_96_ISO8859_4)
|
||||
#define I2CS_ISO8859_7 (I2CS_96 | I2CS_96_ISO8859_7)
|
||||
#define I2CS_ISO8859_6 (I2CS_96 | I2CS_96_ISO8859_6)
|
||||
#define I2CS_ISO8859_8 (I2CS_96 | I2CS_96_ISO8859_8)
|
||||
#define I2CS_ISO8859_5 (I2CS_96 | I2CS_96_ISO8859_5)
|
||||
#define I2CS_ISO8859_9 (I2CS_96 | I2CS_96_ISO8859_9)
|
||||
#define I2CS_TIS620 (I2CS_96 | I2CS_96_TIS620)
|
||||
#define I2CS_ISO8859_10 (I2CS_96 | I2CS_96_ISO8859_10)
|
||||
#define I2CS_ISO8859_13 (I2CS_96 | I2CS_96_ISO8859_13)
|
||||
#define I2CS_VSCII (I2CS_96 | I2CS_96_VSCII)
|
||||
#define I2CS_ISO8859_14 (I2CS_96 | I2CS_96_ISO8859_14)
|
||||
#define I2CS_ISO8859_15 (I2CS_96 | I2CS_96_ISO8859_15)
|
||||
#define I2CS_ISO8859_16 (I2CS_96 | I2CS_96_ISO8859_16)
|
||||
|
||||
|
||||
/* Miscellaneous ISO 2022 definitions */
|
||||
|
||||
#define EUC_CS2 0x8e /* single shift CS2 */
|
||||
#define EUC_CS3 0x8f /* single shift CS3 */
|
||||
|
||||
#define BITS7 0x7f /* 7-bit value mask */
|
||||
#define BIT8 0x80 /* 8th bit mask */
|
||||
|
||||
/* The following saves us from having to have yet more charset tables */
|
||||
|
||||
/* Unicode codepoints */
|
||||
|
||||
#define UCS2_C0CONTROL 0x00 /* first C0 control */
|
||||
#define UCS2_C0CONTROLEND 0x1F /* last C0 control */
|
||||
#define UCS2_C1CONTROL 0x80 /* first C1 control */
|
||||
#define UCS2_C1CONTROLEND 0x9F /* last C1 control */
|
||||
|
||||
/* ISO 646 substituted Unicode codepoints */
|
||||
#define UCS2_POUNDSTERLING 0x00a3
|
||||
#define UCS2_YEN 0x00a5
|
||||
#define UCS2_OVERLINE 0x203e
|
||||
#define UCS2_EURO 0x20ac
|
||||
#define UCS2_KATAKANA 0xff61 /* first katakana codepoint */
|
||||
#define UCS2_BOM 0xfeff /* byte order mark */
|
||||
#define UCS2_BOGON 0xfffd /* replacement character */
|
||||
/* next two codepoints are not Unicode chars */
|
||||
#define UCS2_BOMCHECK 0xfffe /* used to check byte order with UCS2_BOM */
|
||||
#define UCS2_NOTCHAR 0xffff /* not a character */
|
||||
|
||||
#define UCS4_BMPBASE 0x0000 /* Basic Multilingual Plane */
|
||||
#define UCS4_SMPBASE 0x10000 /* Supplementary Multilinugual Plane */
|
||||
#define UCS4_SIPBASE 0x20000 /* Supplementary Ideographic Plane */
|
||||
/* EastAsianWidth says plane 3 is wide */
|
||||
#define UCS4_UNABASE 0x40000 /* unassigned space */
|
||||
#define UCS4_SSPBASE 0xe0000 /* Supplementary Special-purpose Plane */
|
||||
#define UCS4_PVTBASE 0xf0000 /* private-space (two planes) */
|
||||
#define UCS4_MAXUNICODE 0x10ffff/* highest Unicode codepoint */
|
||||
|
||||
#define UTF16_BASE 0x10000 /* base of codepoints needing surrogates */
|
||||
#define UTF16_SHIFT 10 /* surrogate shift */
|
||||
#define UTF16_MASK 0x3ff /* surrogate mask */
|
||||
#define UTF16_SURR 0xd800 /* UTF-16 surrogate area */
|
||||
#define UTF16_SURRH 0xd800 /* UTF-16 first high surrogate */
|
||||
#define UTF16_SURRHEND 0xdbff /* UTF-16 last high surrogate */
|
||||
#define UTF16_SURRL 0xdc00 /* UTF-16 first low surrogate */
|
||||
#define UTF16_SURRLEND 0xdfff /* UTF-16 last low surrogate */
|
||||
#define UTF16_MAXSURR 0xdfff /* end of UTF-16 surrogates */
|
||||
|
||||
|
||||
/* UBOGON is used to represent a codepoint in a character set which does not
|
||||
* map to Unicode. It is also used for mapping failures, e.g. incomplete
|
||||
* shift sequences. This name has the same text width as 0x????, for
|
||||
* convenience in the mapping tables.
|
||||
*
|
||||
* NOCHAR is used to represent a codepoint in Unicode which does not map to
|
||||
* the target character set in a reverse mapping table. This name has the
|
||||
* same text width as 0x???? in case we ever add static reverse mapping tables.
|
||||
*/
|
||||
|
||||
#define UBOGON UCS2_BOGON
|
||||
#define NOCHAR UCS2_NOTCHAR
|
||||
|
||||
/* Codepoints in non-Unicode character sets */
|
||||
|
||||
/* Codepoints in ISO 646 character sets */
|
||||
|
||||
/* British ASCII codepoints */
|
||||
|
||||
#define BRITISH_POUNDSTERLING 0x23
|
||||
|
||||
/* JIS Roman codepoints */
|
||||
|
||||
#define JISROMAN_YEN 0x5c
|
||||
#define JISROMAN_OVERLINE 0x7e
|
||||
|
||||
|
||||
/* Hankaku katakana codepoints & parameters
|
||||
*
|
||||
* In earlier versions, MAX_KANA_7 and MAX_KANA_8 were the maximum codepoint
|
||||
* values. Although this made sense, it was confusing with the "max ku" and
|
||||
* "max ten" values used in the double-byte tables; there are 1-origin, but
|
||||
* the calculated values used for "ku" and "ten" are 0-origin (derived by
|
||||
* substracting the "base"). What this all meant is that for double byte
|
||||
* characters the limit test is of the form (value < max_ku), but for single
|
||||
* byte characters (which used the same cell to hold the max ku) the limit
|
||||
* test was (value <= max_ku).
|
||||
*
|
||||
* By making MAX_KANA_[78] be maximum+1, the same (value < max_ku) limit test
|
||||
* is used throughout. - 6/15/2006
|
||||
*/
|
||||
|
||||
#define MIN_KANA_7 0x21
|
||||
#define MAX_KANA_7 0x60 /* maximum value + 1 */
|
||||
#define KANA_7 (UCS2_KATAKANA - MIN_KANA_7)
|
||||
#define MIN_KANA_8 (MIN_KANA_7 | BIT8)
|
||||
#define MAX_KANA_8 (MAX_KANA_7 | BIT8)
|
||||
#define KANA_8 (UCS2_KATAKANA - MIN_KANA_8)
|
||||
|
||||
/* Charset scripts */
|
||||
|
||||
/* The term "script" is used here in a very loose sense, enough to make
|
||||
* purists cringe. Basically, the idea is to give the main program some
|
||||
* idea of how it should treat the characters of text in a charset with
|
||||
* respect to font, drawing routines, etc.
|
||||
*
|
||||
* In some cases, "script" is associated with a charset; in other cases,
|
||||
* it's more closely tied to a language.
|
||||
*/
|
||||
|
||||
#define SC_UNICODE 0x1 /* Unicode */
|
||||
#define SC_LATIN_1 0x10 /* Western Europe */
|
||||
#define SC_LATIN_2 0x20 /* Eastern Europe */
|
||||
#define SC_LATIN_3 0x40 /* Southern Europe */
|
||||
#define SC_LATIN_4 0x80 /* Northern Europe */
|
||||
#define SC_LATIN_5 0x100 /* Turkish */
|
||||
#define SC_LATIN_6 0x200 /* Nordic */
|
||||
#define SC_LATIN_7 0x400 /* Baltic */
|
||||
#define SC_LATIN_8 0x800 /* Celtic */
|
||||
#define SC_LATIN_9 0x1000 /* Euro */
|
||||
#define SC_LATIN_0 SC_LATIN_9 /* colloquial name for Latin-9 */
|
||||
#define SC_ARABIC 0x2000
|
||||
#define SC_CYRILLIC 0x4000
|
||||
#define SC_GREEK 0x8000
|
||||
#define SC_HEBREW 0x10000
|
||||
#define SC_THAI 0x20000
|
||||
#define SC_UKRANIAN 0x40000
|
||||
#define SC_LATIN_10 0x80000 /* Balkan */
|
||||
#define SC_VIETNAMESE 0x100000
|
||||
#define SC_CHINESE_SIMPLIFIED 0x1000000
|
||||
#define SC_CHINESE_TRADITIONAL 0x2000000
|
||||
#define SC_JAPANESE 0x4000000
|
||||
#define SC_KOREAN 0x8000000
|
||||
|
||||
|
||||
/* Script table */
|
||||
|
||||
typedef struct utf8_scent {
|
||||
char *name; /* script name */
|
||||
char *description; /* script description */
|
||||
unsigned long script; /* script bitmask */
|
||||
} SCRIPT;
|
||||
|
||||
/* Character set table support */
|
||||
|
||||
typedef struct utf8_csent {
|
||||
char *name; /* charset name */
|
||||
unsigned short type; /* type of charset */
|
||||
unsigned short flags; /* charset flags */
|
||||
void *tab; /* additional data */
|
||||
unsigned long script; /* script(s) implemented by this charset */
|
||||
char *preferred; /* preferred charset over this one */
|
||||
} CHARSET;
|
||||
|
||||
|
||||
struct utf8_eucparam {
|
||||
unsigned int base_ku : 8; /* base row */
|
||||
unsigned int base_ten : 8; /* base column */
|
||||
unsigned int max_ku : 8; /* maximum row */
|
||||
unsigned int max_ten : 8; /* maximum column */
|
||||
void *tab; /* conversion table */
|
||||
};
|
||||
|
||||
|
||||
/* Charset types */
|
||||
|
||||
#define CT_UNKNOWN 0 /* unknown 8-bit */
|
||||
#define CT_ASCII 1 /* 7-bit ASCII no table */
|
||||
#define CT_UCS2 2 /* 2 byte 16-bit Unicode no table */
|
||||
#define CT_UCS4 3 /* 4 byte 32-bit Unicode no table */
|
||||
#define CT_1BYTE0 10 /* 1 byte ISO 8859-1 no table */
|
||||
#define CT_1BYTE 11 /* 1 byte ASCII + table 0x80-0xff */
|
||||
#define CT_1BYTE8 12 /* 1 byte table 0x00 - 0xff */
|
||||
#define CT_EUC 100 /* 2 byte ASCII + utf8_eucparam base/CS2/CS3 */
|
||||
#define CT_DBYTE 101 /* 2 byte ASCII + utf8_eucparam */
|
||||
#define CT_DBYTE2 102 /* 2 byte ASCII + utf8_eucparam plane1/2 */
|
||||
#define CT_UTF16 1000 /* variable UTF-16 encoded Unicode no table */
|
||||
#define CT_UTF8 1001 /* variable UTF-8 encoded Unicode no table */
|
||||
#define CT_UTF7 1002 /* variable UTF-7 encoded Unicode no table */
|
||||
#define CT_2022 10000 /* variable ISO-2022 encoded no table */
|
||||
#define CT_SJIS 10001 /* 2 byte Shift-JIS encoded JIS no table */
|
||||
|
||||
|
||||
/* Character set flags */
|
||||
|
||||
#define CF_PRIMARY 0x1 /* primary name for this charset */
|
||||
#define CF_DISPLAY 0x2 /* charset used in displays */
|
||||
#define CF_POSTING 0x4 /* charset used in email posting */
|
||||
#define CF_UNSUPRT 0x8 /* charset unsupported (can't convert to it) */
|
||||
#define CF_NOEMAIL 0x10 /* charset not used in email */
|
||||
|
||||
|
||||
/* UTF-7 engine states */
|
||||
|
||||
#define U7_ASCII 0 /* ASCII character */
|
||||
#define U7_PLUS 1 /* plus seen */
|
||||
#define U7_UNICODE 2 /* Unicode characters */
|
||||
#define U7_MINUS 3 /* absorbed minus seen */
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
typedef unsigned long (*ucs4cn_t) (unsigned long c);
|
||||
typedef unsigned long (*ucs4de_t) (unsigned long c,void **more);
|
||||
|
||||
SCRIPT *utf8_script (char *script);
|
||||
const CHARSET *utf8_charset (char *charset);
|
||||
char *utf8_badcharset (char *charset);
|
||||
long utf8_text (SIZEDTEXT *text,char *charset,SIZEDTEXT *ret,long flags);
|
||||
long utf8_text_cs (SIZEDTEXT *text,const CHARSET *cs,SIZEDTEXT *ret,
|
||||
ucs4cn_t cv,ucs4de_t de);
|
||||
long utf8_cstext (SIZEDTEXT *text,char *charset,SIZEDTEXT *ret,
|
||||
unsigned long errch);
|
||||
long utf8_cstocstext (SIZEDTEXT *text,char *sc,SIZEDTEXT *ret,char *dc,
|
||||
unsigned long errch);
|
||||
unsigned short *utf8_rmap (char *charset);
|
||||
unsigned short *utf8_rmap_cs (const CHARSET *cs);
|
||||
unsigned short *utf8_rmap_gen (const CHARSET *cs,unsigned short *oldmap);
|
||||
long utf8_rmaptext (SIZEDTEXT *text,unsigned short *rmap,SIZEDTEXT *ret,
|
||||
unsigned long errch,long iso2022jp);
|
||||
unsigned long utf8_rmapsize (SIZEDTEXT *text,unsigned short *rmap,
|
||||
unsigned long errch,long iso2022jp);
|
||||
long ucs4_rmaptext (unsigned long *ucs4,unsigned long len,unsigned short *rmap,
|
||||
SIZEDTEXT *ret,unsigned long errch);
|
||||
long ucs4_rmaplen (unsigned long *ucs4,unsigned long len,unsigned short *rmap,
|
||||
unsigned long errch);
|
||||
long ucs4_rmapbuf (unsigned char *t,unsigned long *ucs4,unsigned long len,
|
||||
unsigned short *rmap,unsigned long errch);
|
||||
unsigned long utf8_get (unsigned char **s,unsigned long *i);
|
||||
unsigned long utf8_get_raw (unsigned char **s,unsigned long *i);
|
||||
unsigned long ucs4_cs_get (CHARSET *cs,unsigned char **s,unsigned long *i);
|
||||
unsigned long *utf8_csvalidmap (char *charsets[]);
|
||||
const CHARSET *utf8_infercharset (SIZEDTEXT *src);
|
||||
long utf8_validate (unsigned char *s,unsigned long i);
|
||||
void utf8_text_1byte0 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_1byte (SIZEDTEXT *text,SIZEDTEXT *ret,void *tab,ucs4cn_t cv,
|
||||
ucs4de_t de);
|
||||
void utf8_text_1byte8 (SIZEDTEXT *text,SIZEDTEXT *ret,void *tab,ucs4cn_t cv,
|
||||
ucs4de_t de);
|
||||
void utf8_text_euc (SIZEDTEXT *text,SIZEDTEXT *ret,void *tab,ucs4cn_t cv,
|
||||
ucs4de_t de);
|
||||
void utf8_text_dbyte (SIZEDTEXT *text,SIZEDTEXT *ret,void *tab,ucs4cn_t cv,
|
||||
ucs4de_t de);
|
||||
void utf8_text_dbyte2 (SIZEDTEXT *text,SIZEDTEXT *ret,void *tab,ucs4cn_t cv,
|
||||
ucs4de_t de);
|
||||
void utf8_text_sjis (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_2022 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_utf7 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_utf8 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_ucs2 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_ucs4 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
void utf8_text_utf16 (SIZEDTEXT *text,SIZEDTEXT *ret,ucs4cn_t cv,ucs4de_t de);
|
||||
unsigned long utf8_size (unsigned long c);
|
||||
unsigned char *utf8_put (unsigned char *s,unsigned long c);
|
||||
unsigned long ucs4_titlecase (unsigned long c);
|
||||
long ucs4_width (unsigned long c);
|
||||
long utf8_strwidth (unsigned char *s);
|
||||
long utf8_textwidth (SIZEDTEXT *utf8);
|
||||
unsigned long ucs4_decompose (unsigned long c,void **more);
|
||||
unsigned long ucs4_decompose_recursive (unsigned long c,void **more);
|
||||
449
src/c-client/utf8aux.c
Normal file
449
src/c-client/utf8aux.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: UTF-8 auxillary routines (c-client and MIME2 support)
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 11 June 1997
|
||||
* Last Edited: 12 October 2007
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "c-client.h"
|
||||
|
||||
/* Convert charset labelled stringlist to UTF-8 in place
|
||||
* Accepts: string list
|
||||
* charset
|
||||
*/
|
||||
|
||||
static void utf8_stringlist (STRINGLIST *st,char *charset)
|
||||
{
|
||||
SIZEDTEXT txt;
|
||||
/* convert entire stringstruct */
|
||||
if (st) do if (utf8_text (&st->text,charset,&txt,U8T_CANONICAL)) {
|
||||
fs_give ((void **) &st->text.data);
|
||||
st->text.data = txt.data; /* transfer this text */
|
||||
st->text.size = txt.size;
|
||||
} while (st = st->next);
|
||||
}
|
||||
|
||||
|
||||
/* Convert charset labelled searchpgm to UTF-8 in place
|
||||
* Accepts: search program
|
||||
* charset
|
||||
*/
|
||||
|
||||
void utf8_searchpgm (SEARCHPGM *pgm,char *charset)
|
||||
{
|
||||
SIZEDTEXT txt;
|
||||
SEARCHHEADER *hl;
|
||||
SEARCHOR *ol;
|
||||
SEARCHPGMLIST *pl;
|
||||
if (pgm) { /* must have a search program */
|
||||
utf8_stringlist (pgm->bcc,charset);
|
||||
utf8_stringlist (pgm->cc,charset);
|
||||
utf8_stringlist (pgm->from,charset);
|
||||
utf8_stringlist (pgm->to,charset);
|
||||
utf8_stringlist (pgm->subject,charset);
|
||||
for (hl = pgm->header; hl; hl = hl->next) {
|
||||
if (utf8_text (&hl->line,charset,&txt,U8T_CANONICAL)) {
|
||||
fs_give ((void **) &hl->line.data);
|
||||
hl->line.data = txt.data;
|
||||
hl->line.size = txt.size;
|
||||
}
|
||||
if (utf8_text (&hl->text,charset,&txt,U8T_CANONICAL)) {
|
||||
fs_give ((void **) &hl->text.data);
|
||||
hl->text.data = txt.data;
|
||||
hl->text.size = txt.size;
|
||||
}
|
||||
}
|
||||
utf8_stringlist (pgm->body,charset);
|
||||
utf8_stringlist (pgm->text,charset);
|
||||
for (ol = pgm->or; ol; ol = ol->next) {
|
||||
utf8_searchpgm (ol->first,charset);
|
||||
utf8_searchpgm (ol->second,charset);
|
||||
}
|
||||
for (pl = pgm->not; pl; pl = pl->next) utf8_searchpgm (pl->pgm,charset);
|
||||
utf8_stringlist (pgm->return_path,charset);
|
||||
utf8_stringlist (pgm->sender,charset);
|
||||
utf8_stringlist (pgm->reply_to,charset);
|
||||
utf8_stringlist (pgm->in_reply_to,charset);
|
||||
utf8_stringlist (pgm->message_id,charset);
|
||||
utf8_stringlist (pgm->newsgroups,charset);
|
||||
utf8_stringlist (pgm->followup_to,charset);
|
||||
utf8_stringlist (pgm->references,charset);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert MIME-2 sized text to UTF-8
|
||||
* Accepts: source sized text
|
||||
* charset
|
||||
* flags (same as utf8_text())
|
||||
* Returns: T if successful, NIL if failure
|
||||
*/
|
||||
|
||||
#define MINENCWORD 9
|
||||
#define MAXENCWORD 75
|
||||
|
||||
/* This resizing algorithm is stupid, but hopefully it should never be triggered
|
||||
* except for a pathological header. The main concern is that we don't get a
|
||||
* buffer overflow.
|
||||
*/
|
||||
|
||||
#define DSIZE 65536 /* real headers should never be this big */
|
||||
#define FUZZ 10 /* paranoia fuzz */
|
||||
|
||||
long utf8_mime2text (SIZEDTEXT *src,SIZEDTEXT *dst,long flags)
|
||||
{
|
||||
unsigned char *s,*se,*e,*ee,*t,*te;
|
||||
char *cs,*ce,*ls;
|
||||
SIZEDTEXT txt,rtxt;
|
||||
unsigned long i;
|
||||
size_t dsize = min (DSIZE,((src->size / 4) + 1) * 9);
|
||||
/* always create buffer if canonicalizing */
|
||||
dst->data = (flags & U8T_CANONICAL) ?
|
||||
(unsigned char *) fs_get ((size_t) dsize) : NIL;
|
||||
dst->size = 0; /* nothing written yet */
|
||||
/* look for encoded words */
|
||||
for (s = src->data, se = src->data + src->size; s < se; s++) {
|
||||
if (((se - s) > MINENCWORD) && (*s == '=') && (s[1] == '?') &&
|
||||
(cs = (char *) mime2_token (s+2,se,(unsigned char **) &ce)) &&
|
||||
(e = mime2_token ((unsigned char *) ce+1,se,&ee)) &&
|
||||
(te = mime2_text (t = e+2,se)) && (ee == e + 1) &&
|
||||
((te - s) < MAXENCWORD)) {
|
||||
if (mime2_decode (e,t,te,&txt)) {
|
||||
*ce = '\0'; /* temporarily tie off charset */
|
||||
if (ls = strchr (cs,'*')) *ls = '\0';
|
||||
/* convert to UTF-8 as best we can */
|
||||
if (!utf8_text (&txt,cs,&rtxt,flags)) utf8_text (&txt,NIL,&rtxt,flags);
|
||||
if (dst->data) { /* make sure existing buffer fits */
|
||||
while (dsize <= (dst->size + rtxt.size + FUZZ)) {
|
||||
dsize += DSIZE; /* kick it up */
|
||||
fs_resize ((void **) &dst->data,dsize);
|
||||
}
|
||||
}
|
||||
else { /* make a new buffer */
|
||||
while (dsize <= (dst->size + rtxt.size)) dsize += DSIZE;
|
||||
memcpy (dst->data = (unsigned char *) fs_get (dsize),src->data,
|
||||
dst->size = s - src->data);
|
||||
}
|
||||
for (i = 0; i < rtxt.size; i++) dst->data[dst->size++] = rtxt.data[i];
|
||||
|
||||
/* all done with converted text */
|
||||
if (rtxt.data != txt.data) fs_give ((void **) &rtxt.data);
|
||||
if (ls) *ls = '*'; /* restore language tag delimiter */
|
||||
*ce = '?'; /* restore charset delimiter */
|
||||
/* all done with decoded text */
|
||||
fs_give ((void **) &txt.data);
|
||||
s = te+1; /* continue scan after encoded word */
|
||||
/* skip leading whitespace */
|
||||
for (t = s + 1; (t < se) && ((*t == ' ') || (*t == '\t')); t++);
|
||||
/* see if likely continuation encoded word */
|
||||
if (t < (se - MINENCWORD)) switch (*t) {
|
||||
case '=': /* possible encoded word? */
|
||||
if (t[1] == '?') s = t - 1;
|
||||
break;
|
||||
case '\015': /* CR, eat a following LF */
|
||||
if (t[1] == '\012') t++;
|
||||
case '\012': /* possible end of logical line */
|
||||
if ((t[1] == ' ') || (t[1] == '\t')) {
|
||||
do t++;
|
||||
while ((t < (se - MINENCWORD)) && ((t[1] == ' ')||(t[1] == '\t')));
|
||||
if ((t < (se - MINENCWORD)) && (t[1] == '=') && (t[2] == '?'))
|
||||
s = t; /* definitely looks like continuation */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* restore original text */
|
||||
if (dst->data) fs_give ((void **) &dst->data);
|
||||
dst->data = src->data;
|
||||
dst->size = src->size;
|
||||
return NIL; /* syntax error: MIME-2 decoding failure */
|
||||
}
|
||||
}
|
||||
else do if (dst->data) { /* stash ASCII characters until LWSP */
|
||||
if (dsize < (dst->size + FUZZ)) {
|
||||
dsize += DSIZE; /* kick it up */
|
||||
fs_resize ((void **) &dst->data,dsize);
|
||||
}
|
||||
/* kludge: assumes ASCII doesn't decompose and titlecases to one byte */
|
||||
dst->data[dst->size++] = (flags & U8T_CASECANON) ?
|
||||
(unsigned char) ucs4_titlecase (*s) : *s;
|
||||
}
|
||||
while ((*s != ' ') && (*s != '\t') && (*s != '\015') && (*s != '\012') &&
|
||||
(++s < se));
|
||||
}
|
||||
if (dst->data) dst->data[dst->size] = '\0';
|
||||
else { /* nothing converted, return identity */
|
||||
dst->data = src->data;
|
||||
dst->size = src->size;
|
||||
}
|
||||
return T; /* success */
|
||||
}
|
||||
|
||||
/* Decode MIME-2 text
|
||||
* Accepts: Encoding
|
||||
* text
|
||||
* text end
|
||||
* destination sized text
|
||||
* Returns: T if successful, else NIL
|
||||
*/
|
||||
|
||||
long mime2_decode (unsigned char *e,unsigned char *t,unsigned char *te,
|
||||
SIZEDTEXT *txt)
|
||||
{
|
||||
unsigned char *q;
|
||||
txt->data = NIL; /* initially no returned data */
|
||||
switch (*e) { /* dispatch based upon encoding */
|
||||
case 'Q': case 'q': /* sort-of QUOTED-PRINTABLE */
|
||||
txt->data = (unsigned char *) fs_get ((size_t) (te - t) + 1);
|
||||
for (q = t,txt->size = 0; q < te; q++) switch (*q) {
|
||||
case '=': /* quoted character */
|
||||
/* both must be hex */
|
||||
if (!isxdigit (q[1]) || !isxdigit (q[2])) {
|
||||
fs_give ((void **) &txt->data);
|
||||
return NIL; /* syntax error: bad quoted character */
|
||||
}
|
||||
/* assemble character */
|
||||
txt->data[txt->size++] = hex2byte (q[1],q[2]);
|
||||
q += 2; /* advance past quoted character */
|
||||
break;
|
||||
case '_': /* convert to space */
|
||||
txt->data[txt->size++] = ' ';
|
||||
break;
|
||||
default: /* ordinary character */
|
||||
txt->data[txt->size++] = *q;
|
||||
break;
|
||||
}
|
||||
txt->data[txt->size] = '\0';
|
||||
break;
|
||||
case 'B': case 'b': /* BASE64 */
|
||||
if (txt->data = (unsigned char *) rfc822_base64 (t,te - t,&txt->size))
|
||||
break;
|
||||
default: /* any other encoding is unknown */
|
||||
return NIL; /* syntax error: unknown encoding */
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
/* Get MIME-2 token from encoded word
|
||||
* Accepts: current text pointer
|
||||
* text limit pointer
|
||||
* pointer to returned end pointer
|
||||
* Returns: current text pointer & end pointer if success, else NIL
|
||||
*/
|
||||
|
||||
unsigned char *mime2_token (unsigned char *s,unsigned char *se,
|
||||
unsigned char **t)
|
||||
{
|
||||
for (*t = s; **t != '?'; ++*t) {
|
||||
if ((*t < se) && isgraph (**t)) switch (**t) {
|
||||
case '(': case ')': case '<': case '>': case '@': case ',': case ';':
|
||||
case ':': case '\\': case '"': case '/': case '[': case ']': case '.':
|
||||
case '=':
|
||||
return NIL; /* none of these are valid in tokens */
|
||||
}
|
||||
else return NIL; /* out of text or CTL or space */
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/* Get MIME-2 text from encoded word
|
||||
* Accepts: current text pointer
|
||||
* text limit pointer
|
||||
* pointer to returned end pointer
|
||||
* Returns: end pointer if success, else NIL
|
||||
*/
|
||||
|
||||
unsigned char *mime2_text (unsigned char *s,unsigned char *se)
|
||||
{
|
||||
unsigned char *t = se - 1;
|
||||
/* search for closing ?, make sure valid */
|
||||
while ((s < t) && (*s != '?') && isgraph (*s++));
|
||||
return ((s < t) && (*s == '?') && (s[1] == '=') &&
|
||||
((se == (s + 2)) || (s[2] == ' ') || (s[2] == '\t') ||
|
||||
(s[2] == '\015') || (s[2] == '\012'))) ? s : NIL;
|
||||
}
|
||||
|
||||
/* Convert UTF-16 string to Modified Base64
|
||||
* Accepts: destination pointer
|
||||
* source string
|
||||
* source length in octets
|
||||
* Returns: updated destination pointer
|
||||
*/
|
||||
|
||||
static unsigned char *utf16_to_mbase64 (unsigned char *t,unsigned char *s,
|
||||
size_t i)
|
||||
{
|
||||
char *v = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
||||
*t++ = '&'; /* write shift-in */
|
||||
while (i >= 3) { /* process tuplets */
|
||||
*t++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
||||
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
||||
*t++ = v[((s[0] << 4) + (s[1] >> 4)) & 0x3f];
|
||||
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
||||
*t++ = v[((s[1] << 2) + (s[2] >> 6)) & 0x3f];
|
||||
*t++ = v[s[2] & 0x3f]; /* byte 4: low 6 bits (3) */
|
||||
s += 3;
|
||||
i -= 3;
|
||||
}
|
||||
if (i) {
|
||||
*t++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
||||
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
||||
*t++ = v[((s[0] << 4) + (--i ? (s[1] >> 4) : 0)) & 0x3f];
|
||||
/* byte 3: low 4 bits (2) */
|
||||
if (i) *t++ = v[(s[1] << 2) & 0x3f];
|
||||
}
|
||||
*t++ = '-'; /* write shift-out */
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/* Poot a UTF-16 value to a buffer
|
||||
* Accepts: buffer pointer
|
||||
* value
|
||||
* Returns: updated pointer
|
||||
*/
|
||||
|
||||
static unsigned char *utf16_poot (unsigned char *s,unsigned long c)
|
||||
{
|
||||
*s++ = (unsigned char) (c >> 8);
|
||||
*s++ = (unsigned char) (c & 0xff);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Convert UTF-8 to Modified UTF-7
|
||||
* Accepts: UTF-8 string
|
||||
* Returns: Modified UTF-7 string on success, NIL if invalid UTF-8
|
||||
*/
|
||||
|
||||
#define MAXUNIUTF8 4 /* maximum length of Unicode UTF-8 sequence */
|
||||
|
||||
unsigned char *utf8_to_mutf7 (unsigned char *src)
|
||||
{
|
||||
unsigned char *u16buf,*utf16;
|
||||
unsigned char *ret,*t;
|
||||
unsigned long j,c;
|
||||
unsigned char *s = src;
|
||||
unsigned long i = 0;
|
||||
int nonascii = 0;
|
||||
while (*s) { /* pass one: count destination octets */
|
||||
if (*s & 0x80) { /* non-ASCII character? */
|
||||
j = MAXUNIUTF8; /* get single UCS-4 codepoint */
|
||||
if ((c = utf8_get (&s,&j)) & U8G_ERROR) return NIL;
|
||||
/* tally number of UTF-16 octets */
|
||||
nonascii += (c & U8GM_NONBMP) ? 4 : 2;
|
||||
}
|
||||
else { /* ASCII character */
|
||||
if (nonascii) { /* add pending Modified BASE64 size + shifts */
|
||||
i += ((nonascii / 3) * 4) + ((j = nonascii % 3) ? j + 1 : 0) + 2;
|
||||
nonascii = 0; /* back to ASCII */
|
||||
}
|
||||
if (*s == '&') i += 2; /* two octets if the escape */
|
||||
else ++i; /* otherwise just count another octet */
|
||||
++s; /* advance to next source octet */
|
||||
}
|
||||
}
|
||||
if (nonascii) /* add pending Modified BASE64 size + shifts */
|
||||
i += ((nonascii / 3) * 4) + ((j = nonascii % 3) ? j + 1 : 0) + 2;
|
||||
|
||||
/* create return buffer */
|
||||
t = ret = (unsigned char *) fs_get (i + 1);
|
||||
/* and scratch buffer */
|
||||
utf16 = u16buf = (unsigned char *) fs_get (i + 1);
|
||||
for (s = src; *s;) { /* pass two: copy destination octets */
|
||||
if (*s & 0x80) { /* non-ASCII character? */
|
||||
j = MAXUNIUTF8; /* get single UCS-4 codepoint */
|
||||
if ((c = utf8_get (&s,&j)) & U8G_ERROR) return NIL;
|
||||
if (c & U8GM_NONBMP) { /* non-BMP? */
|
||||
c -= UTF16_BASE; /* yes, convert to surrogate */
|
||||
utf16 = utf16_poot (utf16_poot (utf16,(c >> UTF16_SHIFT)+UTF16_SURRH),
|
||||
(c & UTF16_MASK) + UTF16_SURRL);
|
||||
}
|
||||
else utf16 = utf16_poot (utf16,c);
|
||||
}
|
||||
else { /* ASCII character */
|
||||
if (utf16 != u16buf) { /* add pending Modified BASE64 size + shifts */
|
||||
t = utf16_to_mbase64 (t,u16buf,utf16 - u16buf);
|
||||
utf16 = u16buf; /* reset buffer */
|
||||
}
|
||||
*t++ = *s; /* copy the character */
|
||||
if (*s == '&') *t++ = '-';/* special sequence if the escape */
|
||||
++s; /* advance to next source octet */
|
||||
}
|
||||
}
|
||||
/* add pending Modified BASE64 size + shifts */
|
||||
if (utf16 != u16buf) t = utf16_to_mbase64 (t,u16buf,utf16 - u16buf);
|
||||
*t = '\0'; /* tie off destination */
|
||||
if (i != (t - ret)) fatal ("utf8_to_mutf7 botch");
|
||||
fs_give ((void **) &u16buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Convert Modified UTF-7 to UTF-8
|
||||
* Accepts: Modified UTF-7 string
|
||||
* Returns: UTF-8 string on success, NIL if invalid Modified UTF-7
|
||||
*/
|
||||
|
||||
unsigned char *utf8_from_mutf7 (unsigned char *src)
|
||||
{
|
||||
SIZEDTEXT utf8,utf7;
|
||||
unsigned char *s;
|
||||
int mbase64 = 0;
|
||||
/* disallow bogus strings */
|
||||
if (mail_utf7_valid (src)) return NIL;
|
||||
/* initialize SIZEDTEXTs */
|
||||
memset (&utf7,0,sizeof (SIZEDTEXT));
|
||||
memset (&utf8,0,sizeof (SIZEDTEXT));
|
||||
/* make copy of source */
|
||||
for (s = cpytxt (&utf7,src,strlen (src)); *s; ++s) switch (*s) {
|
||||
case '&': /* Modified UTF-7 uses & instead of + */
|
||||
*s = '+';
|
||||
mbase64 = T; /* note that we are in Modified BASE64 */
|
||||
break;
|
||||
case '+': /* temporarily swap text + to & */
|
||||
if (!mbase64) *s = '&';
|
||||
break;
|
||||
case '-': /* shift back to ASCII */
|
||||
mbase64 = NIL;
|
||||
break;
|
||||
case ',': /* Modified UTF-7 uses , instead of / ... */
|
||||
if (mbase64) *s = '/'; /* ...in Modified BASE64 */
|
||||
break;
|
||||
}
|
||||
/* do the conversion */
|
||||
utf8_text_utf7 (&utf7,&utf8,NIL,NIL);
|
||||
/* no longer need copy of source */
|
||||
fs_give ((void **) &utf7.data);
|
||||
/* post-process: switch & and + */
|
||||
for (s = utf8.data; *s; ++s) switch (*s) {
|
||||
case '&':
|
||||
*s = '+';
|
||||
break;
|
||||
case '+':
|
||||
*s = '&';
|
||||
break;
|
||||
}
|
||||
return utf8.data;
|
||||
}
|
||||
44
src/c-client/utf8aux.h
Normal file
44
src/c-client/utf8aux.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: UTF-8 auxillary routines (c-client and MIME2 support)
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 11 June 1997
|
||||
* Last Edited: 9 October 2007
|
||||
*/
|
||||
|
||||
|
||||
/* Following routines are in utf8aux.c as these depend upon c-client.
|
||||
* Splitting these routines out makes it possible for pico to link with utf8.o
|
||||
* and a few rump routines (e.g., fs_get()) but not all the rest of c-client
|
||||
* (which pico does not need).
|
||||
*/
|
||||
|
||||
void utf8_searchpgm (SEARCHPGM *pgm,char *charset);
|
||||
long utf8_mime2text (SIZEDTEXT *src,SIZEDTEXT *dst,long flags);
|
||||
unsigned char *mime2_token (unsigned char *s,unsigned char *se,
|
||||
unsigned char **t);
|
||||
unsigned char *mime2_text (unsigned char *s,unsigned char *se);
|
||||
long mime2_decode (unsigned char *e,unsigned char *t,unsigned char *te,
|
||||
SIZEDTEXT *txt);
|
||||
unsigned char *utf8_to_mutf7 (unsigned char *src);
|
||||
unsigned char *utf8_from_mutf7 (unsigned char *src);
|
||||
2016
src/charset/big5.c
Normal file
2016
src/charset/big5.c
Normal file
File diff suppressed because it is too large
Load Diff
8590
src/charset/cns11643.c
Normal file
8590
src/charset/cns11643.c
Normal file
File diff suppressed because it is too large
Load Diff
2909
src/charset/decomtab.c
Normal file
2909
src/charset/decomtab.c
Normal file
File diff suppressed because it is too large
Load Diff
1114
src/charset/gb_12345.c
Normal file
1114
src/charset/gb_12345.c
Normal file
File diff suppressed because it is too large
Load Diff
2795
src/charset/gb_2312.c
Normal file
2795
src/charset/gb_2312.c
Normal file
File diff suppressed because it is too large
Load Diff
347
src/charset/ibm.c
Normal file
347
src/charset/ibm.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: IBM conversion tables
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 4 November 2002
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* IBM Latin US */
|
||||
static const unsigned short ibm_437tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,
|
||||
0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,
|
||||
0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Greek */
|
||||
static const unsigned short ibm_737tab[128] = {
|
||||
0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,
|
||||
0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,0x03a0,
|
||||
0x03a1,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,
|
||||
0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,0x03b8,
|
||||
0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03c0,
|
||||
0x03c1,0x03c3,0x03c2,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03c9,0x03ac,0x03ad,0x03ae,0x03ca,0x03af,0x03cc,0x03cd,
|
||||
0x03cb,0x03ce,0x0386,0x0388,0x0389,0x038a,0x038c,0x038e,
|
||||
0x038f,0x00b1,0x2265,0x2264,0x03aa,0x03ab,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Baltic Rim */
|
||||
static const unsigned short ibm_775tab[128] = {
|
||||
0x0106,0x00fc,0x00e9,0x0101,0x00e4,0x0123,0x00e5,0x0107,
|
||||
0x0142,0x0113,0x0156,0x0157,0x012b,0x0179,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x014d,0x00f6,0x0122,0x00a2,0x015a,
|
||||
0x015b,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x00a4,
|
||||
0x0100,0x012a,0x00f3,0x017b,0x017c,0x017a,0x201d,0x00a6,
|
||||
0x00a9,0x00ae,0x00ac,0x00bd,0x00bc,0x0141,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x0104,0x010c,0x0118,
|
||||
0x0116,0x2563,0x2551,0x2557,0x255d,0x012e,0x0160,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0172,0x016a,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x017d,
|
||||
0x0105,0x010d,0x0119,0x0117,0x012f,0x0161,0x0173,0x016b,
|
||||
0x017e,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x00d3,0x00df,0x014c,0x0143,0x00f5,0x00d5,0x00b5,0x0144,
|
||||
0x0136,0x0137,0x013b,0x013c,0x0146,0x0112,0x0145,0x2019,
|
||||
0x00ad,0x00b1,0x201c,0x00be,0x00b6,0x00a7,0x00f7,0x201e,
|
||||
0x00b0,0x2219,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Latin 1 */
|
||||
static const unsigned short ibm_850tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,
|
||||
0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x00d7,0x0192,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,
|
||||
0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,
|
||||
0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
|
||||
0x00f0,0x00d0,0x00ca,0x00cb,0x00c8,0x0131,0x00cd,0x00ce,
|
||||
0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
|
||||
0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,0x00fe,
|
||||
0x00de,0x00da,0x00db,0x00d9,0x00fd,0x00dd,0x00af,0x00b4,
|
||||
0x00ad,0x00b1,0x2017,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,
|
||||
0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Latin 2 */
|
||||
static const unsigned short ibm_852tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x016f,0x0107,0x00e7,
|
||||
0x0142,0x00eb,0x0150,0x0151,0x00ee,0x0179,0x00c4,0x0106,
|
||||
0x00c9,0x0139,0x013a,0x00f4,0x00f6,0x013d,0x013e,0x015a,
|
||||
0x015b,0x00d6,0x00dc,0x0164,0x0165,0x0141,0x00d7,0x010d,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x0104,0x0105,0x017d,0x017e,
|
||||
0x0118,0x0119,0x00ac,0x017a,0x010c,0x015f,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x011a,
|
||||
0x015e,0x2563,0x2551,0x2557,0x255d,0x017b,0x017c,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x0102,0x0103,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
|
||||
0x0111,0x0110,0x010e,0x00cb,0x010f,0x0147,0x00cd,0x00ce,
|
||||
0x011b,0x2518,0x250c,0x2588,0x2584,0x0162,0x016e,0x2580,
|
||||
0x00d3,0x00df,0x00d4,0x0143,0x0144,0x0148,0x0160,0x0161,
|
||||
0x0154,0x00da,0x0155,0x0170,0x00fd,0x00dd,0x0163,0x00b4,
|
||||
0x00ad,0x02dd,0x02db,0x02c7,0x02d8,0x00a7,0x00f7,0x00b8,
|
||||
0x00b0,0x00a8,0x02d9,0x0171,0x0158,0x0159,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Cyrillic */
|
||||
static const unsigned short ibm_855tab[128] = {
|
||||
0x0452,0x0402,0x0453,0x0403,0x0451,0x0401,0x0454,0x0404,
|
||||
0x0455,0x0405,0x0456,0x0406,0x0457,0x0407,0x0458,0x0408,
|
||||
0x0459,0x0409,0x045a,0x040a,0x045b,0x040b,0x045c,0x040c,
|
||||
0x045e,0x040e,0x045f,0x040f,0x044e,0x042e,0x044a,0x042a,
|
||||
0x0430,0x0410,0x0431,0x0411,0x0446,0x0426,0x0434,0x0414,
|
||||
0x0435,0x0415,0x0444,0x0424,0x0433,0x0413,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x0445,0x0425,0x0438,
|
||||
0x0418,0x2563,0x2551,0x2557,0x255d,0x0439,0x0419,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x043a,0x041a,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
|
||||
0x043b,0x041b,0x043c,0x041c,0x043d,0x041d,0x043e,0x041e,
|
||||
0x043f,0x2518,0x250c,0x2588,0x2584,0x041f,0x044f,0x2580,
|
||||
0x042f,0x0440,0x0420,0x0441,0x0421,0x0442,0x0422,0x0443,
|
||||
0x0423,0x0436,0x0416,0x0432,0x0412,0x044c,0x042c,0x2116,
|
||||
0x00ad,0x044b,0x042b,0x0437,0x0417,0x0448,0x0428,0x044d,
|
||||
0x042d,0x0449,0x0429,0x0447,0x0427,0x00a7,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Turkish */
|
||||
static const unsigned short ibm_857tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x0131,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,
|
||||
0x0130,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x015e,0x015f,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x011e,0x011f,
|
||||
0x00bf,0x00ae,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x00c1,0x00c2,0x00c0,
|
||||
0x00a9,0x2563,0x2551,0x2557,0x255d,0x00a2,0x00a5,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x00e3,0x00c3,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x00a4,
|
||||
0x00ba,0x00aa,0x00ca,0x00cb,0x00c8,UBOGON,0x00cd,0x00ce,
|
||||
0x00cf,0x2518,0x250c,0x2588,0x2584,0x00a6,0x00cc,0x2580,
|
||||
0x00d3,0x00df,0x00d4,0x00d2,0x00f5,0x00d5,0x00b5,UBOGON,
|
||||
0x00d7,0x00da,0x00db,0x00d9,0x00ec,0x00ff,0x00af,0x00b4,
|
||||
0x00ad,0x00b1,UBOGON,0x00be,0x00b6,0x00a7,0x00f7,0x00b8,
|
||||
0x00b0,0x00a8,0x00b7,0x00b9,0x00b3,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Portuguese */
|
||||
static const unsigned short ibm_860tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e3,0x00e0,0x00c1,0x00e7,
|
||||
0x00ea,0x00ca,0x00e8,0x00cd,0x00d4,0x00ec,0x00c3,0x00c2,
|
||||
0x00c9,0x00c0,0x00c8,0x00f4,0x00f5,0x00f2,0x00da,0x00f9,
|
||||
0x00cc,0x00d5,0x00dc,0x00a2,0x00a3,0x00d9,0x20a7,0x00d3,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,
|
||||
0x00bf,0x00d2,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Icelandic */
|
||||
static const unsigned short ibm_861tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00d0,0x00f0,0x00de,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00fe,0x00fb,0x00dd,
|
||||
0x00fd,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00c1,0x00cd,0x00d3,0x00da,
|
||||
0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Hebrew */
|
||||
static const unsigned short ibm_862tab[128] = {
|
||||
0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,
|
||||
0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df,
|
||||
0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,
|
||||
0x05e8,0x05e9,0x05ea,0x00a2,0x00a3,0x00a5,0x20a7,0x0192,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,
|
||||
0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Canada/French */
|
||||
static const unsigned short ibm_863tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00c2,0x00e0,0x00b6,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x2017,0x00c0,0x00a7,
|
||||
0x00c9,0x00c8,0x00ca,0x00f4,0x00cb,0x00cf,0x00fb,0x00f9,
|
||||
0x00a4,0x00d4,0x00dc,0x00a2,0x00a3,0x00d9,0x00db,0x0192,
|
||||
0x00a6,0x00b4,0x00f3,0x00fa,0x00a8,0x00b8,0x00b3,0x00af,
|
||||
0x00ce,0x2310,0x00ac,0x00bd,0x00bc,0x00be,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Arabic */
|
||||
static const unsigned short ibm_864tab[128] = {
|
||||
0x00b0,0x00b7,0x2219,0x221a,0x2592,0x2500,0x2502,0x253c,
|
||||
0x2524,0x252c,0x251c,0x2534,0x2510,0x250c,0x2514,0x2518,
|
||||
0x03b2,0x221e,0x03c6,0x00b1,0x00bd,0x00bc,0x2248,0x00ab,
|
||||
0x00bb,0xfef7,0xfef8,UBOGON,UBOGON,0xfefb,0xfefc,UBOGON,
|
||||
0x00a0,0x00ad,0xfe82,0x00a3,0x00a4,0xfe84,UBOGON,UBOGON,
|
||||
0xfe8e,0xfe8f,0xfe95,0xfe99,0x060c,0xfe9d,0xfea1,0xfea5,
|
||||
0x0660,0x0661,0x0662,0x0663,0x0664,0x0665,0x0666,0x0667,
|
||||
0x0668,0x0669,0xfed1,0x061b,0xfeb1,0xfeb5,0xfeb9,0x061f,
|
||||
0x00a2,0xfe80,0xfe81,0xfe83,0xfe85,0xfeca,0xfe8b,0xfe8d,
|
||||
0xfe91,0xfe93,0xfe97,0xfe9b,0xfe9f,0xfea3,0xfea7,0xfea9,
|
||||
0xfeab,0xfead,0xfeaf,0xfeb3,0xfeb7,0xfebb,0xfebf,0xfec1,
|
||||
0xfec5,0xfecb,0xfecf,0x00a6,0x00ac,0x00f7,0x00d7,0xfec9,
|
||||
0x0640,0xfed3,0xfed7,0xfedb,0xfedf,0xfee3,0xfee7,0xfeeb,
|
||||
0xfeed,0xfeef,0xfef3,0xfebd,0xfecc,0xfece,0xfecd,0xfee1,
|
||||
0xfe7d,0x0651,0xfee5,0xfee9,0xfeec,0xfef0,0xfef2,0xfed0,
|
||||
0xfed5,0xfef5,0xfef6,0xfedd,0xfed9,0xfef1,0x25a0,UBOGON
|
||||
};
|
||||
|
||||
/* IBM Nordic */
|
||||
static const unsigned short ibm_865tab[128] = {
|
||||
0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7,
|
||||
0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5,
|
||||
0x00c9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9,
|
||||
0x00ff,0x00d6,0x00dc,0x00f8,0x00a3,0x00d8,0x20a7,0x0192,
|
||||
0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba,
|
||||
0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00a4,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4,
|
||||
0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229,
|
||||
0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Cyrillic/Russian */
|
||||
static const unsigned short ibm_866tab[128] = {
|
||||
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,
|
||||
0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
|
||||
0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,
|
||||
0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
|
||||
0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,
|
||||
0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
|
||||
0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567,
|
||||
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b,
|
||||
0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580,
|
||||
0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,
|
||||
0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f,
|
||||
0x0401,0x0451,0x0404,0x0454,0x0407,0x0457,0x040e,0x045e,
|
||||
0x00b0,0x2219,0x00b7,0x221a,0x2116,0x00a4,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Greek 2 */
|
||||
static const unsigned short ibm_869tab[128] = {
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,0x0386,UBOGON,
|
||||
0x00b7,0x00ac,0x00a6,0x2018,0x2019,0x0388,0x2015,0x0389,
|
||||
0x038a,0x03aa,0x038c,UBOGON,UBOGON,0x038e,0x03ab,0x00a9,
|
||||
0x038f,0x00b2,0x00b3,0x03ac,0x00a3,0x03ad,0x03ae,0x03af,
|
||||
0x03ca,0x0390,0x03cc,0x03cd,0x0391,0x0392,0x0393,0x0394,
|
||||
0x0395,0x0396,0x0397,0x00bd,0x0398,0x0399,0x00ab,0x00bb,
|
||||
0x2591,0x2592,0x2593,0x2502,0x2524,0x039a,0x039b,0x039c,
|
||||
0x039d,0x2563,0x2551,0x2557,0x255d,0x039e,0x039f,0x2510,
|
||||
0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x03a0,0x03a1,
|
||||
0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x03a3,
|
||||
0x03a4,0x03a5,0x03a6,0x03a7,0x03a8,0x03a9,0x03b1,0x03b2,
|
||||
0x03b3,0x2518,0x250c,0x2588,0x2584,0x03b4,0x03b5,0x2580,
|
||||
0x03b6,0x03b7,0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,
|
||||
0x03be,0x03bf,0x03c0,0x03c1,0x03c3,0x03c2,0x03c4,0x0384,
|
||||
0x00ad,0x00b1,0x03c5,0x03c6,0x03c7,0x00a7,0x03c8,0x0385,
|
||||
0x00b0,0x00a8,0x03c9,0x03cb,0x03b0,0x03ce,0x25a0,0x00a0
|
||||
};
|
||||
|
||||
/* IBM Thai */
|
||||
static const unsigned short ibm_874tab[128] = {
|
||||
0x20ac,UBOGON,UBOGON,UBOGON,UBOGON,0x2026,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x00a0,0x0e01,0x0e02,0x0e03,0x0e04,0x0e05,0x0e06,0x0e07,
|
||||
0x0e08,0x0e09,0x0e0a,0x0e0b,0x0e0c,0x0e0d,0x0e0e,0x0e0f,
|
||||
0x0e10,0x0e11,0x0e12,0x0e13,0x0e14,0x0e15,0x0e16,0x0e17,
|
||||
0x0e18,0x0e19,0x0e1a,0x0e1b,0x0e1c,0x0e1d,0x0e1e,0x0e1f,
|
||||
0x0e20,0x0e21,0x0e22,0x0e23,0x0e24,0x0e25,0x0e26,0x0e27,
|
||||
0x0e28,0x0e29,0x0e2a,0x0e2b,0x0e2c,0x0e2d,0x0e2e,0x0e2f,
|
||||
0x0e30,0x0e31,0x0e32,0x0e33,0x0e34,0x0e35,0x0e36,0x0e37,
|
||||
0x0e38,0x0e39,0x0e3a,UBOGON,UBOGON,UBOGON,UBOGON,0x0e3f,
|
||||
0x0e40,0x0e41,0x0e42,0x0e43,0x0e44,0x0e45,0x0e46,0x0e47,
|
||||
0x0e48,0x0e49,0x0e4a,0x0e4b,0x0e4c,0x0e4d,0x0e4e,0x0e4f,
|
||||
0x0e50,0x0e51,0x0e52,0x0e53,0x0e54,0x0e55,0x0e56,0x0e57,
|
||||
0x0e58,0x0e59,0x0e5a,0x0e5b,UBOGON,UBOGON,UBOGON,UBOGON
|
||||
};
|
||||
308
src/charset/iso_8859.c
Normal file
308
src/charset/iso_8859.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: ISO-8859 conversion tables
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 3 July 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* ISO-8859 conversion tables */
|
||||
|
||||
/* Latin-2 (East European) */
|
||||
static const unsigned short iso8859_2tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0104,0x02d8,0x0141,0x00a4,0x013d,0x015a,0x00a7,
|
||||
0x00a8,0x0160,0x015e,0x0164,0x0179,0x00ad,0x017d,0x017b,
|
||||
0x00b0,0x0105,0x02db,0x0142,0x00b4,0x013e,0x015b,0x02c7,
|
||||
0x00b8,0x0161,0x015f,0x0165,0x017a,0x02dd,0x017e,0x017c,
|
||||
0x0154,0x00c1,0x00c2,0x0102,0x00c4,0x0139,0x0106,0x00c7,
|
||||
0x010c,0x00c9,0x0118,0x00cb,0x011a,0x00cd,0x00ce,0x010e,
|
||||
0x0110,0x0143,0x0147,0x00d3,0x00d4,0x0150,0x00d6,0x00d7,
|
||||
0x0158,0x016e,0x00da,0x0170,0x00dc,0x00dd,0x0162,0x00df,
|
||||
0x0155,0x00e1,0x00e2,0x0103,0x00e4,0x013a,0x0107,0x00e7,
|
||||
0x010d,0x00e9,0x0119,0x00eb,0x011b,0x00ed,0x00ee,0x010f,
|
||||
0x0111,0x0144,0x0148,0x00f3,0x00f4,0x0151,0x00f6,0x00f7,
|
||||
0x0159,0x016f,0x00fa,0x0171,0x00fc,0x00fd,0x0163,0x02d9
|
||||
};
|
||||
|
||||
|
||||
/* Latin-3 (South European) */
|
||||
static const unsigned short iso8859_3tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0126,0x02d8,0x00a3,0x00a4,UBOGON,0x0124,0x00a7,
|
||||
0x00a8,0x0130,0x015e,0x011e,0x0134,0x00ad,UBOGON,0x017b,
|
||||
0x00b0,0x0127,0x00b2,0x00b3,0x00b4,0x00b5,0x0125,0x00b7,
|
||||
0x00b8,0x0131,0x015f,0x011f,0x0135,0x00bd,UBOGON,0x017c,
|
||||
0x00c0,0x00c1,0x00c2,UBOGON,0x00c4,0x010a,0x0108,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
UBOGON,0x00d1,0x00d2,0x00d3,0x00d4,0x0120,0x00d6,0x00d7,
|
||||
0x011c,0x00d9,0x00da,0x00db,0x00dc,0x016c,0x015c,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,UBOGON,0x00e4,0x010b,0x0109,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
UBOGON,0x00f1,0x00f2,0x00f3,0x00f4,0x0121,0x00f6,0x00f7,
|
||||
0x011d,0x00f9,0x00fa,0x00fb,0x00fc,0x016d,0x015d,0x02d9
|
||||
};
|
||||
|
||||
|
||||
/* Latin-4 (North European) */
|
||||
static const unsigned short iso8859_4tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0104,0x0138,0x0156,0x00a4,0x0128,0x013b,0x00a7,
|
||||
0x00a8,0x0160,0x0112,0x0122,0x0166,0x00ad,0x017d,0x00af,
|
||||
0x00b0,0x0105,0x02db,0x0157,0x00b4,0x0129,0x013c,0x02c7,
|
||||
0x00b8,0x0161,0x0113,0x0123,0x0167,0x014a,0x017e,0x014b,
|
||||
0x0100,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x012e,
|
||||
0x010c,0x00c9,0x0118,0x00cb,0x0116,0x00cd,0x00ce,0x012a,
|
||||
0x0110,0x0145,0x014c,0x0136,0x00d4,0x00d5,0x00d6,0x00d7,
|
||||
0x00d8,0x0172,0x00da,0x00db,0x00dc,0x0168,0x016a,0x00df,
|
||||
0x0101,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x012f,
|
||||
0x010d,0x00e9,0x0119,0x00eb,0x0117,0x00ed,0x00ee,0x012b,
|
||||
0x0111,0x0146,0x014d,0x0137,0x00f4,0x00f5,0x00f6,0x00f7,
|
||||
0x00f8,0x0173,0x00fa,0x00fb,0x00fc,0x0169,0x016b,0x02d9
|
||||
};
|
||||
|
||||
|
||||
/* Cyrillic */
|
||||
static const unsigned short iso8859_5tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,
|
||||
0x0408,0x0409,0x040a,0x040b,0x040c,0x00ad,0x040e,0x040f,
|
||||
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,
|
||||
0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
|
||||
0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,
|
||||
0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
|
||||
0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,
|
||||
0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
|
||||
0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,
|
||||
0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f,
|
||||
0x2116,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,
|
||||
0x0458,0x0459,0x045a,0x045b,0x045c,0x00a7,0x045e,0x045f
|
||||
};
|
||||
|
||||
|
||||
/* Arabic */
|
||||
static const unsigned short iso8859_6tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,UBOGON,UBOGON,UBOGON,0x00a4,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,0x060c,0x00ad,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,0x061b,UBOGON,UBOGON,UBOGON,0x061f,
|
||||
UBOGON,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627,
|
||||
0x0628,0x0629,0x062a,0x062b,0x062c,0x062d,0x062e,0x062f,
|
||||
0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x0637,
|
||||
0x0638,0x0639,0x063a,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x0640,0x0641,0x0642,0x0643,0x0644,0x0645,0x0646,0x0647,
|
||||
0x0648,0x0649,0x064a,0x064b,0x064c,0x064d,0x064e,0x064f,
|
||||
0x0650,0x0651,0x0652,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON
|
||||
};
|
||||
|
||||
|
||||
/* Greek */
|
||||
static const unsigned short iso8859_7tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x2018,0x2019,0x00a3,UBOGON,UBOGON,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,UBOGON,0x00ab,0x00ac,0x00ad,UBOGON,0x2015,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x0384,0x0385,0x0386,0x00b7,
|
||||
0x0388,0x0389,0x038a,0x00bb,0x038c,0x00bd,0x038e,0x038f,
|
||||
0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,
|
||||
0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,
|
||||
0x03a0,0x03a1,UBOGON,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,
|
||||
0x03a8,0x03a9,0x03aa,0x03ab,0x03ac,0x03ad,0x03ae,0x03af,
|
||||
0x03b0,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,
|
||||
0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,
|
||||
0x03c0,0x03c1,0x03c2,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7,
|
||||
0x03c8,0x03c9,0x03ca,0x03cb,0x03cc,0x03cd,0x03ce,UBOGON
|
||||
};
|
||||
|
||||
|
||||
/* Hebrew */
|
||||
static const unsigned short iso8859_8tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,UBOGON,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00d7,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00f7,0x00bb,0x00bc,0x00bd,0x00be,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,0x2017,
|
||||
0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,
|
||||
0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df,
|
||||
0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,
|
||||
0x05e8,0x05e9,0x05ea,UBOGON,UBOGON,0x200e,0x200f,UBOGON
|
||||
};
|
||||
|
||||
|
||||
/* Latin-5 (Turkish) */
|
||||
static const unsigned short iso8859_9tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x011e,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x0130,0x015e,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x011f,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x0131,0x015f,0x00ff
|
||||
};
|
||||
|
||||
|
||||
/* Latin-6 (Nordic) */
|
||||
static const unsigned short iso8859_10tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0104,0x0112,0x0122,0x012a,0x0128,0x0136,0x00a7,
|
||||
0x013b,0x0110,0x0160,0x0166,0x017d,0x00ad,0x016a,0x014a,
|
||||
0x00b0,0x0105,0x0113,0x0123,0x012b,0x0129,0x0137,0x00b7,
|
||||
0x013c,0x0111,0x0161,0x0167,0x017e,0x2015,0x016b,0x014b,
|
||||
0x0100,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x012e,
|
||||
0x010c,0x00c9,0x0118,0x00cb,0x0116,0x00cd,0x00ce,0x00cf,
|
||||
0x00d0,0x0145,0x014c,0x00d3,0x00d4,0x00d5,0x00d6,0x0168,
|
||||
0x00d8,0x0172,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df,
|
||||
0x0101,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x012f,
|
||||
0x010d,0x00e9,0x0119,0x00eb,0x0117,0x00ed,0x00ee,0x00ef,
|
||||
0x00f0,0x0146,0x014d,0x00f3,0x00f4,0x00f5,0x00f6,0x0169,
|
||||
0x00f8,0x0173,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x0138
|
||||
};
|
||||
|
||||
|
||||
/* Thai */
|
||||
#define iso8859_11tab tis620tab
|
||||
|
||||
/* reserved for ISCII Indian */
|
||||
|
||||
/* Latin-7 (Baltic) */
|
||||
static const unsigned short iso8859_13tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x201d,0x00a2,0x00a3,0x00a4,0x201e,0x00a6,0x00a7,
|
||||
0x00d8,0x00a9,0x0156,0x00ab,0x00ac,0x00ad,0x00ae,0x00c6,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x201c,0x00b5,0x00b6,0x00b7,
|
||||
0x00f8,0x00b9,0x0157,0x00bb,0x00bc,0x00bd,0x00be,0x00e6,
|
||||
0x0104,0x012e,0x0100,0x0106,0x00c4,0x00c5,0x0118,0x0112,
|
||||
0x010c,0x00c9,0x0179,0x0116,0x0122,0x0136,0x012a,0x013b,
|
||||
0x0160,0x0143,0x0145,0x00d3,0x014c,0x00d5,0x00d6,0x00d7,
|
||||
0x0172,0x0141,0x015a,0x016a,0x00dc,0x017b,0x017d,0x00df,
|
||||
0x0105,0x012f,0x0101,0x0107,0x00e4,0x00e5,0x0119,0x0113,
|
||||
0x010d,0x00e9,0x017a,0x0117,0x0123,0x0137,0x012b,0x013c,
|
||||
0x0161,0x0144,0x0146,0x00f3,0x014d,0x00f5,0x00f6,0x00f7,
|
||||
0x0173,0x0142,0x015b,0x016b,0x00fc,0x017c,0x017e,0x2019
|
||||
};
|
||||
|
||||
|
||||
/* Latin-8 (Celtic) */
|
||||
|
||||
static const unsigned short iso8859_14tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x1e02,0x1e03,0x00a3,0x010a,0x010b,0x1e0a,0x00a7,
|
||||
0x1e80,0x00a9,0x1e82,0x1e0b,0x1ef2,0x00ad,0x00ae,0x0178,
|
||||
0x1e1e,0x1e1f,0x0120,0x0121,0x1e40,0x1e41,0x00b6,0x1e56,
|
||||
0x1e81,0x1e57,0x1e83,0x1e60,0x1ef3,0x1e84,0x1e85,0x1e61,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x0174,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x1e6a,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x0176,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x0175,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x1e6b,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x0177,0x00ff
|
||||
};
|
||||
|
||||
|
||||
/* Latin-9 a.k.a. Latin-0 (Euro) */
|
||||
static const unsigned short iso8859_15tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x20ac,0x00a5,0x0160,0x00a7,
|
||||
0x0161,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x017d,0x00b5,0x00b6,0x00b7,
|
||||
0x017e,0x00b9,0x00ba,0x00bb,0x0152,0x0153,0x0178,0x00bf,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x00f0,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x00ff
|
||||
};
|
||||
|
||||
|
||||
/* Latin-10 (Balkan) */
|
||||
|
||||
static const unsigned short iso8859_16tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
0x00a0,0x0104,0x0105,0x0141,0x20ac,0x201e,0x0160,0x00a7,
|
||||
0x0161,0x00a9,0x0218,0x00ab,0x0179,0x00ad,0x017a,0x017b,
|
||||
0x00b0,0x00b1,0x010c,0x0142,0x017d,0x201d,0x00b6,0x00b7,
|
||||
0x017e,0x010d,0x0219,0x00bb,0x0152,0x0153,0x0178,0x017c,
|
||||
0x00c0,0x00c1,0x00c2,0x0102,0x00c4,0x0106,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x0110,0x0143,0x00d2,0x00d3,0x00d4,0x0150,0x00d6,0x015a,
|
||||
0x0170,0x00d9,0x00da,0x00db,0x00dc,0x0118,0x021a,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x0103,0x00e4,0x0107,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x0111,0x0144,0x00f2,0x00f3,0x00f4,0x0151,0x00f6,0x015b,
|
||||
0x0171,0x00f9,0x00fa,0x00fb,0x00fc,0x0119,0x021b,0x00ff
|
||||
};
|
||||
1092
src/charset/jis_0208.c
Normal file
1092
src/charset/jis_0208.c
Normal file
File diff suppressed because it is too large
Load Diff
962
src/charset/jis_0212.c
Normal file
962
src/charset/jis_0212.c
Normal file
@@ -0,0 +1,962 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: JIS X0212 conversion table
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 4 August 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* JIS X0212 is the supplemental industrial standard of Japan. */
|
||||
|
||||
#define BASE_JIS0212_KU 0x22
|
||||
#define BASE_JIS0212_TEN 0x21
|
||||
#define MAX_JIS0212_KU 76
|
||||
#define MAX_JIS0212_TEN 94
|
||||
|
||||
|
||||
#define JIS0212TOUNICODE(c,c1,ku,ten) \
|
||||
((((ku = (c & 0x7f) - BASE_JIS0212_KU) < MAX_JIS0212_KU) && \
|
||||
((ten = (c1 & 0x7f) - BASE_JIS0212_TEN) < MAX_JIS0212_TEN)) ? \
|
||||
jis0212tab[ku][ten] : UBOGON)
|
||||
|
||||
|
||||
static const unsigned short jis0212tab[MAX_JIS0212_KU][MAX_JIS0212_TEN] = {
|
||||
{ /* ku 02 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,0x02d8,0x02c7,0x00b8,0x02d9,0x02dd,0x00af,
|
||||
0x02db,0x02da,0x007e,0x0384,0x0385,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,0x00a1,0x00a6,0x00bf,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,0x00ba,0x00aa,0x00a9,0x00ae,0x2122,0x00a4,
|
||||
0x2116,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 03 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 04 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 05 */
|
||||
/* Note: ku/ten codepoints 05/87 - 05/90 are proposed for addition to
|
||||
* JIS X 0212; I don't know if they've been formally accepted yet.
|
||||
* They represent katakana VA, VI, VE, and VO, and are in the BMP but
|
||||
* not in Unicode's JIS conversion tables. They're useful enough that
|
||||
* I decided to put them here.
|
||||
*/
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,0x30f7,0x30f8,0x30f9,0x30fa,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 06 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,0x0386,0x0388,0x0389,0x038a,0x03aa,UBOGON,
|
||||
0x038c,UBOGON,0x038e,0x03ab,UBOGON,0x038f,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x03ac,0x03ad,0x03ae,0x03af,0x03ca,0x0390,0x03cc,0x03c2,0x03cd,0x03cb,
|
||||
0x03b0,0x03ce,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 07 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,0x0408,
|
||||
0x0409,0x040a,0x040b,0x040c,0x040e,0x040f,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,0x0458,0x0459,0x045a,
|
||||
0x045b,0x045c,0x045e,0x045f
|
||||
},
|
||||
{ /* ku 08 */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 09 */
|
||||
0x00c6,0x0110,UBOGON,0x0126,UBOGON,0x0132,UBOGON,0x0141,0x013f,UBOGON,
|
||||
0x014a,0x00d8,0x0152,UBOGON,0x0166,0x00de,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,0x00e6,0x0111,0x00f0,0x0127,0x0131,0x0133,0x0138,0x0142,
|
||||
0x0140,0x0149,0x014b,0x00f8,0x0153,0x00df,0x0167,0x00fe,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0a */
|
||||
0x00c1,0x00c0,0x00c4,0x00c2,0x0102,0x01cd,0x0100,0x0104,0x00c5,0x00c3,
|
||||
0x0106,0x0108,0x010c,0x00c7,0x010a,0x010e,0x00c9,0x00c8,0x00cb,0x00ca,
|
||||
0x011a,0x0116,0x0112,0x0118,UBOGON,0x011c,0x011e,0x0122,0x0120,0x0124,
|
||||
0x00cd,0x00cc,0x00cf,0x00ce,0x01cf,0x0130,0x012a,0x012e,0x0128,0x0134,
|
||||
0x0136,0x0139,0x013d,0x013b,0x0143,0x0147,0x0145,0x00d1,0x00d3,0x00d2,
|
||||
0x00d6,0x00d4,0x01d1,0x0150,0x014c,0x00d5,0x0154,0x0158,0x0156,0x015a,
|
||||
0x015c,0x0160,0x015e,0x0164,0x0162,0x00da,0x00d9,0x00dc,0x00db,0x016c,
|
||||
0x01d3,0x0170,0x016a,0x0172,0x016e,0x0168,0x01d7,0x01db,0x01d9,0x01d5,
|
||||
0x0174,0x00dd,0x0178,0x0176,0x0179,0x017d,0x017b,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0b */
|
||||
0x00e1,0x00e0,0x00e4,0x00e2,0x0103,0x01ce,0x0101,0x0105,0x00e5,0x00e3,
|
||||
0x0107,0x0109,0x010d,0x00e7,0x010b,0x010f,0x00e9,0x00e8,0x00eb,0x00ea,
|
||||
0x011b,0x0117,0x0113,0x0119,0x01f5,0x011d,0x011f,UBOGON,0x0121,0x0125,
|
||||
0x00ed,0x00ec,0x00ef,0x00ee,0x01d0,UBOGON,0x012b,0x012f,0x0129,0x0135,
|
||||
0x0137,0x013a,0x013e,0x013c,0x0144,0x0148,0x0146,0x00f1,0x00f3,0x00f2,
|
||||
0x00f6,0x00f4,0x01d2,0x0151,0x014d,0x00f5,0x0155,0x0159,0x0157,0x015b,
|
||||
0x015d,0x0161,0x015f,0x0165,0x0163,0x00fa,0x00f9,0x00fc,0x00fb,0x016d,
|
||||
0x01d4,0x0171,0x016b,0x0173,0x016f,0x0169,0x01d8,0x01dc,0x01da,0x01d6,
|
||||
0x0175,0x00fd,0x00ff,0x0177,0x017a,0x017e,0x017c,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0c */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0d */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0e */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 0f */
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
},
|
||||
{ /* ku 10 */
|
||||
0x4e02,0x4e04,0x4e05,0x4e0c,0x4e12,0x4e1f,0x4e23,0x4e24,0x4e28,0x4e2b,
|
||||
0x4e2e,0x4e2f,0x4e30,0x4e35,0x4e40,0x4e41,0x4e44,0x4e47,0x4e51,0x4e5a,
|
||||
0x4e5c,0x4e63,0x4e68,0x4e69,0x4e74,0x4e75,0x4e79,0x4e7f,0x4e8d,0x4e96,
|
||||
0x4e97,0x4e9d,0x4eaf,0x4eb9,0x4ec3,0x4ed0,0x4eda,0x4edb,0x4ee0,0x4ee1,
|
||||
0x4ee2,0x4ee8,0x4eef,0x4ef1,0x4ef3,0x4ef5,0x4efd,0x4efe,0x4eff,0x4f00,
|
||||
0x4f02,0x4f03,0x4f08,0x4f0b,0x4f0c,0x4f12,0x4f15,0x4f16,0x4f17,0x4f19,
|
||||
0x4f2e,0x4f31,0x4f60,0x4f33,0x4f35,0x4f37,0x4f39,0x4f3b,0x4f3e,0x4f40,
|
||||
0x4f42,0x4f48,0x4f49,0x4f4b,0x4f4c,0x4f52,0x4f54,0x4f56,0x4f58,0x4f5f,
|
||||
0x4f63,0x4f6a,0x4f6c,0x4f6e,0x4f71,0x4f77,0x4f78,0x4f79,0x4f7a,0x4f7d,
|
||||
0x4f7e,0x4f81,0x4f82,0x4f84
|
||||
},
|
||||
{ /* ku 11 */
|
||||
0x4f85,0x4f89,0x4f8a,0x4f8c,0x4f8e,0x4f90,0x4f92,0x4f93,0x4f94,0x4f97,
|
||||
0x4f99,0x4f9a,0x4f9e,0x4f9f,0x4fb2,0x4fb7,0x4fb9,0x4fbb,0x4fbc,0x4fbd,
|
||||
0x4fbe,0x4fc0,0x4fc1,0x4fc5,0x4fc6,0x4fc8,0x4fc9,0x4fcb,0x4fcc,0x4fcd,
|
||||
0x4fcf,0x4fd2,0x4fdc,0x4fe0,0x4fe2,0x4ff0,0x4ff2,0x4ffc,0x4ffd,0x4fff,
|
||||
0x5000,0x5001,0x5004,0x5007,0x500a,0x500c,0x500e,0x5010,0x5013,0x5017,
|
||||
0x5018,0x501b,0x501c,0x501d,0x501e,0x5022,0x5027,0x502e,0x5030,0x5032,
|
||||
0x5033,0x5035,0x5040,0x5041,0x5042,0x5045,0x5046,0x504a,0x504c,0x504e,
|
||||
0x5051,0x5052,0x5053,0x5057,0x5059,0x505f,0x5060,0x5062,0x5063,0x5066,
|
||||
0x5067,0x506a,0x506d,0x5070,0x5071,0x503b,0x5081,0x5083,0x5084,0x5086,
|
||||
0x508a,0x508e,0x508f,0x5090
|
||||
},
|
||||
{ /* ku 12 */
|
||||
0x5092,0x5093,0x5094,0x5096,0x509b,0x509c,0x509e,0x509f,0x50a0,0x50a1,
|
||||
0x50a2,0x50aa,0x50af,0x50b0,0x50b9,0x50ba,0x50bd,0x50c0,0x50c3,0x50c4,
|
||||
0x50c7,0x50cc,0x50ce,0x50d0,0x50d3,0x50d4,0x50d8,0x50dc,0x50dd,0x50df,
|
||||
0x50e2,0x50e4,0x50e6,0x50e8,0x50e9,0x50ef,0x50f1,0x50f6,0x50fa,0x50fe,
|
||||
0x5103,0x5106,0x5107,0x5108,0x510b,0x510c,0x510d,0x510e,0x50f2,0x5110,
|
||||
0x5117,0x5119,0x511b,0x511c,0x511d,0x511e,0x5123,0x5127,0x5128,0x512c,
|
||||
0x512d,0x512f,0x5131,0x5133,0x5134,0x5135,0x5138,0x5139,0x5142,0x514a,
|
||||
0x514f,0x5153,0x5155,0x5157,0x5158,0x515f,0x5164,0x5166,0x517e,0x5183,
|
||||
0x5184,0x518b,0x518e,0x5198,0x519d,0x51a1,0x51a3,0x51ad,0x51b8,0x51ba,
|
||||
0x51bc,0x51be,0x51bf,0x51c2
|
||||
},
|
||||
{ /* ku 13 */
|
||||
0x51c8,0x51cf,0x51d1,0x51d2,0x51d3,0x51d5,0x51d8,0x51de,0x51e2,0x51e5,
|
||||
0x51ee,0x51f2,0x51f3,0x51f4,0x51f7,0x5201,0x5202,0x5205,0x5212,0x5213,
|
||||
0x5215,0x5216,0x5218,0x5222,0x5228,0x5231,0x5232,0x5235,0x523c,0x5245,
|
||||
0x5249,0x5255,0x5257,0x5258,0x525a,0x525c,0x525f,0x5260,0x5261,0x5266,
|
||||
0x526e,0x5277,0x5278,0x5279,0x5280,0x5282,0x5285,0x528a,0x528c,0x5293,
|
||||
0x5295,0x5296,0x5297,0x5298,0x529a,0x529c,0x52a4,0x52a5,0x52a6,0x52a7,
|
||||
0x52af,0x52b0,0x52b6,0x52b7,0x52b8,0x52ba,0x52bb,0x52bd,0x52c0,0x52c4,
|
||||
0x52c6,0x52c8,0x52cc,0x52cf,0x52d1,0x52d4,0x52d6,0x52db,0x52dc,0x52e1,
|
||||
0x52e5,0x52e8,0x52e9,0x52ea,0x52ec,0x52f0,0x52f1,0x52f4,0x52f6,0x52f7,
|
||||
0x5300,0x5303,0x530a,0x530b
|
||||
},
|
||||
{ /* ku 14 */
|
||||
0x530c,0x5311,0x5313,0x5318,0x531b,0x531c,0x531e,0x531f,0x5325,0x5327,
|
||||
0x5328,0x5329,0x532b,0x532c,0x532d,0x5330,0x5332,0x5335,0x533c,0x533d,
|
||||
0x533e,0x5342,0x534c,0x534b,0x5359,0x535b,0x5361,0x5363,0x5365,0x536c,
|
||||
0x536d,0x5372,0x5379,0x537e,0x5383,0x5387,0x5388,0x538e,0x5393,0x5394,
|
||||
0x5399,0x539d,0x53a1,0x53a4,0x53aa,0x53ab,0x53af,0x53b2,0x53b4,0x53b5,
|
||||
0x53b7,0x53b8,0x53ba,0x53bd,0x53c0,0x53c5,0x53cf,0x53d2,0x53d3,0x53d5,
|
||||
0x53da,0x53dd,0x53de,0x53e0,0x53e6,0x53e7,0x53f5,0x5402,0x5413,0x541a,
|
||||
0x5421,0x5427,0x5428,0x542a,0x542f,0x5431,0x5434,0x5435,0x5443,0x5444,
|
||||
0x5447,0x544d,0x544f,0x545e,0x5462,0x5464,0x5466,0x5467,0x5469,0x546b,
|
||||
0x546d,0x546e,0x5474,0x547f
|
||||
},
|
||||
{ /* ku 15 */
|
||||
0x5481,0x5483,0x5485,0x5488,0x5489,0x548d,0x5491,0x5495,0x5496,0x549c,
|
||||
0x549f,0x54a1,0x54a6,0x54a7,0x54a9,0x54aa,0x54ad,0x54ae,0x54b1,0x54b7,
|
||||
0x54b9,0x54ba,0x54bb,0x54bf,0x54c6,0x54ca,0x54cd,0x54ce,0x54e0,0x54ea,
|
||||
0x54ec,0x54ef,0x54f6,0x54fc,0x54fe,0x54ff,0x5500,0x5501,0x5505,0x5508,
|
||||
0x5509,0x550c,0x550d,0x550e,0x5515,0x552a,0x552b,0x5532,0x5535,0x5536,
|
||||
0x553b,0x553c,0x553d,0x5541,0x5547,0x5549,0x554a,0x554d,0x5550,0x5551,
|
||||
0x5558,0x555a,0x555b,0x555e,0x5560,0x5561,0x5564,0x5566,0x557f,0x5581,
|
||||
0x5582,0x5586,0x5588,0x558e,0x558f,0x5591,0x5592,0x5593,0x5594,0x5597,
|
||||
0x55a3,0x55a4,0x55ad,0x55b2,0x55bf,0x55c1,0x55c3,0x55c6,0x55c9,0x55cb,
|
||||
0x55cc,0x55ce,0x55d1,0x55d2
|
||||
},
|
||||
{ /* ku 16 */
|
||||
0x55d3,0x55d7,0x55d8,0x55db,0x55de,0x55e2,0x55e9,0x55f6,0x55ff,0x5605,
|
||||
0x5608,0x560a,0x560d,0x560e,0x560f,0x5610,0x5611,0x5612,0x5619,0x562c,
|
||||
0x5630,0x5633,0x5635,0x5637,0x5639,0x563b,0x563c,0x563d,0x563f,0x5640,
|
||||
0x5641,0x5643,0x5644,0x5646,0x5649,0x564b,0x564d,0x564f,0x5654,0x565e,
|
||||
0x5660,0x5661,0x5662,0x5663,0x5666,0x5669,0x566d,0x566f,0x5671,0x5672,
|
||||
0x5675,0x5684,0x5685,0x5688,0x568b,0x568c,0x5695,0x5699,0x569a,0x569d,
|
||||
0x569e,0x569f,0x56a6,0x56a7,0x56a8,0x56a9,0x56ab,0x56ac,0x56ad,0x56b1,
|
||||
0x56b3,0x56b7,0x56be,0x56c5,0x56c9,0x56ca,0x56cb,0x56cf,0x56d0,0x56cc,
|
||||
0x56cd,0x56d9,0x56dc,0x56dd,0x56df,0x56e1,0x56e4,0x56e5,0x56e6,0x56e7,
|
||||
0x56e8,0x56f1,0x56eb,0x56ed
|
||||
},
|
||||
{ /* ku 17 */
|
||||
0x56f6,0x56f7,0x5701,0x5702,0x5707,0x570a,0x570c,0x5711,0x5715,0x571a,
|
||||
0x571b,0x571d,0x5720,0x5722,0x5723,0x5724,0x5725,0x5729,0x572a,0x572c,
|
||||
0x572e,0x572f,0x5733,0x5734,0x573d,0x573e,0x573f,0x5745,0x5746,0x574c,
|
||||
0x574d,0x5752,0x5762,0x5765,0x5767,0x5768,0x576b,0x576d,0x576e,0x576f,
|
||||
0x5770,0x5771,0x5773,0x5774,0x5775,0x5777,0x5779,0x577a,0x577b,0x577c,
|
||||
0x577e,0x5781,0x5783,0x578c,0x5794,0x5797,0x5799,0x579a,0x579c,0x579d,
|
||||
0x579e,0x579f,0x57a1,0x5795,0x57a7,0x57a8,0x57a9,0x57ac,0x57b8,0x57bd,
|
||||
0x57c7,0x57c8,0x57cc,0x57cf,0x57d5,0x57dd,0x57de,0x57e4,0x57e6,0x57e7,
|
||||
0x57e9,0x57ed,0x57f0,0x57f5,0x57f6,0x57f8,0x57fd,0x57fe,0x57ff,0x5803,
|
||||
0x5804,0x5808,0x5809,0x57e1
|
||||
},
|
||||
{ /* ku 18 */
|
||||
0x580c,0x580d,0x581b,0x581e,0x581f,0x5820,0x5826,0x5827,0x582d,0x5832,
|
||||
0x5839,0x583f,0x5849,0x584c,0x584d,0x584f,0x5850,0x5855,0x585f,0x5861,
|
||||
0x5864,0x5867,0x5868,0x5878,0x587c,0x587f,0x5880,0x5881,0x5887,0x5888,
|
||||
0x5889,0x588a,0x588c,0x588d,0x588f,0x5890,0x5894,0x5896,0x589d,0x58a0,
|
||||
0x58a1,0x58a2,0x58a6,0x58a9,0x58b1,0x58b2,0x58c4,0x58bc,0x58c2,0x58c8,
|
||||
0x58cd,0x58ce,0x58d0,0x58d2,0x58d4,0x58d6,0x58da,0x58dd,0x58e1,0x58e2,
|
||||
0x58e9,0x58f3,0x5905,0x5906,0x590b,0x590c,0x5912,0x5913,0x5914,0x8641,
|
||||
0x591d,0x5921,0x5923,0x5924,0x5928,0x592f,0x5930,0x5933,0x5935,0x5936,
|
||||
0x593f,0x5943,0x5946,0x5952,0x5953,0x5959,0x595b,0x595d,0x595e,0x595f,
|
||||
0x5961,0x5963,0x596b,0x596d
|
||||
},
|
||||
{ /* ku 19 */
|
||||
0x596f,0x5972,0x5975,0x5976,0x5979,0x597b,0x597c,0x598b,0x598c,0x598e,
|
||||
0x5992,0x5995,0x5997,0x599f,0x59a4,0x59a7,0x59ad,0x59ae,0x59af,0x59b0,
|
||||
0x59b3,0x59b7,0x59ba,0x59bc,0x59c1,0x59c3,0x59c4,0x59c8,0x59ca,0x59cd,
|
||||
0x59d2,0x59dd,0x59de,0x59df,0x59e3,0x59e4,0x59e7,0x59ee,0x59ef,0x59f1,
|
||||
0x59f2,0x59f4,0x59f7,0x5a00,0x5a04,0x5a0c,0x5a0d,0x5a0e,0x5a12,0x5a13,
|
||||
0x5a1e,0x5a23,0x5a24,0x5a27,0x5a28,0x5a2a,0x5a2d,0x5a30,0x5a44,0x5a45,
|
||||
0x5a47,0x5a48,0x5a4c,0x5a50,0x5a55,0x5a5e,0x5a63,0x5a65,0x5a67,0x5a6d,
|
||||
0x5a77,0x5a7a,0x5a7b,0x5a7e,0x5a8b,0x5a90,0x5a93,0x5a96,0x5a99,0x5a9c,
|
||||
0x5a9e,0x5a9f,0x5aa0,0x5aa2,0x5aa7,0x5aac,0x5ab1,0x5ab2,0x5ab3,0x5ab5,
|
||||
0x5ab8,0x5aba,0x5abb,0x5abf
|
||||
},
|
||||
{ /* ku 1a */
|
||||
0x5ac4,0x5ac6,0x5ac8,0x5acf,0x5ada,0x5adc,0x5ae0,0x5ae5,0x5aea,0x5aee,
|
||||
0x5af5,0x5af6,0x5afd,0x5b00,0x5b01,0x5b08,0x5b17,0x5b34,0x5b19,0x5b1b,
|
||||
0x5b1d,0x5b21,0x5b25,0x5b2d,0x5b38,0x5b41,0x5b4b,0x5b4c,0x5b52,0x5b56,
|
||||
0x5b5e,0x5b68,0x5b6e,0x5b6f,0x5b7c,0x5b7d,0x5b7e,0x5b7f,0x5b81,0x5b84,
|
||||
0x5b86,0x5b8a,0x5b8e,0x5b90,0x5b91,0x5b93,0x5b94,0x5b96,0x5ba8,0x5ba9,
|
||||
0x5bac,0x5bad,0x5baf,0x5bb1,0x5bb2,0x5bb7,0x5bba,0x5bbc,0x5bc0,0x5bc1,
|
||||
0x5bcd,0x5bcf,0x5bd6,0x5bd7,0x5bd8,0x5bd9,0x5bda,0x5be0,0x5bef,0x5bf1,
|
||||
0x5bf4,0x5bfd,0x5c0c,0x5c17,0x5c1e,0x5c1f,0x5c23,0x5c26,0x5c29,0x5c2b,
|
||||
0x5c2c,0x5c2e,0x5c30,0x5c32,0x5c35,0x5c36,0x5c59,0x5c5a,0x5c5c,0x5c62,
|
||||
0x5c63,0x5c67,0x5c68,0x5c69
|
||||
},
|
||||
{ /* ku 1b */
|
||||
0x5c6d,0x5c70,0x5c74,0x5c75,0x5c7a,0x5c7b,0x5c7c,0x5c7d,0x5c87,0x5c88,
|
||||
0x5c8a,0x5c8f,0x5c92,0x5c9d,0x5c9f,0x5ca0,0x5ca2,0x5ca3,0x5ca6,0x5caa,
|
||||
0x5cb2,0x5cb4,0x5cb5,0x5cba,0x5cc9,0x5ccb,0x5cd2,0x5cdd,0x5cd7,0x5cee,
|
||||
0x5cf1,0x5cf2,0x5cf4,0x5d01,0x5d06,0x5d0d,0x5d12,0x5d2b,0x5d23,0x5d24,
|
||||
0x5d26,0x5d27,0x5d31,0x5d34,0x5d39,0x5d3d,0x5d3f,0x5d42,0x5d43,0x5d46,
|
||||
0x5d48,0x5d55,0x5d51,0x5d59,0x5d4a,0x5d5f,0x5d60,0x5d61,0x5d62,0x5d64,
|
||||
0x5d6a,0x5d6d,0x5d70,0x5d79,0x5d7a,0x5d7e,0x5d7f,0x5d81,0x5d83,0x5d88,
|
||||
0x5d8a,0x5d92,0x5d93,0x5d94,0x5d95,0x5d99,0x5d9b,0x5d9f,0x5da0,0x5da7,
|
||||
0x5dab,0x5db0,0x5db4,0x5db8,0x5db9,0x5dc3,0x5dc7,0x5dcb,0x5dd0,0x5dce,
|
||||
0x5dd8,0x5dd9,0x5de0,0x5de4
|
||||
},
|
||||
{ /* ku 1c */
|
||||
0x5de9,0x5df8,0x5df9,0x5e00,0x5e07,0x5e0d,0x5e12,0x5e14,0x5e15,0x5e18,
|
||||
0x5e1f,0x5e20,0x5e2e,0x5e28,0x5e32,0x5e35,0x5e3e,0x5e4b,0x5e50,0x5e49,
|
||||
0x5e51,0x5e56,0x5e58,0x5e5b,0x5e5c,0x5e5e,0x5e68,0x5e6a,0x5e6b,0x5e6c,
|
||||
0x5e6d,0x5e6e,0x5e70,0x5e80,0x5e8b,0x5e8e,0x5ea2,0x5ea4,0x5ea5,0x5ea8,
|
||||
0x5eaa,0x5eac,0x5eb1,0x5eb3,0x5ebd,0x5ebe,0x5ebf,0x5ec6,0x5ecc,0x5ecb,
|
||||
0x5ece,0x5ed1,0x5ed2,0x5ed4,0x5ed5,0x5edc,0x5ede,0x5ee5,0x5eeb,0x5f02,
|
||||
0x5f06,0x5f07,0x5f08,0x5f0e,0x5f19,0x5f1c,0x5f1d,0x5f21,0x5f22,0x5f23,
|
||||
0x5f24,0x5f28,0x5f2b,0x5f2c,0x5f2e,0x5f30,0x5f34,0x5f36,0x5f3b,0x5f3d,
|
||||
0x5f3f,0x5f40,0x5f44,0x5f45,0x5f47,0x5f4d,0x5f50,0x5f54,0x5f58,0x5f5b,
|
||||
0x5f60,0x5f63,0x5f64,0x5f67
|
||||
},
|
||||
{ /* ku 1d */
|
||||
0x5f6f,0x5f72,0x5f74,0x5f75,0x5f78,0x5f7a,0x5f7d,0x5f7e,0x5f89,0x5f8d,
|
||||
0x5f8f,0x5f96,0x5f9c,0x5f9d,0x5fa2,0x5fa7,0x5fab,0x5fa4,0x5fac,0x5faf,
|
||||
0x5fb0,0x5fb1,0x5fb8,0x5fc4,0x5fc7,0x5fc8,0x5fc9,0x5fcb,0x5fd0,0x5fd1,
|
||||
0x5fd2,0x5fd3,0x5fd4,0x5fde,0x5fe1,0x5fe2,0x5fe8,0x5fe9,0x5fea,0x5fec,
|
||||
0x5fed,0x5fee,0x5fef,0x5ff2,0x5ff3,0x5ff6,0x5ffa,0x5ffc,0x6007,0x600a,
|
||||
0x600d,0x6013,0x6014,0x6017,0x6018,0x601a,0x601f,0x6024,0x602d,0x6033,
|
||||
0x6035,0x6040,0x6047,0x6048,0x6049,0x604c,0x6051,0x6054,0x6056,0x6057,
|
||||
0x605d,0x6061,0x6067,0x6071,0x607e,0x607f,0x6082,0x6086,0x6088,0x608a,
|
||||
0x608e,0x6091,0x6093,0x6095,0x6098,0x609d,0x609e,0x60a2,0x60a4,0x60a5,
|
||||
0x60a8,0x60b0,0x60b1,0x60b7
|
||||
},
|
||||
{ /* ku 1e */
|
||||
0x60bb,0x60be,0x60c2,0x60c4,0x60c8,0x60c9,0x60ca,0x60cb,0x60ce,0x60cf,
|
||||
0x60d4,0x60d5,0x60d9,0x60db,0x60dd,0x60de,0x60e2,0x60e5,0x60f2,0x60f5,
|
||||
0x60f8,0x60fc,0x60fd,0x6102,0x6107,0x610a,0x610c,0x6110,0x6111,0x6112,
|
||||
0x6113,0x6114,0x6116,0x6117,0x6119,0x611c,0x611e,0x6122,0x612a,0x612b,
|
||||
0x6130,0x6131,0x6135,0x6136,0x6137,0x6139,0x6141,0x6145,0x6146,0x6149,
|
||||
0x615e,0x6160,0x616c,0x6172,0x6178,0x617b,0x617c,0x617f,0x6180,0x6181,
|
||||
0x6183,0x6184,0x618b,0x618d,0x6192,0x6193,0x6197,0x6198,0x619c,0x619d,
|
||||
0x619f,0x61a0,0x61a5,0x61a8,0x61aa,0x61ad,0x61b8,0x61b9,0x61bc,0x61c0,
|
||||
0x61c1,0x61c2,0x61ce,0x61cf,0x61d5,0x61dc,0x61dd,0x61de,0x61df,0x61e1,
|
||||
0x61e2,0x61e7,0x61e9,0x61e5
|
||||
},
|
||||
{ /* ku 1f */
|
||||
0x61ec,0x61ed,0x61ef,0x6201,0x6203,0x6204,0x6207,0x6213,0x6215,0x621c,
|
||||
0x6220,0x6222,0x6223,0x6227,0x6229,0x622b,0x6239,0x623d,0x6242,0x6243,
|
||||
0x6244,0x6246,0x624c,0x6250,0x6251,0x6252,0x6254,0x6256,0x625a,0x625c,
|
||||
0x6264,0x626d,0x626f,0x6273,0x627a,0x627d,0x628d,0x628e,0x628f,0x6290,
|
||||
0x62a6,0x62a8,0x62b3,0x62b6,0x62b7,0x62ba,0x62be,0x62bf,0x62c4,0x62ce,
|
||||
0x62d5,0x62d6,0x62da,0x62ea,0x62f2,0x62f4,0x62fc,0x62fd,0x6303,0x6304,
|
||||
0x630a,0x630b,0x630d,0x6310,0x6313,0x6316,0x6318,0x6329,0x632a,0x632d,
|
||||
0x6335,0x6336,0x6339,0x633c,0x6341,0x6342,0x6343,0x6344,0x6346,0x634a,
|
||||
0x634b,0x634e,0x6352,0x6353,0x6354,0x6358,0x635b,0x6365,0x6366,0x636c,
|
||||
0x636d,0x6371,0x6374,0x6375
|
||||
},
|
||||
{ /* ku 20 */
|
||||
0x6378,0x637c,0x637d,0x637f,0x6382,0x6384,0x6387,0x638a,0x6390,0x6394,
|
||||
0x6395,0x6399,0x639a,0x639e,0x63a4,0x63a6,0x63ad,0x63ae,0x63af,0x63bd,
|
||||
0x63c1,0x63c5,0x63c8,0x63ce,0x63d1,0x63d3,0x63d4,0x63d5,0x63dc,0x63e0,
|
||||
0x63e5,0x63ea,0x63ec,0x63f2,0x63f3,0x63f5,0x63f8,0x63f9,0x6409,0x640a,
|
||||
0x6410,0x6412,0x6414,0x6418,0x641e,0x6420,0x6422,0x6424,0x6425,0x6429,
|
||||
0x642a,0x642f,0x6430,0x6435,0x643d,0x643f,0x644b,0x644f,0x6451,0x6452,
|
||||
0x6453,0x6454,0x645a,0x645b,0x645c,0x645d,0x645f,0x6460,0x6461,0x6463,
|
||||
0x646d,0x6473,0x6474,0x647b,0x647d,0x6485,0x6487,0x648f,0x6490,0x6491,
|
||||
0x6498,0x6499,0x649b,0x649d,0x649f,0x64a1,0x64a3,0x64a6,0x64a8,0x64ac,
|
||||
0x64b3,0x64bd,0x64be,0x64bf
|
||||
},
|
||||
{ /* ku 21 */
|
||||
0x64c4,0x64c9,0x64ca,0x64cb,0x64cc,0x64ce,0x64d0,0x64d1,0x64d5,0x64d7,
|
||||
0x64e4,0x64e5,0x64e9,0x64ea,0x64ed,0x64f0,0x64f5,0x64f7,0x64fb,0x64ff,
|
||||
0x6501,0x6504,0x6508,0x6509,0x650a,0x650f,0x6513,0x6514,0x6516,0x6519,
|
||||
0x651b,0x651e,0x651f,0x6522,0x6526,0x6529,0x652e,0x6531,0x653a,0x653c,
|
||||
0x653d,0x6543,0x6547,0x6549,0x6550,0x6552,0x6554,0x655f,0x6560,0x6567,
|
||||
0x656b,0x657a,0x657d,0x6581,0x6585,0x658a,0x6592,0x6595,0x6598,0x659d,
|
||||
0x65a0,0x65a3,0x65a6,0x65ae,0x65b2,0x65b3,0x65b4,0x65bf,0x65c2,0x65c8,
|
||||
0x65c9,0x65ce,0x65d0,0x65d4,0x65d6,0x65d8,0x65df,0x65f0,0x65f2,0x65f4,
|
||||
0x65f5,0x65f9,0x65fe,0x65ff,0x6600,0x6604,0x6608,0x6609,0x660d,0x6611,
|
||||
0x6612,0x6615,0x6616,0x661d
|
||||
},
|
||||
{ /* ku 22 */
|
||||
0x661e,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662a,0x662b,0x662c,
|
||||
0x662e,0x6630,0x6631,0x6633,0x6639,0x6637,0x6640,0x6645,0x6646,0x664a,
|
||||
0x664c,0x6651,0x664e,0x6657,0x6658,0x6659,0x665b,0x665c,0x6660,0x6661,
|
||||
0x66fb,0x666a,0x666b,0x666c,0x667e,0x6673,0x6675,0x667f,0x6677,0x6678,
|
||||
0x6679,0x667b,0x6680,0x667c,0x668b,0x668c,0x668d,0x6690,0x6692,0x6699,
|
||||
0x669a,0x669b,0x669c,0x669f,0x66a0,0x66a4,0x66ad,0x66b1,0x66b2,0x66b5,
|
||||
0x66bb,0x66bf,0x66c0,0x66c2,0x66c3,0x66c8,0x66cc,0x66ce,0x66cf,0x66d4,
|
||||
0x66db,0x66df,0x66e8,0x66eb,0x66ec,0x66ee,0x66fa,0x6705,0x6707,0x670e,
|
||||
0x6713,0x6719,0x671c,0x6720,0x6722,0x6733,0x673e,0x6745,0x6747,0x6748,
|
||||
0x674c,0x6754,0x6755,0x675d
|
||||
},
|
||||
{ /* ku 23 */
|
||||
0x6766,0x676c,0x676e,0x6774,0x6776,0x677b,0x6781,0x6784,0x678e,0x678f,
|
||||
0x6791,0x6793,0x6796,0x6798,0x6799,0x679b,0x67b0,0x67b1,0x67b2,0x67b5,
|
||||
0x67bb,0x67bc,0x67bd,0x67f9,0x67c0,0x67c2,0x67c3,0x67c5,0x67c8,0x67c9,
|
||||
0x67d2,0x67d7,0x67d9,0x67dc,0x67e1,0x67e6,0x67f0,0x67f2,0x67f6,0x67f7,
|
||||
0x6852,0x6814,0x6819,0x681d,0x681f,0x6828,0x6827,0x682c,0x682d,0x682f,
|
||||
0x6830,0x6831,0x6833,0x683b,0x683f,0x6844,0x6845,0x684a,0x684c,0x6855,
|
||||
0x6857,0x6858,0x685b,0x686b,0x686e,0x686f,0x6870,0x6871,0x6872,0x6875,
|
||||
0x6879,0x687a,0x687b,0x687c,0x6882,0x6884,0x6886,0x6888,0x6896,0x6898,
|
||||
0x689a,0x689c,0x68a1,0x68a3,0x68a5,0x68a9,0x68aa,0x68ae,0x68b2,0x68bb,
|
||||
0x68c5,0x68c8,0x68cc,0x68cf
|
||||
},
|
||||
{ /* ku 24 */
|
||||
0x68d0,0x68d1,0x68d3,0x68d6,0x68d9,0x68dc,0x68dd,0x68e5,0x68e8,0x68ea,
|
||||
0x68eb,0x68ec,0x68ed,0x68f0,0x68f1,0x68f5,0x68f6,0x68fb,0x68fc,0x68fd,
|
||||
0x6906,0x6909,0x690a,0x6910,0x6911,0x6913,0x6916,0x6917,0x6931,0x6933,
|
||||
0x6935,0x6938,0x693b,0x6942,0x6945,0x6949,0x694e,0x6957,0x695b,0x6963,
|
||||
0x6964,0x6965,0x6966,0x6968,0x6969,0x696c,0x6970,0x6971,0x6972,0x697a,
|
||||
0x697b,0x697f,0x6980,0x698d,0x6992,0x6996,0x6998,0x69a1,0x69a5,0x69a6,
|
||||
0x69a8,0x69ab,0x69ad,0x69af,0x69b7,0x69b8,0x69ba,0x69bc,0x69c5,0x69c8,
|
||||
0x69d1,0x69d6,0x69d7,0x69e2,0x69e5,0x69ee,0x69ef,0x69f1,0x69f3,0x69f5,
|
||||
0x69fe,0x6a00,0x6a01,0x6a03,0x6a0f,0x6a11,0x6a15,0x6a1a,0x6a1d,0x6a20,
|
||||
0x6a24,0x6a28,0x6a30,0x6a32
|
||||
},
|
||||
{ /* ku 25 */
|
||||
0x6a34,0x6a37,0x6a3b,0x6a3e,0x6a3f,0x6a45,0x6a46,0x6a49,0x6a4a,0x6a4e,
|
||||
0x6a50,0x6a51,0x6a52,0x6a55,0x6a56,0x6a5b,0x6a64,0x6a67,0x6a6a,0x6a71,
|
||||
0x6a73,0x6a7e,0x6a81,0x6a83,0x6a86,0x6a87,0x6a89,0x6a8b,0x6a91,0x6a9b,
|
||||
0x6a9d,0x6a9e,0x6a9f,0x6aa5,0x6aab,0x6aaf,0x6ab0,0x6ab1,0x6ab4,0x6abd,
|
||||
0x6abe,0x6abf,0x6ac6,0x6ac9,0x6ac8,0x6acc,0x6ad0,0x6ad4,0x6ad5,0x6ad6,
|
||||
0x6adc,0x6add,0x6ae4,0x6ae7,0x6aec,0x6af0,0x6af1,0x6af2,0x6afc,0x6afd,
|
||||
0x6b02,0x6b03,0x6b06,0x6b07,0x6b09,0x6b0f,0x6b10,0x6b11,0x6b17,0x6b1b,
|
||||
0x6b1e,0x6b24,0x6b28,0x6b2b,0x6b2c,0x6b2f,0x6b35,0x6b36,0x6b3b,0x6b3f,
|
||||
0x6b46,0x6b4a,0x6b4d,0x6b52,0x6b56,0x6b58,0x6b5d,0x6b60,0x6b67,0x6b6b,
|
||||
0x6b6e,0x6b70,0x6b75,0x6b7d
|
||||
},
|
||||
{ /* ku 26 */
|
||||
0x6b7e,0x6b82,0x6b85,0x6b97,0x6b9b,0x6b9f,0x6ba0,0x6ba2,0x6ba3,0x6ba8,
|
||||
0x6ba9,0x6bac,0x6bad,0x6bae,0x6bb0,0x6bb8,0x6bb9,0x6bbd,0x6bbe,0x6bc3,
|
||||
0x6bc4,0x6bc9,0x6bcc,0x6bd6,0x6bda,0x6be1,0x6be3,0x6be6,0x6be7,0x6bee,
|
||||
0x6bf1,0x6bf7,0x6bf9,0x6bff,0x6c02,0x6c04,0x6c05,0x6c09,0x6c0d,0x6c0e,
|
||||
0x6c10,0x6c12,0x6c19,0x6c1f,0x6c26,0x6c27,0x6c28,0x6c2c,0x6c2e,0x6c33,
|
||||
0x6c35,0x6c36,0x6c3a,0x6c3b,0x6c3f,0x6c4a,0x6c4b,0x6c4d,0x6c4f,0x6c52,
|
||||
0x6c54,0x6c59,0x6c5b,0x6c5c,0x6c6b,0x6c6d,0x6c6f,0x6c74,0x6c76,0x6c78,
|
||||
0x6c79,0x6c7b,0x6c85,0x6c86,0x6c87,0x6c89,0x6c94,0x6c95,0x6c97,0x6c98,
|
||||
0x6c9c,0x6c9f,0x6cb0,0x6cb2,0x6cb4,0x6cc2,0x6cc6,0x6ccd,0x6ccf,0x6cd0,
|
||||
0x6cd1,0x6cd2,0x6cd4,0x6cd6
|
||||
},
|
||||
{ /* ku 27 */
|
||||
0x6cda,0x6cdc,0x6ce0,0x6ce7,0x6ce9,0x6ceb,0x6cec,0x6cee,0x6cf2,0x6cf4,
|
||||
0x6d04,0x6d07,0x6d0a,0x6d0e,0x6d0f,0x6d11,0x6d13,0x6d1a,0x6d26,0x6d27,
|
||||
0x6d28,0x6c67,0x6d2e,0x6d2f,0x6d31,0x6d39,0x6d3c,0x6d3f,0x6d57,0x6d5e,
|
||||
0x6d5f,0x6d61,0x6d65,0x6d67,0x6d6f,0x6d70,0x6d7c,0x6d82,0x6d87,0x6d91,
|
||||
0x6d92,0x6d94,0x6d96,0x6d97,0x6d98,0x6daa,0x6dac,0x6db4,0x6db7,0x6db9,
|
||||
0x6dbd,0x6dbf,0x6dc4,0x6dc8,0x6dca,0x6dce,0x6dcf,0x6dd6,0x6ddb,0x6ddd,
|
||||
0x6ddf,0x6de0,0x6de2,0x6de5,0x6de9,0x6def,0x6df0,0x6df4,0x6df6,0x6dfc,
|
||||
0x6e00,0x6e04,0x6e1e,0x6e22,0x6e27,0x6e32,0x6e36,0x6e39,0x6e3b,0x6e3c,
|
||||
0x6e44,0x6e45,0x6e48,0x6e49,0x6e4b,0x6e4f,0x6e51,0x6e52,0x6e53,0x6e54,
|
||||
0x6e57,0x6e5c,0x6e5d,0x6e5e
|
||||
},
|
||||
{ /* ku 28 */
|
||||
0x6e62,0x6e63,0x6e68,0x6e73,0x6e7b,0x6e7d,0x6e8d,0x6e93,0x6e99,0x6ea0,
|
||||
0x6ea7,0x6ead,0x6eae,0x6eb1,0x6eb3,0x6ebb,0x6ebf,0x6ec0,0x6ec1,0x6ec3,
|
||||
0x6ec7,0x6ec8,0x6eca,0x6ecd,0x6ece,0x6ecf,0x6eeb,0x6eed,0x6eee,0x6ef9,
|
||||
0x6efb,0x6efd,0x6f04,0x6f08,0x6f0a,0x6f0c,0x6f0d,0x6f16,0x6f18,0x6f1a,
|
||||
0x6f1b,0x6f26,0x6f29,0x6f2a,0x6f2f,0x6f30,0x6f33,0x6f36,0x6f3b,0x6f3c,
|
||||
0x6f2d,0x6f4f,0x6f51,0x6f52,0x6f53,0x6f57,0x6f59,0x6f5a,0x6f5d,0x6f5e,
|
||||
0x6f61,0x6f62,0x6f68,0x6f6c,0x6f7d,0x6f7e,0x6f83,0x6f87,0x6f88,0x6f8b,
|
||||
0x6f8c,0x6f8d,0x6f90,0x6f92,0x6f93,0x6f94,0x6f96,0x6f9a,0x6f9f,0x6fa0,
|
||||
0x6fa5,0x6fa6,0x6fa7,0x6fa8,0x6fae,0x6faf,0x6fb0,0x6fb5,0x6fb6,0x6fbc,
|
||||
0x6fc5,0x6fc7,0x6fc8,0x6fca
|
||||
},
|
||||
{ /* ku 29 */
|
||||
0x6fda,0x6fde,0x6fe8,0x6fe9,0x6ff0,0x6ff5,0x6ff9,0x6ffc,0x6ffd,0x7000,
|
||||
0x7005,0x7006,0x7007,0x700d,0x7017,0x7020,0x7023,0x702f,0x7034,0x7037,
|
||||
0x7039,0x703c,0x7043,0x7044,0x7048,0x7049,0x704a,0x704b,0x7054,0x7055,
|
||||
0x705d,0x705e,0x704e,0x7064,0x7065,0x706c,0x706e,0x7075,0x7076,0x707e,
|
||||
0x7081,0x7085,0x7086,0x7094,0x7095,0x7096,0x7097,0x7098,0x709b,0x70a4,
|
||||
0x70ab,0x70b0,0x70b1,0x70b4,0x70b7,0x70ca,0x70d1,0x70d3,0x70d4,0x70d5,
|
||||
0x70d6,0x70d8,0x70dc,0x70e4,0x70fa,0x7103,0x7104,0x7105,0x7106,0x7107,
|
||||
0x710b,0x710c,0x710f,0x711e,0x7120,0x712b,0x712d,0x712f,0x7130,0x7131,
|
||||
0x7138,0x7141,0x7145,0x7146,0x7147,0x714a,0x714b,0x7150,0x7152,0x7157,
|
||||
0x715a,0x715c,0x715e,0x7160
|
||||
},
|
||||
{ /* ku 2a */
|
||||
0x7168,0x7179,0x7180,0x7185,0x7187,0x718c,0x7192,0x719a,0x719b,0x71a0,
|
||||
0x71a2,0x71af,0x71b0,0x71b2,0x71b3,0x71ba,0x71bf,0x71c0,0x71c1,0x71c4,
|
||||
0x71cb,0x71cc,0x71d3,0x71d6,0x71d9,0x71da,0x71dc,0x71f8,0x71fe,0x7200,
|
||||
0x7207,0x7208,0x7209,0x7213,0x7217,0x721a,0x721d,0x721f,0x7224,0x722b,
|
||||
0x722f,0x7234,0x7238,0x7239,0x7241,0x7242,0x7243,0x7245,0x724e,0x724f,
|
||||
0x7250,0x7253,0x7255,0x7256,0x725a,0x725c,0x725e,0x7260,0x7263,0x7268,
|
||||
0x726b,0x726e,0x726f,0x7271,0x7277,0x7278,0x727b,0x727c,0x727f,0x7284,
|
||||
0x7289,0x728d,0x728e,0x7293,0x729b,0x72a8,0x72ad,0x72ae,0x72b1,0x72b4,
|
||||
0x72be,0x72c1,0x72c7,0x72c9,0x72cc,0x72d5,0x72d6,0x72d8,0x72df,0x72e5,
|
||||
0x72f3,0x72f4,0x72fa,0x72fb
|
||||
},
|
||||
{ /* ku 2b */
|
||||
0x72fe,0x7302,0x7304,0x7305,0x7307,0x730b,0x730d,0x7312,0x7313,0x7318,
|
||||
0x7319,0x731e,0x7322,0x7324,0x7327,0x7328,0x732c,0x7331,0x7332,0x7335,
|
||||
0x733a,0x733b,0x733d,0x7343,0x734d,0x7350,0x7352,0x7356,0x7358,0x735d,
|
||||
0x735e,0x735f,0x7360,0x7366,0x7367,0x7369,0x736b,0x736c,0x736e,0x736f,
|
||||
0x7371,0x7377,0x7379,0x737c,0x7380,0x7381,0x7383,0x7385,0x7386,0x738e,
|
||||
0x7390,0x7393,0x7395,0x7397,0x7398,0x739c,0x739e,0x739f,0x73a0,0x73a2,
|
||||
0x73a5,0x73a6,0x73aa,0x73ab,0x73ad,0x73b5,0x73b7,0x73b9,0x73bc,0x73bd,
|
||||
0x73bf,0x73c5,0x73c6,0x73c9,0x73cb,0x73cc,0x73cf,0x73d2,0x73d3,0x73d6,
|
||||
0x73d9,0x73dd,0x73e1,0x73e3,0x73e6,0x73e7,0x73e9,0x73f4,0x73f5,0x73f7,
|
||||
0x73f9,0x73fa,0x73fb,0x73fd
|
||||
},
|
||||
{ /* ku 2c */
|
||||
0x73ff,0x7400,0x7401,0x7404,0x7407,0x740a,0x7411,0x741a,0x741b,0x7424,
|
||||
0x7426,0x7428,0x7429,0x742a,0x742b,0x742c,0x742d,0x742e,0x742f,0x7430,
|
||||
0x7431,0x7439,0x7440,0x7443,0x7444,0x7446,0x7447,0x744b,0x744d,0x7451,
|
||||
0x7452,0x7457,0x745d,0x7462,0x7466,0x7467,0x7468,0x746b,0x746d,0x746e,
|
||||
0x7471,0x7472,0x7480,0x7481,0x7485,0x7486,0x7487,0x7489,0x748f,0x7490,
|
||||
0x7491,0x7492,0x7498,0x7499,0x749a,0x749c,0x749f,0x74a0,0x74a1,0x74a3,
|
||||
0x74a6,0x74a8,0x74a9,0x74aa,0x74ab,0x74ae,0x74af,0x74b1,0x74b2,0x74b5,
|
||||
0x74b9,0x74bb,0x74bf,0x74c8,0x74c9,0x74cc,0x74d0,0x74d3,0x74d8,0x74da,
|
||||
0x74db,0x74de,0x74df,0x74e4,0x74e8,0x74ea,0x74eb,0x74ef,0x74f4,0x74fa,
|
||||
0x74fb,0x74fc,0x74ff,0x7506
|
||||
},
|
||||
{ /* ku 2d */
|
||||
0x7512,0x7516,0x7517,0x7520,0x7521,0x7524,0x7527,0x7529,0x752a,0x752f,
|
||||
0x7536,0x7539,0x753d,0x753e,0x753f,0x7540,0x7543,0x7547,0x7548,0x754e,
|
||||
0x7550,0x7552,0x7557,0x755e,0x755f,0x7561,0x756f,0x7571,0x7579,0x757a,
|
||||
0x757b,0x757c,0x757d,0x757e,0x7581,0x7585,0x7590,0x7592,0x7593,0x7595,
|
||||
0x7599,0x759c,0x75a2,0x75a4,0x75b4,0x75ba,0x75bf,0x75c0,0x75c1,0x75c4,
|
||||
0x75c6,0x75cc,0x75ce,0x75cf,0x75d7,0x75dc,0x75df,0x75e0,0x75e1,0x75e4,
|
||||
0x75e7,0x75ec,0x75ee,0x75ef,0x75f1,0x75f9,0x7600,0x7602,0x7603,0x7604,
|
||||
0x7607,0x7608,0x760a,0x760c,0x760f,0x7612,0x7613,0x7615,0x7616,0x7619,
|
||||
0x761b,0x761c,0x761d,0x761e,0x7623,0x7625,0x7626,0x7629,0x762d,0x7632,
|
||||
0x7633,0x7635,0x7638,0x7639
|
||||
},
|
||||
{ /* ku 2e */
|
||||
0x763a,0x763c,0x764a,0x7640,0x7641,0x7643,0x7644,0x7645,0x7649,0x764b,
|
||||
0x7655,0x7659,0x765f,0x7664,0x7665,0x766d,0x766e,0x766f,0x7671,0x7674,
|
||||
0x7681,0x7685,0x768c,0x768d,0x7695,0x769b,0x769c,0x769d,0x769f,0x76a0,
|
||||
0x76a2,0x76a3,0x76a4,0x76a5,0x76a6,0x76a7,0x76a8,0x76aa,0x76ad,0x76bd,
|
||||
0x76c1,0x76c5,0x76c9,0x76cb,0x76cc,0x76ce,0x76d4,0x76d9,0x76e0,0x76e6,
|
||||
0x76e8,0x76ec,0x76f0,0x76f1,0x76f6,0x76f9,0x76fc,0x7700,0x7706,0x770a,
|
||||
0x770e,0x7712,0x7714,0x7715,0x7717,0x7719,0x771a,0x771c,0x7722,0x7728,
|
||||
0x772d,0x772e,0x772f,0x7734,0x7735,0x7736,0x7739,0x773d,0x773e,0x7742,
|
||||
0x7745,0x7746,0x774a,0x774d,0x774e,0x774f,0x7752,0x7756,0x7757,0x775c,
|
||||
0x775e,0x775f,0x7760,0x7762
|
||||
},
|
||||
{ /* ku 2f */
|
||||
0x7764,0x7767,0x776a,0x776c,0x7770,0x7772,0x7773,0x7774,0x777a,0x777d,
|
||||
0x7780,0x7784,0x778c,0x778d,0x7794,0x7795,0x7796,0x779a,0x779f,0x77a2,
|
||||
0x77a7,0x77aa,0x77ae,0x77af,0x77b1,0x77b5,0x77be,0x77c3,0x77c9,0x77d1,
|
||||
0x77d2,0x77d5,0x77d9,0x77de,0x77df,0x77e0,0x77e4,0x77e6,0x77ea,0x77ec,
|
||||
0x77f0,0x77f1,0x77f4,0x77f8,0x77fb,0x7805,0x7806,0x7809,0x780d,0x780e,
|
||||
0x7811,0x781d,0x7821,0x7822,0x7823,0x782d,0x782e,0x7830,0x7835,0x7837,
|
||||
0x7843,0x7844,0x7847,0x7848,0x784c,0x784e,0x7852,0x785c,0x785e,0x7860,
|
||||
0x7861,0x7863,0x7864,0x7868,0x786a,0x786e,0x787a,0x787e,0x788a,0x788f,
|
||||
0x7894,0x7898,0x78a1,0x789d,0x789e,0x789f,0x78a4,0x78a8,0x78ac,0x78ad,
|
||||
0x78b0,0x78b1,0x78b2,0x78b3
|
||||
},
|
||||
{ /* ku 30 */
|
||||
0x78bb,0x78bd,0x78bf,0x78c7,0x78c8,0x78c9,0x78cc,0x78ce,0x78d2,0x78d3,
|
||||
0x78d5,0x78d6,0x78e4,0x78db,0x78df,0x78e0,0x78e1,0x78e6,0x78ea,0x78f2,
|
||||
0x78f3,0x7900,0x78f6,0x78f7,0x78fa,0x78fb,0x78ff,0x7906,0x790c,0x7910,
|
||||
0x791a,0x791c,0x791e,0x791f,0x7920,0x7925,0x7927,0x7929,0x792d,0x7931,
|
||||
0x7934,0x7935,0x793b,0x793d,0x793f,0x7944,0x7945,0x7946,0x794a,0x794b,
|
||||
0x794f,0x7951,0x7954,0x7958,0x795b,0x795c,0x7967,0x7969,0x796b,0x7972,
|
||||
0x7979,0x797b,0x797c,0x797e,0x798b,0x798c,0x7991,0x7993,0x7994,0x7995,
|
||||
0x7996,0x7998,0x799b,0x799c,0x79a1,0x79a8,0x79a9,0x79ab,0x79af,0x79b1,
|
||||
0x79b4,0x79b8,0x79bb,0x79c2,0x79c4,0x79c7,0x79c8,0x79ca,0x79cf,0x79d4,
|
||||
0x79d6,0x79da,0x79dd,0x79de
|
||||
},
|
||||
{ /* ku 31 */
|
||||
0x79e0,0x79e2,0x79e5,0x79ea,0x79eb,0x79ed,0x79f1,0x79f8,0x79fc,0x7a02,
|
||||
0x7a03,0x7a07,0x7a09,0x7a0a,0x7a0c,0x7a11,0x7a15,0x7a1b,0x7a1e,0x7a21,
|
||||
0x7a27,0x7a2b,0x7a2d,0x7a2f,0x7a30,0x7a34,0x7a35,0x7a38,0x7a39,0x7a3a,
|
||||
0x7a44,0x7a45,0x7a47,0x7a48,0x7a4c,0x7a55,0x7a56,0x7a59,0x7a5c,0x7a5d,
|
||||
0x7a5f,0x7a60,0x7a65,0x7a67,0x7a6a,0x7a6d,0x7a75,0x7a78,0x7a7e,0x7a80,
|
||||
0x7a82,0x7a85,0x7a86,0x7a8a,0x7a8b,0x7a90,0x7a91,0x7a94,0x7a9e,0x7aa0,
|
||||
0x7aa3,0x7aac,0x7ab3,0x7ab5,0x7ab9,0x7abb,0x7abc,0x7ac6,0x7ac9,0x7acc,
|
||||
0x7ace,0x7ad1,0x7adb,0x7ae8,0x7ae9,0x7aeb,0x7aec,0x7af1,0x7af4,0x7afb,
|
||||
0x7afd,0x7afe,0x7b07,0x7b14,0x7b1f,0x7b23,0x7b27,0x7b29,0x7b2a,0x7b2b,
|
||||
0x7b2d,0x7b2e,0x7b2f,0x7b30
|
||||
},
|
||||
{ /* ku 32 */
|
||||
0x7b31,0x7b34,0x7b3d,0x7b3f,0x7b40,0x7b41,0x7b47,0x7b4e,0x7b55,0x7b60,
|
||||
0x7b64,0x7b66,0x7b69,0x7b6a,0x7b6d,0x7b6f,0x7b72,0x7b73,0x7b77,0x7b84,
|
||||
0x7b89,0x7b8e,0x7b90,0x7b91,0x7b96,0x7b9b,0x7b9e,0x7ba0,0x7ba5,0x7bac,
|
||||
0x7baf,0x7bb0,0x7bb2,0x7bb5,0x7bb6,0x7bba,0x7bbb,0x7bbc,0x7bbd,0x7bc2,
|
||||
0x7bc5,0x7bc8,0x7bca,0x7bd4,0x7bd6,0x7bd7,0x7bd9,0x7bda,0x7bdb,0x7be8,
|
||||
0x7bea,0x7bf2,0x7bf4,0x7bf5,0x7bf8,0x7bf9,0x7bfa,0x7bfc,0x7bfe,0x7c01,
|
||||
0x7c02,0x7c03,0x7c04,0x7c06,0x7c09,0x7c0b,0x7c0c,0x7c0e,0x7c0f,0x7c19,
|
||||
0x7c1b,0x7c20,0x7c25,0x7c26,0x7c28,0x7c2c,0x7c31,0x7c33,0x7c34,0x7c36,
|
||||
0x7c39,0x7c3a,0x7c46,0x7c4a,0x7c55,0x7c51,0x7c52,0x7c53,0x7c59,0x7c5a,
|
||||
0x7c5b,0x7c5c,0x7c5d,0x7c5e
|
||||
},
|
||||
{ /* ku 33 */
|
||||
0x7c61,0x7c63,0x7c67,0x7c69,0x7c6d,0x7c6e,0x7c70,0x7c72,0x7c79,0x7c7c,
|
||||
0x7c7d,0x7c86,0x7c87,0x7c8f,0x7c94,0x7c9e,0x7ca0,0x7ca6,0x7cb0,0x7cb6,
|
||||
0x7cb7,0x7cba,0x7cbb,0x7cbc,0x7cbf,0x7cc4,0x7cc7,0x7cc8,0x7cc9,0x7ccd,
|
||||
0x7ccf,0x7cd3,0x7cd4,0x7cd5,0x7cd7,0x7cd9,0x7cda,0x7cdd,0x7ce6,0x7ce9,
|
||||
0x7ceb,0x7cf5,0x7d03,0x7d07,0x7d08,0x7d09,0x7d0f,0x7d11,0x7d12,0x7d13,
|
||||
0x7d16,0x7d1d,0x7d1e,0x7d23,0x7d26,0x7d2a,0x7d2d,0x7d31,0x7d3c,0x7d3d,
|
||||
0x7d3e,0x7d40,0x7d41,0x7d47,0x7d48,0x7d4d,0x7d51,0x7d53,0x7d57,0x7d59,
|
||||
0x7d5a,0x7d5c,0x7d5d,0x7d65,0x7d67,0x7d6a,0x7d70,0x7d78,0x7d7a,0x7d7b,
|
||||
0x7d7f,0x7d81,0x7d82,0x7d83,0x7d85,0x7d86,0x7d88,0x7d8b,0x7d8c,0x7d8d,
|
||||
0x7d91,0x7d96,0x7d97,0x7d9d
|
||||
},
|
||||
{ /* ku 34 */
|
||||
0x7d9e,0x7da6,0x7da7,0x7daa,0x7db3,0x7db6,0x7db7,0x7db9,0x7dc2,0x7dc3,
|
||||
0x7dc4,0x7dc5,0x7dc6,0x7dcc,0x7dcd,0x7dce,0x7dd7,0x7dd9,0x7e00,0x7de2,
|
||||
0x7de5,0x7de6,0x7dea,0x7deb,0x7ded,0x7df1,0x7df5,0x7df6,0x7df9,0x7dfa,
|
||||
0x7e08,0x7e10,0x7e11,0x7e15,0x7e17,0x7e1c,0x7e1d,0x7e20,0x7e27,0x7e28,
|
||||
0x7e2c,0x7e2d,0x7e2f,0x7e33,0x7e36,0x7e3f,0x7e44,0x7e45,0x7e47,0x7e4e,
|
||||
0x7e50,0x7e52,0x7e58,0x7e5f,0x7e61,0x7e62,0x7e65,0x7e6b,0x7e6e,0x7e6f,
|
||||
0x7e73,0x7e78,0x7e7e,0x7e81,0x7e86,0x7e87,0x7e8a,0x7e8d,0x7e91,0x7e95,
|
||||
0x7e98,0x7e9a,0x7e9d,0x7e9e,0x7f3c,0x7f3b,0x7f3d,0x7f3e,0x7f3f,0x7f43,
|
||||
0x7f44,0x7f47,0x7f4f,0x7f52,0x7f53,0x7f5b,0x7f5c,0x7f5d,0x7f61,0x7f63,
|
||||
0x7f64,0x7f65,0x7f66,0x7f6d
|
||||
},
|
||||
{ /* ku 35 */
|
||||
0x7f71,0x7f7d,0x7f7e,0x7f7f,0x7f80,0x7f8b,0x7f8d,0x7f8f,0x7f90,0x7f91,
|
||||
0x7f96,0x7f97,0x7f9c,0x7fa1,0x7fa2,0x7fa6,0x7faa,0x7fad,0x7fb4,0x7fbc,
|
||||
0x7fbf,0x7fc0,0x7fc3,0x7fc8,0x7fce,0x7fcf,0x7fdb,0x7fdf,0x7fe3,0x7fe5,
|
||||
0x7fe8,0x7fec,0x7fee,0x7fef,0x7ff2,0x7ffa,0x7ffd,0x7ffe,0x7fff,0x8007,
|
||||
0x8008,0x800a,0x800d,0x800e,0x800f,0x8011,0x8013,0x8014,0x8016,0x801d,
|
||||
0x801e,0x801f,0x8020,0x8024,0x8026,0x802c,0x802e,0x8030,0x8034,0x8035,
|
||||
0x8037,0x8039,0x803a,0x803c,0x803e,0x8040,0x8044,0x8060,0x8064,0x8066,
|
||||
0x806d,0x8071,0x8075,0x8081,0x8088,0x808e,0x809c,0x809e,0x80a6,0x80a7,
|
||||
0x80ab,0x80b8,0x80b9,0x80c8,0x80cd,0x80cf,0x80d2,0x80d4,0x80d5,0x80d7,
|
||||
0x80d8,0x80e0,0x80ed,0x80ee
|
||||
},
|
||||
{ /* ku 36 */
|
||||
0x80f0,0x80f2,0x80f3,0x80f6,0x80f9,0x80fa,0x80fe,0x8103,0x810b,0x8116,
|
||||
0x8117,0x8118,0x811c,0x811e,0x8120,0x8124,0x8127,0x812c,0x8130,0x8135,
|
||||
0x813a,0x813c,0x8145,0x8147,0x814a,0x814c,0x8152,0x8157,0x8160,0x8161,
|
||||
0x8167,0x8168,0x8169,0x816d,0x816f,0x8177,0x8181,0x8190,0x8184,0x8185,
|
||||
0x8186,0x818b,0x818e,0x8196,0x8198,0x819b,0x819e,0x81a2,0x81ae,0x81b2,
|
||||
0x81b4,0x81bb,0x81cb,0x81c3,0x81c5,0x81ca,0x81ce,0x81cf,0x81d5,0x81d7,
|
||||
0x81db,0x81dd,0x81de,0x81e1,0x81e4,0x81eb,0x81ec,0x81f0,0x81f1,0x81f2,
|
||||
0x81f5,0x81f6,0x81f8,0x81f9,0x81fd,0x81ff,0x8200,0x8203,0x820f,0x8213,
|
||||
0x8214,0x8219,0x821a,0x821d,0x8221,0x8222,0x8228,0x8232,0x8234,0x823a,
|
||||
0x8243,0x8244,0x8245,0x8246
|
||||
},
|
||||
{ /* ku 37 */
|
||||
0x824b,0x824e,0x824f,0x8251,0x8256,0x825c,0x8260,0x8263,0x8267,0x826d,
|
||||
0x8274,0x827b,0x827d,0x827f,0x8280,0x8281,0x8283,0x8284,0x8287,0x8289,
|
||||
0x828a,0x828e,0x8291,0x8294,0x8296,0x8298,0x829a,0x829b,0x82a0,0x82a1,
|
||||
0x82a3,0x82a4,0x82a7,0x82a8,0x82a9,0x82aa,0x82ae,0x82b0,0x82b2,0x82b4,
|
||||
0x82b7,0x82ba,0x82bc,0x82be,0x82bf,0x82c6,0x82d0,0x82d5,0x82da,0x82e0,
|
||||
0x82e2,0x82e4,0x82e8,0x82ea,0x82ed,0x82ef,0x82f6,0x82f7,0x82fd,0x82fe,
|
||||
0x8300,0x8301,0x8307,0x8308,0x830a,0x830b,0x8354,0x831b,0x831d,0x831e,
|
||||
0x831f,0x8321,0x8322,0x832c,0x832d,0x832e,0x8330,0x8333,0x8337,0x833a,
|
||||
0x833c,0x833d,0x8342,0x8343,0x8344,0x8347,0x834d,0x834e,0x8351,0x8355,
|
||||
0x8356,0x8357,0x8370,0x8378
|
||||
},
|
||||
{ /* ku 38 */
|
||||
0x837d,0x837f,0x8380,0x8382,0x8384,0x8386,0x838d,0x8392,0x8394,0x8395,
|
||||
0x8398,0x8399,0x839b,0x839c,0x839d,0x83a6,0x83a7,0x83a9,0x83ac,0x83be,
|
||||
0x83bf,0x83c0,0x83c7,0x83c9,0x83cf,0x83d0,0x83d1,0x83d4,0x83dd,0x8353,
|
||||
0x83e8,0x83ea,0x83f6,0x83f8,0x83f9,0x83fc,0x8401,0x8406,0x840a,0x840f,
|
||||
0x8411,0x8415,0x8419,0x83ad,0x842f,0x8439,0x8445,0x8447,0x8448,0x844a,
|
||||
0x844d,0x844f,0x8451,0x8452,0x8456,0x8458,0x8459,0x845a,0x845c,0x8460,
|
||||
0x8464,0x8465,0x8467,0x846a,0x8470,0x8473,0x8474,0x8476,0x8478,0x847c,
|
||||
0x847d,0x8481,0x8485,0x8492,0x8493,0x8495,0x849e,0x84a6,0x84a8,0x84a9,
|
||||
0x84aa,0x84af,0x84b1,0x84b4,0x84ba,0x84bd,0x84be,0x84c0,0x84c2,0x84c7,
|
||||
0x84c8,0x84cc,0x84cf,0x84d3
|
||||
},
|
||||
{ /* ku 39 */
|
||||
0x84dc,0x84e7,0x84ea,0x84ef,0x84f0,0x84f1,0x84f2,0x84f7,0x8532,0x84fa,
|
||||
0x84fb,0x84fd,0x8502,0x8503,0x8507,0x850c,0x850e,0x8510,0x851c,0x851e,
|
||||
0x8522,0x8523,0x8524,0x8525,0x8527,0x852a,0x852b,0x852f,0x8533,0x8534,
|
||||
0x8536,0x853f,0x8546,0x854f,0x8550,0x8551,0x8552,0x8553,0x8556,0x8559,
|
||||
0x855c,0x855d,0x855e,0x855f,0x8560,0x8561,0x8562,0x8564,0x856b,0x856f,
|
||||
0x8579,0x857a,0x857b,0x857d,0x857f,0x8581,0x8585,0x8586,0x8589,0x858b,
|
||||
0x858c,0x858f,0x8593,0x8598,0x859d,0x859f,0x85a0,0x85a2,0x85a5,0x85a7,
|
||||
0x85b4,0x85b6,0x85b7,0x85b8,0x85bc,0x85bd,0x85be,0x85bf,0x85c2,0x85c7,
|
||||
0x85ca,0x85cb,0x85ce,0x85ad,0x85d8,0x85da,0x85df,0x85e0,0x85e6,0x85e8,
|
||||
0x85ed,0x85f3,0x85f6,0x85fc
|
||||
},
|
||||
{ /* ku 3a */
|
||||
0x85ff,0x8600,0x8604,0x8605,0x860d,0x860e,0x8610,0x8611,0x8612,0x8618,
|
||||
0x8619,0x861b,0x861e,0x8621,0x8627,0x8629,0x8636,0x8638,0x863a,0x863c,
|
||||
0x863d,0x8640,0x8642,0x8646,0x8652,0x8653,0x8656,0x8657,0x8658,0x8659,
|
||||
0x865d,0x8660,0x8661,0x8662,0x8663,0x8664,0x8669,0x866c,0x866f,0x8675,
|
||||
0x8676,0x8677,0x867a,0x868d,0x8691,0x8696,0x8698,0x869a,0x869c,0x86a1,
|
||||
0x86a6,0x86a7,0x86a8,0x86ad,0x86b1,0x86b3,0x86b4,0x86b5,0x86b7,0x86b8,
|
||||
0x86b9,0x86bf,0x86c0,0x86c1,0x86c3,0x86c5,0x86d1,0x86d2,0x86d5,0x86d7,
|
||||
0x86da,0x86dc,0x86e0,0x86e3,0x86e5,0x86e7,0x8688,0x86fa,0x86fc,0x86fd,
|
||||
0x8704,0x8705,0x8707,0x870b,0x870e,0x870f,0x8710,0x8713,0x8714,0x8719,
|
||||
0x871e,0x871f,0x8721,0x8723
|
||||
},
|
||||
{ /* ku 3b */
|
||||
0x8728,0x872e,0x872f,0x8731,0x8732,0x8739,0x873a,0x873c,0x873d,0x873e,
|
||||
0x8740,0x8743,0x8745,0x874d,0x8758,0x875d,0x8761,0x8764,0x8765,0x876f,
|
||||
0x8771,0x8772,0x877b,0x8783,0x8784,0x8785,0x8786,0x8787,0x8788,0x8789,
|
||||
0x878b,0x878c,0x8790,0x8793,0x8795,0x8797,0x8798,0x8799,0x879e,0x87a0,
|
||||
0x87a3,0x87a7,0x87ac,0x87ad,0x87ae,0x87b1,0x87b5,0x87be,0x87bf,0x87c1,
|
||||
0x87c8,0x87c9,0x87ca,0x87ce,0x87d5,0x87d6,0x87d9,0x87da,0x87dc,0x87df,
|
||||
0x87e2,0x87e3,0x87e4,0x87ea,0x87eb,0x87ed,0x87f1,0x87f3,0x87f8,0x87fa,
|
||||
0x87ff,0x8801,0x8803,0x8806,0x8809,0x880a,0x880b,0x8810,0x8819,0x8812,
|
||||
0x8813,0x8814,0x8818,0x881a,0x881b,0x881c,0x881e,0x881f,0x8828,0x882d,
|
||||
0x882e,0x8830,0x8832,0x8835
|
||||
},
|
||||
{ /* ku 3c */
|
||||
0x883a,0x883c,0x8841,0x8843,0x8845,0x8848,0x8849,0x884a,0x884b,0x884e,
|
||||
0x8851,0x8855,0x8856,0x8858,0x885a,0x885c,0x885f,0x8860,0x8864,0x8869,
|
||||
0x8871,0x8879,0x887b,0x8880,0x8898,0x889a,0x889b,0x889c,0x889f,0x88a0,
|
||||
0x88a8,0x88aa,0x88ba,0x88bd,0x88be,0x88c0,0x88ca,0x88cb,0x88cc,0x88cd,
|
||||
0x88ce,0x88d1,0x88d2,0x88d3,0x88db,0x88de,0x88e7,0x88ef,0x88f0,0x88f1,
|
||||
0x88f5,0x88f7,0x8901,0x8906,0x890d,0x890e,0x890f,0x8915,0x8916,0x8918,
|
||||
0x8919,0x891a,0x891c,0x8920,0x8926,0x8927,0x8928,0x8930,0x8931,0x8932,
|
||||
0x8935,0x8939,0x893a,0x893e,0x8940,0x8942,0x8945,0x8946,0x8949,0x894f,
|
||||
0x8952,0x8957,0x895a,0x895b,0x895c,0x8961,0x8962,0x8963,0x896b,0x896e,
|
||||
0x8970,0x8973,0x8975,0x897a
|
||||
},
|
||||
{ /* ku 3d */
|
||||
0x897b,0x897c,0x897d,0x8989,0x898d,0x8990,0x8994,0x8995,0x899b,0x899c,
|
||||
0x899f,0x89a0,0x89a5,0x89b0,0x89b4,0x89b5,0x89b6,0x89b7,0x89bc,0x89d4,
|
||||
0x89d5,0x89d6,0x89d7,0x89d8,0x89e5,0x89e9,0x89eb,0x89ed,0x89f1,0x89f3,
|
||||
0x89f6,0x89f9,0x89fd,0x89ff,0x8a04,0x8a05,0x8a07,0x8a0f,0x8a11,0x8a12,
|
||||
0x8a14,0x8a15,0x8a1e,0x8a20,0x8a22,0x8a24,0x8a26,0x8a2b,0x8a2c,0x8a2f,
|
||||
0x8a35,0x8a37,0x8a3d,0x8a3e,0x8a40,0x8a43,0x8a45,0x8a47,0x8a49,0x8a4d,
|
||||
0x8a4e,0x8a53,0x8a56,0x8a57,0x8a58,0x8a5c,0x8a5d,0x8a61,0x8a65,0x8a67,
|
||||
0x8a75,0x8a76,0x8a77,0x8a79,0x8a7a,0x8a7b,0x8a7e,0x8a7f,0x8a80,0x8a83,
|
||||
0x8a86,0x8a8b,0x8a8f,0x8a90,0x8a92,0x8a96,0x8a97,0x8a99,0x8a9f,0x8aa7,
|
||||
0x8aa9,0x8aae,0x8aaf,0x8ab3
|
||||
},
|
||||
{ /* ku 3e */
|
||||
0x8ab6,0x8ab7,0x8abb,0x8abe,0x8ac3,0x8ac6,0x8ac8,0x8ac9,0x8aca,0x8ad1,
|
||||
0x8ad3,0x8ad4,0x8ad5,0x8ad7,0x8add,0x8adf,0x8aec,0x8af0,0x8af4,0x8af5,
|
||||
0x8af6,0x8afc,0x8aff,0x8b05,0x8b06,0x8b0b,0x8b11,0x8b1c,0x8b1e,0x8b1f,
|
||||
0x8b0a,0x8b2d,0x8b30,0x8b37,0x8b3c,0x8b42,0x8b43,0x8b44,0x8b45,0x8b46,
|
||||
0x8b48,0x8b52,0x8b53,0x8b54,0x8b59,0x8b4d,0x8b5e,0x8b63,0x8b6d,0x8b76,
|
||||
0x8b78,0x8b79,0x8b7c,0x8b7e,0x8b81,0x8b84,0x8b85,0x8b8b,0x8b8d,0x8b8f,
|
||||
0x8b94,0x8b95,0x8b9c,0x8b9e,0x8b9f,0x8c38,0x8c39,0x8c3d,0x8c3e,0x8c45,
|
||||
0x8c47,0x8c49,0x8c4b,0x8c4f,0x8c51,0x8c53,0x8c54,0x8c57,0x8c58,0x8c5b,
|
||||
0x8c5d,0x8c59,0x8c63,0x8c64,0x8c66,0x8c68,0x8c69,0x8c6d,0x8c73,0x8c75,
|
||||
0x8c76,0x8c7b,0x8c7e,0x8c86
|
||||
},
|
||||
{ /* ku 3f */
|
||||
0x8c87,0x8c8b,0x8c90,0x8c92,0x8c93,0x8c99,0x8c9b,0x8c9c,0x8ca4,0x8cb9,
|
||||
0x8cba,0x8cc5,0x8cc6,0x8cc9,0x8ccb,0x8ccf,0x8cd6,0x8cd5,0x8cd9,0x8cdd,
|
||||
0x8ce1,0x8ce8,0x8cec,0x8cef,0x8cf0,0x8cf2,0x8cf5,0x8cf7,0x8cf8,0x8cfe,
|
||||
0x8cff,0x8d01,0x8d03,0x8d09,0x8d12,0x8d17,0x8d1b,0x8d65,0x8d69,0x8d6c,
|
||||
0x8d6e,0x8d7f,0x8d82,0x8d84,0x8d88,0x8d8d,0x8d90,0x8d91,0x8d95,0x8d9e,
|
||||
0x8d9f,0x8da0,0x8da6,0x8dab,0x8dac,0x8daf,0x8db2,0x8db5,0x8db7,0x8db9,
|
||||
0x8dbb,0x8dc0,0x8dc5,0x8dc6,0x8dc7,0x8dc8,0x8dca,0x8dce,0x8dd1,0x8dd4,
|
||||
0x8dd5,0x8dd7,0x8dd9,0x8de4,0x8de5,0x8de7,0x8dec,0x8df0,0x8dbc,0x8df1,
|
||||
0x8df2,0x8df4,0x8dfd,0x8e01,0x8e04,0x8e05,0x8e06,0x8e0b,0x8e11,0x8e14,
|
||||
0x8e16,0x8e20,0x8e21,0x8e22
|
||||
},
|
||||
{ /* ku 40 */
|
||||
0x8e23,0x8e26,0x8e27,0x8e31,0x8e33,0x8e36,0x8e37,0x8e38,0x8e39,0x8e3d,
|
||||
0x8e40,0x8e41,0x8e4b,0x8e4d,0x8e4e,0x8e4f,0x8e54,0x8e5b,0x8e5c,0x8e5d,
|
||||
0x8e5e,0x8e61,0x8e62,0x8e69,0x8e6c,0x8e6d,0x8e6f,0x8e70,0x8e71,0x8e79,
|
||||
0x8e7a,0x8e7b,0x8e82,0x8e83,0x8e89,0x8e90,0x8e92,0x8e95,0x8e9a,0x8e9b,
|
||||
0x8e9d,0x8e9e,0x8ea2,0x8ea7,0x8ea9,0x8ead,0x8eae,0x8eb3,0x8eb5,0x8eba,
|
||||
0x8ebb,0x8ec0,0x8ec1,0x8ec3,0x8ec4,0x8ec7,0x8ecf,0x8ed1,0x8ed4,0x8edc,
|
||||
0x8ee8,0x8eee,0x8ef0,0x8ef1,0x8ef7,0x8ef9,0x8efa,0x8eed,0x8f00,0x8f02,
|
||||
0x8f07,0x8f08,0x8f0f,0x8f10,0x8f16,0x8f17,0x8f18,0x8f1e,0x8f20,0x8f21,
|
||||
0x8f23,0x8f25,0x8f27,0x8f28,0x8f2c,0x8f2d,0x8f2e,0x8f34,0x8f35,0x8f36,
|
||||
0x8f37,0x8f3a,0x8f40,0x8f41
|
||||
},
|
||||
{ /* ku 41 */
|
||||
0x8f43,0x8f47,0x8f4f,0x8f51,0x8f52,0x8f53,0x8f54,0x8f55,0x8f58,0x8f5d,
|
||||
0x8f5e,0x8f65,0x8f9d,0x8fa0,0x8fa1,0x8fa4,0x8fa5,0x8fa6,0x8fb5,0x8fb6,
|
||||
0x8fb8,0x8fbe,0x8fc0,0x8fc1,0x8fc6,0x8fca,0x8fcb,0x8fcd,0x8fd0,0x8fd2,
|
||||
0x8fd3,0x8fd5,0x8fe0,0x8fe3,0x8fe4,0x8fe8,0x8fee,0x8ff1,0x8ff5,0x8ff6,
|
||||
0x8ffb,0x8ffe,0x9002,0x9004,0x9008,0x900c,0x9018,0x901b,0x9028,0x9029,
|
||||
0x902f,0x902a,0x902c,0x902d,0x9033,0x9034,0x9037,0x903f,0x9043,0x9044,
|
||||
0x904c,0x905b,0x905d,0x9062,0x9066,0x9067,0x906c,0x9070,0x9074,0x9079,
|
||||
0x9085,0x9088,0x908b,0x908c,0x908e,0x9090,0x9095,0x9097,0x9098,0x9099,
|
||||
0x909b,0x90a0,0x90a1,0x90a2,0x90a5,0x90b0,0x90b2,0x90b3,0x90b4,0x90b6,
|
||||
0x90bd,0x90cc,0x90be,0x90c3
|
||||
},
|
||||
{ /* ku 42 */
|
||||
0x90c4,0x90c5,0x90c7,0x90c8,0x90d5,0x90d7,0x90d8,0x90d9,0x90dc,0x90dd,
|
||||
0x90df,0x90e5,0x90d2,0x90f6,0x90eb,0x90ef,0x90f0,0x90f4,0x90fe,0x90ff,
|
||||
0x9100,0x9104,0x9105,0x9106,0x9108,0x910d,0x9110,0x9114,0x9116,0x9117,
|
||||
0x9118,0x911a,0x911c,0x911e,0x9120,0x9125,0x9122,0x9123,0x9127,0x9129,
|
||||
0x912e,0x912f,0x9131,0x9134,0x9136,0x9137,0x9139,0x913a,0x913c,0x913d,
|
||||
0x9143,0x9147,0x9148,0x914f,0x9153,0x9157,0x9159,0x915a,0x915b,0x9161,
|
||||
0x9164,0x9167,0x916d,0x9174,0x9179,0x917a,0x917b,0x9181,0x9183,0x9185,
|
||||
0x9186,0x918a,0x918e,0x9191,0x9193,0x9194,0x9195,0x9198,0x919e,0x91a1,
|
||||
0x91a6,0x91a8,0x91ac,0x91ad,0x91ae,0x91b0,0x91b1,0x91b2,0x91b3,0x91b6,
|
||||
0x91bb,0x91bc,0x91bd,0x91bf
|
||||
},
|
||||
{ /* ku 43 */
|
||||
0x91c2,0x91c3,0x91c5,0x91d3,0x91d4,0x91d7,0x91d9,0x91da,0x91de,0x91e4,
|
||||
0x91e5,0x91e9,0x91ea,0x91ec,0x91ed,0x91ee,0x91ef,0x91f0,0x91f1,0x91f7,
|
||||
0x91f9,0x91fb,0x91fd,0x9200,0x9201,0x9204,0x9205,0x9206,0x9207,0x9209,
|
||||
0x920a,0x920c,0x9210,0x9212,0x9213,0x9216,0x9218,0x921c,0x921d,0x9223,
|
||||
0x9224,0x9225,0x9226,0x9228,0x922e,0x922f,0x9230,0x9233,0x9235,0x9236,
|
||||
0x9238,0x9239,0x923a,0x923c,0x923e,0x9240,0x9242,0x9243,0x9246,0x9247,
|
||||
0x924a,0x924d,0x924e,0x924f,0x9251,0x9258,0x9259,0x925c,0x925d,0x9260,
|
||||
0x9261,0x9265,0x9267,0x9268,0x9269,0x926e,0x926f,0x9270,0x9275,0x9276,
|
||||
0x9277,0x9278,0x9279,0x927b,0x927c,0x927d,0x927f,0x9288,0x9289,0x928a,
|
||||
0x928d,0x928e,0x9292,0x9297
|
||||
},
|
||||
{ /* ku 44 */
|
||||
0x9299,0x929f,0x92a0,0x92a4,0x92a5,0x92a7,0x92a8,0x92ab,0x92af,0x92b2,
|
||||
0x92b6,0x92b8,0x92ba,0x92bb,0x92bc,0x92bd,0x92bf,0x92c0,0x92c1,0x92c2,
|
||||
0x92c3,0x92c5,0x92c6,0x92c7,0x92c8,0x92cb,0x92cc,0x92cd,0x92ce,0x92d0,
|
||||
0x92d3,0x92d5,0x92d7,0x92d8,0x92d9,0x92dc,0x92dd,0x92df,0x92e0,0x92e1,
|
||||
0x92e3,0x92e5,0x92e7,0x92e8,0x92ec,0x92ee,0x92f0,0x92f9,0x92fb,0x92ff,
|
||||
0x9300,0x9302,0x9308,0x930d,0x9311,0x9314,0x9315,0x931c,0x931d,0x931e,
|
||||
0x931f,0x9321,0x9324,0x9325,0x9327,0x9329,0x932a,0x9333,0x9334,0x9336,
|
||||
0x9337,0x9347,0x9348,0x9349,0x9350,0x9351,0x9352,0x9355,0x9357,0x9358,
|
||||
0x935a,0x935e,0x9364,0x9365,0x9367,0x9369,0x936a,0x936d,0x936f,0x9370,
|
||||
0x9371,0x9373,0x9374,0x9376
|
||||
},
|
||||
{ /* ku 45 */
|
||||
0x937a,0x937d,0x937f,0x9380,0x9381,0x9382,0x9388,0x938a,0x938b,0x938d,
|
||||
0x938f,0x9392,0x9395,0x9398,0x939b,0x939e,0x93a1,0x93a3,0x93a4,0x93a6,
|
||||
0x93a8,0x93ab,0x93b4,0x93b5,0x93b6,0x93ba,0x93a9,0x93c1,0x93c4,0x93c5,
|
||||
0x93c6,0x93c7,0x93c9,0x93ca,0x93cb,0x93cc,0x93cd,0x93d3,0x93d9,0x93dc,
|
||||
0x93de,0x93df,0x93e2,0x93e6,0x93e7,0x93f9,0x93f7,0x93f8,0x93fa,0x93fb,
|
||||
0x93fd,0x9401,0x9402,0x9404,0x9408,0x9409,0x940d,0x940e,0x940f,0x9415,
|
||||
0x9416,0x9417,0x941f,0x942e,0x942f,0x9431,0x9432,0x9433,0x9434,0x943b,
|
||||
0x943f,0x943d,0x9443,0x9445,0x9448,0x944a,0x944c,0x9455,0x9459,0x945c,
|
||||
0x945f,0x9461,0x9463,0x9468,0x946b,0x946d,0x946e,0x946f,0x9471,0x9472,
|
||||
0x9484,0x9483,0x9578,0x9579
|
||||
},
|
||||
{ /* ku 46 */
|
||||
0x957e,0x9584,0x9588,0x958c,0x958d,0x958e,0x959d,0x959e,0x959f,0x95a1,
|
||||
0x95a6,0x95a9,0x95ab,0x95ac,0x95b4,0x95b6,0x95ba,0x95bd,0x95bf,0x95c6,
|
||||
0x95c8,0x95c9,0x95cb,0x95d0,0x95d1,0x95d2,0x95d3,0x95d9,0x95da,0x95dd,
|
||||
0x95de,0x95df,0x95e0,0x95e4,0x95e6,0x961d,0x961e,0x9622,0x9624,0x9625,
|
||||
0x9626,0x962c,0x9631,0x9633,0x9637,0x9638,0x9639,0x963a,0x963c,0x963d,
|
||||
0x9641,0x9652,0x9654,0x9656,0x9657,0x9658,0x9661,0x966e,0x9674,0x967b,
|
||||
0x967c,0x967e,0x967f,0x9681,0x9682,0x9683,0x9684,0x9689,0x9691,0x9696,
|
||||
0x969a,0x969d,0x969f,0x96a4,0x96a5,0x96a6,0x96a9,0x96ae,0x96af,0x96b3,
|
||||
0x96ba,0x96ca,0x96d2,0x5db2,0x96d8,0x96da,0x96dd,0x96de,0x96df,0x96e9,
|
||||
0x96ef,0x96f1,0x96fa,0x9702
|
||||
},
|
||||
{ /* ku 47 */
|
||||
0x9703,0x9705,0x9709,0x971a,0x971b,0x971d,0x9721,0x9722,0x9723,0x9728,
|
||||
0x9731,0x9733,0x9741,0x9743,0x974a,0x974e,0x974f,0x9755,0x9757,0x9758,
|
||||
0x975a,0x975b,0x9763,0x9767,0x976a,0x976e,0x9773,0x9776,0x9777,0x9778,
|
||||
0x977b,0x977d,0x977f,0x9780,0x9789,0x9795,0x9796,0x9797,0x9799,0x979a,
|
||||
0x979e,0x979f,0x97a2,0x97ac,0x97ae,0x97b1,0x97b2,0x97b5,0x97b6,0x97b8,
|
||||
0x97b9,0x97ba,0x97bc,0x97be,0x97bf,0x97c1,0x97c4,0x97c5,0x97c7,0x97c9,
|
||||
0x97ca,0x97cc,0x97cd,0x97ce,0x97d0,0x97d1,0x97d4,0x97d7,0x97d8,0x97d9,
|
||||
0x97dd,0x97de,0x97e0,0x97db,0x97e1,0x97e4,0x97ef,0x97f1,0x97f4,0x97f7,
|
||||
0x97f8,0x97fa,0x9807,0x980a,0x9819,0x980d,0x980e,0x9814,0x9816,0x981c,
|
||||
0x981e,0x9820,0x9823,0x9826
|
||||
},
|
||||
{ /* ku 48 */
|
||||
0x982b,0x982e,0x982f,0x9830,0x9832,0x9833,0x9835,0x9825,0x983e,0x9844,
|
||||
0x9847,0x984a,0x9851,0x9852,0x9853,0x9856,0x9857,0x9859,0x985a,0x9862,
|
||||
0x9863,0x9865,0x9866,0x986a,0x986c,0x98ab,0x98ad,0x98ae,0x98b0,0x98b4,
|
||||
0x98b7,0x98b8,0x98ba,0x98bb,0x98bf,0x98c2,0x98c5,0x98c8,0x98cc,0x98e1,
|
||||
0x98e3,0x98e5,0x98e6,0x98e7,0x98ea,0x98f3,0x98f6,0x9902,0x9907,0x9908,
|
||||
0x9911,0x9915,0x9916,0x9917,0x991a,0x991b,0x991c,0x991f,0x9922,0x9926,
|
||||
0x9927,0x992b,0x9931,0x9932,0x9933,0x9934,0x9935,0x9939,0x993a,0x993b,
|
||||
0x993c,0x9940,0x9941,0x9946,0x9947,0x9948,0x994d,0x994e,0x9954,0x9958,
|
||||
0x9959,0x995b,0x995c,0x995e,0x995f,0x9960,0x999b,0x999d,0x999f,0x99a6,
|
||||
0x99b0,0x99b1,0x99b2,0x99b5
|
||||
},
|
||||
{ /* ku 49 */
|
||||
0x99b9,0x99ba,0x99bd,0x99bf,0x99c3,0x99c9,0x99d3,0x99d4,0x99d9,0x99da,
|
||||
0x99dc,0x99de,0x99e7,0x99ea,0x99eb,0x99ec,0x99f0,0x99f4,0x99f5,0x99f9,
|
||||
0x99fd,0x99fe,0x9a02,0x9a03,0x9a04,0x9a0b,0x9a0c,0x9a10,0x9a11,0x9a16,
|
||||
0x9a1e,0x9a20,0x9a22,0x9a23,0x9a24,0x9a27,0x9a2d,0x9a2e,0x9a33,0x9a35,
|
||||
0x9a36,0x9a38,0x9a47,0x9a41,0x9a44,0x9a4a,0x9a4b,0x9a4c,0x9a4e,0x9a51,
|
||||
0x9a54,0x9a56,0x9a5d,0x9aaa,0x9aac,0x9aae,0x9aaf,0x9ab2,0x9ab4,0x9ab5,
|
||||
0x9ab6,0x9ab9,0x9abb,0x9abe,0x9abf,0x9ac1,0x9ac3,0x9ac6,0x9ac8,0x9ace,
|
||||
0x9ad0,0x9ad2,0x9ad5,0x9ad6,0x9ad7,0x9adb,0x9adc,0x9ae0,0x9ae4,0x9ae5,
|
||||
0x9ae7,0x9ae9,0x9aec,0x9af2,0x9af3,0x9af5,0x9af9,0x9afa,0x9afd,0x9aff,
|
||||
0x9b00,0x9b01,0x9b02,0x9b03
|
||||
},
|
||||
{ /* ku 4a */
|
||||
0x9b04,0x9b05,0x9b08,0x9b09,0x9b0b,0x9b0c,0x9b0d,0x9b0e,0x9b10,0x9b12,
|
||||
0x9b16,0x9b19,0x9b1b,0x9b1c,0x9b20,0x9b26,0x9b2b,0x9b2d,0x9b33,0x9b34,
|
||||
0x9b35,0x9b37,0x9b39,0x9b3a,0x9b3d,0x9b48,0x9b4b,0x9b4c,0x9b55,0x9b56,
|
||||
0x9b57,0x9b5b,0x9b5e,0x9b61,0x9b63,0x9b65,0x9b66,0x9b68,0x9b6a,0x9b6b,
|
||||
0x9b6c,0x9b6d,0x9b6e,0x9b73,0x9b75,0x9b77,0x9b78,0x9b79,0x9b7f,0x9b80,
|
||||
0x9b84,0x9b85,0x9b86,0x9b87,0x9b89,0x9b8a,0x9b8b,0x9b8d,0x9b8f,0x9b90,
|
||||
0x9b94,0x9b9a,0x9b9d,0x9b9e,0x9ba6,0x9ba7,0x9ba9,0x9bac,0x9bb0,0x9bb1,
|
||||
0x9bb2,0x9bb7,0x9bb8,0x9bbb,0x9bbc,0x9bbe,0x9bbf,0x9bc1,0x9bc7,0x9bc8,
|
||||
0x9bce,0x9bd0,0x9bd7,0x9bd8,0x9bdd,0x9bdf,0x9be5,0x9be7,0x9bea,0x9beb,
|
||||
0x9bef,0x9bf3,0x9bf7,0x9bf8
|
||||
},
|
||||
{ /* ku 4b */
|
||||
0x9bf9,0x9bfa,0x9bfd,0x9bff,0x9c00,0x9c02,0x9c0b,0x9c0f,0x9c11,0x9c16,
|
||||
0x9c18,0x9c19,0x9c1a,0x9c1c,0x9c1e,0x9c22,0x9c23,0x9c26,0x9c27,0x9c28,
|
||||
0x9c29,0x9c2a,0x9c31,0x9c35,0x9c36,0x9c37,0x9c3d,0x9c41,0x9c43,0x9c44,
|
||||
0x9c45,0x9c49,0x9c4a,0x9c4e,0x9c4f,0x9c50,0x9c53,0x9c54,0x9c56,0x9c58,
|
||||
0x9c5b,0x9c5d,0x9c5e,0x9c5f,0x9c63,0x9c69,0x9c6a,0x9c5c,0x9c6b,0x9c68,
|
||||
0x9c6e,0x9c70,0x9c72,0x9c75,0x9c77,0x9c7b,0x9ce6,0x9cf2,0x9cf7,0x9cf9,
|
||||
0x9d0b,0x9d02,0x9d11,0x9d17,0x9d18,0x9d1c,0x9d1d,0x9d1e,0x9d2f,0x9d30,
|
||||
0x9d32,0x9d33,0x9d34,0x9d3a,0x9d3c,0x9d45,0x9d3d,0x9d42,0x9d43,0x9d47,
|
||||
0x9d4a,0x9d53,0x9d54,0x9d5f,0x9d63,0x9d62,0x9d65,0x9d69,0x9d6a,0x9d6b,
|
||||
0x9d70,0x9d76,0x9d77,0x9d7b
|
||||
},
|
||||
{ /* ku 4c */
|
||||
0x9d7c,0x9d7e,0x9d83,0x9d84,0x9d86,0x9d8a,0x9d8d,0x9d8e,0x9d92,0x9d93,
|
||||
0x9d95,0x9d96,0x9d97,0x9d98,0x9da1,0x9daa,0x9dac,0x9dae,0x9db1,0x9db5,
|
||||
0x9db9,0x9dbc,0x9dbf,0x9dc3,0x9dc7,0x9dc9,0x9dca,0x9dd4,0x9dd5,0x9dd6,
|
||||
0x9dd7,0x9dda,0x9dde,0x9ddf,0x9de0,0x9de5,0x9de7,0x9de9,0x9deb,0x9dee,
|
||||
0x9df0,0x9df3,0x9df4,0x9dfe,0x9e0a,0x9e02,0x9e07,0x9e0e,0x9e10,0x9e11,
|
||||
0x9e12,0x9e15,0x9e16,0x9e19,0x9e1c,0x9e1d,0x9e7a,0x9e7b,0x9e7c,0x9e80,
|
||||
0x9e82,0x9e83,0x9e84,0x9e85,0x9e87,0x9e8e,0x9e8f,0x9e96,0x9e98,0x9e9b,
|
||||
0x9e9e,0x9ea4,0x9ea8,0x9eac,0x9eae,0x9eaf,0x9eb0,0x9eb3,0x9eb4,0x9eb5,
|
||||
0x9ec6,0x9ec8,0x9ecb,0x9ed5,0x9edf,0x9ee4,0x9ee7,0x9eec,0x9eed,0x9eee,
|
||||
0x9ef0,0x9ef1,0x9ef2,0x9ef5
|
||||
},
|
||||
{ /* ku 4d */
|
||||
0x9ef8,0x9eff,0x9f02,0x9f03,0x9f09,0x9f0f,0x9f10,0x9f11,0x9f12,0x9f14,
|
||||
0x9f16,0x9f17,0x9f19,0x9f1a,0x9f1b,0x9f1f,0x9f22,0x9f26,0x9f2a,0x9f2b,
|
||||
0x9f2f,0x9f31,0x9f32,0x9f34,0x9f37,0x9f39,0x9f3a,0x9f3c,0x9f3d,0x9f3f,
|
||||
0x9f41,0x9f43,0x9f44,0x9f45,0x9f46,0x9f47,0x9f53,0x9f55,0x9f56,0x9f57,
|
||||
0x9f58,0x9f5a,0x9f5d,0x9f5e,0x9f68,0x9f69,0x9f6d,0x9f6e,0x9f6f,0x9f70,
|
||||
0x9f71,0x9f73,0x9f75,0x9f7a,0x9f7d,0x9f8f,0x9f90,0x9f91,0x9f92,0x9f94,
|
||||
0x9f96,0x9f97,0x9f9e,0x9fa1,0x9fa2,0x9fa3,0x9fa5,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON
|
||||
}
|
||||
};
|
||||
48
src/charset/koi8_r.c
Normal file
48
src/charset/koi8_r.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: KOI8-R conversion table
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 3 July 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* KOI8-R is a de-facto standard of Russia */
|
||||
|
||||
static const unsigned short koi8rtab[128] = {
|
||||
0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
|
||||
0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
|
||||
0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
|
||||
0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
|
||||
0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
|
||||
0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
|
||||
0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
|
||||
0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
|
||||
0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
|
||||
0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
|
||||
0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
|
||||
0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
|
||||
0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
|
||||
0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
|
||||
0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
|
||||
0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
|
||||
};
|
||||
48
src/charset/koi8_u.c
Normal file
48
src/charset/koi8_u.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: KOI8-U conversion table
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 25 August 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* KOI8-U is a de-facto standard of Ukraine */
|
||||
|
||||
static const unsigned short koi8utab[128] = {
|
||||
0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
|
||||
0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
|
||||
0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
|
||||
0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
|
||||
0x2550,0x2551,0x2552,0x0451,0x0454,0x2554,0x0456,0x0457,
|
||||
0x2557,0x2558,0x2559,0x255a,0x255b,0x0491,0x255d,0x255e,
|
||||
0x255f,0x2560,0x2561,0x0401,0x0403,0x2563,0x0406,0x0407,
|
||||
0x2566,0x2567,0x2568,0x2569,0x256a,0x0490,0x256c,0x00a9,
|
||||
0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
|
||||
0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
|
||||
0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
|
||||
0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
|
||||
0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
|
||||
0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
|
||||
0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
|
||||
0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
|
||||
};
|
||||
2673
src/charset/ksc_5601.c
Normal file
2673
src/charset/ksc_5601.c
Normal file
File diff suppressed because it is too large
Load Diff
51
src/charset/tis_620.c
Normal file
51
src/charset/tis_620.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: TIS 620-2529 conversion table
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 24 October 1997
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* TIS 620-2529 is the "Thai Industrial Standard for Thai Character Code
|
||||
* for Computer", published by the Thai Industrial Standards Institute,
|
||||
* Ministry of Industry of Thailand.
|
||||
*/
|
||||
|
||||
static const unsigned short tis620tab[128] = {
|
||||
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
|
||||
0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
|
||||
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
|
||||
0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
|
||||
UBOGON,0x0e01,0x0e02,0x0e03,0x0e04,0x0e05,0x0e06,0x0e07,
|
||||
0x0e08,0x0e09,0x0e0a,0x0e0b,0x0e0c,0x0e0d,0x0e0e,0x0e0f,
|
||||
0x0e10,0x0e11,0x0e12,0x0e13,0x0e14,0x0e15,0x0e16,0x0e17,
|
||||
0x0e18,0x0e19,0x0e1a,0x0e1b,0x0e1c,0x0e1d,0x0e1e,0x0e1f,
|
||||
0x0e20,0x0e21,0x0e22,0x0e23,0x0e24,0x0e25,0x0e26,0x0e27,
|
||||
0x0e28,0x0e29,0x0e2a,0x0e2b,0x0e2c,0x0e2d,0x0e2e,0x0e2f,
|
||||
0x0e30,0x0e31,0x0e32,0x0e33,0x0e34,0x0e35,0x0e36,0x0e37,
|
||||
0x0e38,0x0e39,0x0e3a,UBOGON,UBOGON,UBOGON,UBOGON,0x0e3f,
|
||||
0x0e40,0x0e41,0x0e42,0x0e43,0x0e44,0x0e45,0x0e46,0x0e47,
|
||||
0x0e48,0x0e49,0x0e4a,0x0e4b,0x0e4c,0x0e4d,0x0e4e,0x0e4f,
|
||||
0x0e50,0x0e51,0x0e52,0x0e53,0x0e54,0x0e55,0x0e56,0x0e57,
|
||||
0x0e58,0x0e59,0x0e5a,0x0e5b,UBOGON,UBOGON,UBOGON,UBOGON
|
||||
};
|
||||
1487
src/charset/tmap.c
Normal file
1487
src/charset/tmap.c
Normal file
File diff suppressed because it is too large
Load Diff
67
src/charset/viscii.c
Normal file
67
src/charset/viscii.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: VISCII conversion table
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 2 June 1998
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* VISCII is the VIetnamese Standard Code for Information Interchange,
|
||||
* defined by the Vietnamese Standardization Working Group, RFC-1456,
|
||||
* May 1993.
|
||||
*/
|
||||
|
||||
static const unsigned short visciitab[256] = {
|
||||
0x0000,0x0001,0x1eb2,0x0003,0x0004,0x1eb4,0x1eaa,0x0007,
|
||||
0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
|
||||
0x0010,0x0011,0x0012,0x0013,0x1ef6,0x0015,0x0016,0x0017,
|
||||
0x0018,0x1ef8,0x001a,0x001b,0x001c,0x001d,0x1ef4,0x001f,
|
||||
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
|
||||
0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
|
||||
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
|
||||
0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
|
||||
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
|
||||
0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
|
||||
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
|
||||
0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
|
||||
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
|
||||
0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
|
||||
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
|
||||
0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
|
||||
0x1ea0,0x1eae,0x1eb0,0x1eb6,0x1ea4,0x1ea6,0x1ea8,0x1eac,
|
||||
0x1ebc,0x1eb8,0x1ebe,0x1ec0,0x1ec2,0x1ec4,0x1ec6,0x1ed0,
|
||||
0x1ed2,0x1ed4,0x1ed6,0x1ed8,0x1ee2,0x1eda,0x1edc,0x1ede,
|
||||
0x1eca,0x1ece,0x1ecc,0x1ec8,0x1ee6,0x0168,0x1ee4,0x1ef2,
|
||||
0x00d5,0x1eaf,0x1eb1,0x1eb7,0x1ea5,0x1ea7,0x1ea9,0x1ead,
|
||||
0x1ebd,0x1eb9,0x1ebf,0x1ec1,0x1ec3,0x1ec5,0x1ec7,0x1ed1,
|
||||
0x1ed3,0x1ed5,0x1ed7,0x1ee0,0x01a0,0x1ed9,0x1edd,0x1edf,
|
||||
0x1ecb,0x1ef0,0x1ee8,0x1eea,0x1eec,0x01a1,0x1edb,0x01af,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x1ea2,0x0102,0x1eb3,0x1eb5,
|
||||
0x00c8,0x00c9,0x00ca,0x1eba,0x00cc,0x00cd,0x0128,0x1ef3,
|
||||
0x0110,0x1ee9,0x00d2,0x00d3,0x00d4,0x1ea1,0x1ef7,0x1eeb,
|
||||
0x1eed,0x00d9,0x00da,0x1ef9,0x1ef5,0x00dd,0x1ee1,0x01b0,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x1ea3,0x0103,0x1eef,0x1eab,
|
||||
0x00e8,0x00e9,0x00ea,0x1ebb,0x00ec,0x00ed,0x0129,0x1ec9,
|
||||
0x0111,0x1ef1,0x00f2,0x00f3,0x00f4,0x00f5,0x1ecf,0x1ecd,
|
||||
0x1ee5,0x00f9,0x00fa,0x0169,0x1ee7,0x00fd,0x1ee3,0x1eee
|
||||
};
|
||||
4136
src/charset/widths.c
Normal file
4136
src/charset/widths.c
Normal file
File diff suppressed because it is too large
Load Diff
228
src/charset/windows.c
Normal file
228
src/charset/windows.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Windows conversion tables
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 16 October 2000
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Windows Thai */
|
||||
static const unsigned short windows_874tab[128] = {
|
||||
0x20ac,UBOGON,UBOGON,UBOGON,UBOGON,0x2026,UBOGON,UBOGON,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x00a0,0x0e01,0x0e02,0x0e03,0x0e04,0x0e05,0x0e06,0x0e07,
|
||||
0x0e08,0x0e09,0x0e0a,0x0e0b,0x0e0c,0x0e0d,0x0e0e,0x0e0f,
|
||||
0x0e10,0x0e11,0x0e12,0x0e13,0x0e14,0x0e15,0x0e16,0x0e17,
|
||||
0x0e18,0x0e19,0x0e1a,0x0e1b,0x0e1c,0x0e1d,0x0e1e,0x0e1f,
|
||||
0x0e20,0x0e21,0x0e22,0x0e23,0x0e24,0x0e25,0x0e26,0x0e27,
|
||||
0x0e28,0x0e29,0x0e2a,0x0e2b,0x0e2c,0x0e2d,0x0e2e,0x0e2f,
|
||||
0x0e30,0x0e31,0x0e32,0x0e33,0x0e34,0x0e35,0x0e36,0x0e37,
|
||||
0x0e38,0x0e39,0x0e3a,UBOGON,UBOGON,UBOGON,UBOGON,0x0e3f,
|
||||
0x0e40,0x0e41,0x0e42,0x0e43,0x0e44,0x0e45,0x0e46,0x0e47,
|
||||
0x0e48,0x0e49,0x0e4a,0x0e4b,0x0e4c,0x0e4d,0x0e4e,0x0e4f,
|
||||
0x0e50,0x0e51,0x0e52,0x0e53,0x0e54,0x0e55,0x0e56,0x0e57,
|
||||
0x0e58,0x0e59,0x0e5a,0x0e5b,UBOGON,UBOGON,UBOGON,UBOGON
|
||||
};
|
||||
|
||||
/* Windows Latin-2 */
|
||||
static const unsigned short windows_1250tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,UBOGON,0x201e,0x2026,0x2020,0x2021,
|
||||
UBOGON,0x2030,0x0160,0x2039,0x015a,0x0164,0x017d,0x0179,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,0x2122,0x0161,0x203a,0x015b,0x0165,0x017e,0x017a,
|
||||
0x00a0,0x02c7,0x02d8,0x0141,0x00a4,0x0104,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x015e,0x00ab,0x00ac,0x00ad,0x00ae,0x017b,
|
||||
0x00b0,0x00b1,0x02db,0x0142,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x0105,0x015f,0x00bb,0x013d,0x02dd,0x013e,0x017c,
|
||||
0x0154,0x00c1,0x00c2,0x0102,0x00c4,0x0139,0x0106,0x00c7,
|
||||
0x010c,0x00c9,0x0118,0x00cb,0x011a,0x00cd,0x00ce,0x010e,
|
||||
0x0110,0x0143,0x0147,0x00d3,0x00d4,0x0150,0x00d6,0x00d7,
|
||||
0x0158,0x016e,0x00da,0x0170,0x00dc,0x00dd,0x0162,0x00df,
|
||||
0x0155,0x00e1,0x00e2,0x0103,0x00e4,0x013a,0x0107,0x00e7,
|
||||
0x010d,0x00e9,0x0119,0x00eb,0x011b,0x00ed,0x00ee,0x010f,
|
||||
0x0111,0x0144,0x0148,0x00f3,0x00f4,0x0151,0x00f6,0x00f7,
|
||||
0x0159,0x016f,0x00fa,0x0171,0x00fc,0x00fd,0x0163,0x02d9
|
||||
};
|
||||
|
||||
/* Windows Cyrillic */
|
||||
static const unsigned short windows_1251tab[128] = {
|
||||
0x0402,0x0403,0x201a,0x0453,0x201e,0x2026,0x2020,0x2021,
|
||||
0x20ac,0x2030,0x0409,0x2039,0x040a,0x040c,0x040b,0x040f,
|
||||
0x0452,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,0x2122,0x0459,0x203a,0x045a,0x045c,0x045b,0x045f,
|
||||
0x00a0,0x040e,0x045e,0x0408,0x00a4,0x0490,0x00a6,0x00a7,
|
||||
0x0401,0x00a9,0x0404,0x00ab,0x00ac,0x00ad,0x00ae,0x0407,
|
||||
0x00b0,0x00b1,0x0406,0x0456,0x0491,0x00b5,0x00b6,0x00b7,
|
||||
0x0451,0x2116,0x0454,0x00bb,0x0458,0x0405,0x0455,0x0457,
|
||||
0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,
|
||||
0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
|
||||
0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,
|
||||
0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
|
||||
0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,
|
||||
0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
|
||||
0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,
|
||||
0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f
|
||||
};
|
||||
|
||||
/* Windows Latin-1 */
|
||||
static const unsigned short windows_1252tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
0x02c6,0x2030,0x0160,0x2039,0x0152,UBOGON,0x017d,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
0x02dc,0x2122,0x0161,0x203a,0x0153,UBOGON,0x017e,0x0178,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x00f0,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x00ff
|
||||
};
|
||||
|
||||
|
||||
/* Windows Greek */
|
||||
static const unsigned short windows_1253tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
UBOGON,0x2030,UBOGON,0x2039,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,0x2122,UBOGON,0x203a,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x00a0,0x0385,0x0386,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,UBOGON,0x00ab,0x00ac,0x00ad,0x00ae,0x2015,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x0384,0x00b5,0x00b6,0x00b7,
|
||||
0x0388,0x0389,0x038a,0x00bb,0x038c,0x00bd,0x038e,0x038f,
|
||||
0x0390,0x0391,0x0392,0x0393,0x0394,0x0395,0x0396,0x0397,
|
||||
0x0398,0x0399,0x039a,0x039b,0x039c,0x039d,0x039e,0x039f,
|
||||
0x03a0,0x03a1,UBOGON,0x03a3,0x03a4,0x03a5,0x03a6,0x03a7,
|
||||
0x03a8,0x03a9,0x03aa,0x03ab,0x03ac,0x03ad,0x03ae,0x03af,
|
||||
0x03b0,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6,0x03b7,
|
||||
0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,
|
||||
0x03c0,0x03c1,0x03c2,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7,
|
||||
0x03c8,0x03c9,0x03ca,0x03cb,0x03cc,0x03cd,0x03ce,UBOGON
|
||||
};
|
||||
|
||||
/* Windows Turkish */
|
||||
static const unsigned short windows_1254tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
0x02c6,0x2030,0x0160,0x2039,0x0152,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
0x02dc,0x2122,0x0161,0x203a,0x0153,UBOGON,UBOGON,0x0178,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
|
||||
0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
|
||||
0x011e,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x0130,0x015e,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
|
||||
0x011f,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x0131,0x015f,0x00ff
|
||||
};
|
||||
|
||||
/* Windows Hebrew */
|
||||
static const unsigned short windows_1255tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
0x02c6,0x2030,UBOGON,0x2039,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
0x02dc,0x2122,UBOGON,0x203a,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x20aa,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00d7,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00f7,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
|
||||
0x05b0,0x05b1,0x05b2,0x05b3,0x05b4,0x05b5,0x05b6,0x05b7,
|
||||
0x05b8,0x05b9,UBOGON,0x05bb,0x05bc,0x05bd,0x05be,0x05bf,
|
||||
0x05c0,0x05c1,0x05c2,0x05c3,0x05f0,0x05f1,0x05f2,0x05f3,
|
||||
0x05f4,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,UBOGON,
|
||||
0x05d0,0x05d1,0x05d2,0x05d3,0x05d4,0x05d5,0x05d6,0x05d7,
|
||||
0x05d8,0x05d9,0x05da,0x05db,0x05dc,0x05dd,0x05de,0x05df,
|
||||
0x05e0,0x05e1,0x05e2,0x05e3,0x05e4,0x05e5,0x05e6,0x05e7,
|
||||
0x05e8,0x05e9,0x05ea,UBOGON,UBOGON,0x200e,0x200f,UBOGON
|
||||
};
|
||||
|
||||
/* Windows Arabic */
|
||||
static const unsigned short windows_1256tab[128] = {
|
||||
0x20ac,0x067e,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
0x02c6,0x2030,0x0679,0x2039,0x0152,0x0686,0x0698,0x0688,
|
||||
0x06af,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
0x06a9,0x2122,0x0691,0x203a,0x0153,0x200c,0x200d,0x06ba,
|
||||
0x00a0,0x060c,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x06be,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x061b,0x00bb,0x00bc,0x00bd,0x00be,0x061f,
|
||||
0x06c1,0x0621,0x0622,0x0623,0x0624,0x0625,0x0626,0x0627,
|
||||
0x0628,0x0629,0x062a,0x062b,0x062c,0x062d,0x062e,0x062f,
|
||||
0x0630,0x0631,0x0632,0x0633,0x0634,0x0635,0x0636,0x00d7,
|
||||
0x0637,0x0638,0x0639,0x063a,0x0640,0x0641,0x0642,0x0643,
|
||||
0x00e0,0x0644,0x00e2,0x0645,0x0646,0x0647,0x0648,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x0649,0x064a,0x00ee,0x00ef,
|
||||
0x064b,0x064c,0x064d,0x064e,0x00f4,0x064f,0x0650,0x00f7,
|
||||
0x0651,0x00f9,0x0652,0x00fb,0x00fc,0x200e,0x200f,0x06d2
|
||||
};
|
||||
|
||||
/* Windows Baltic */
|
||||
static const unsigned short windows_1257tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,UBOGON,0x201e,0x2026,0x2020,0x2021,
|
||||
UBOGON,0x2030,UBOGON,0x2039,UBOGON,0x00a8,0x02c7,0x00b8,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
UBOGON,0x2122,UBOGON,0x203a,UBOGON,0x00af,0x02db,UBOGON,
|
||||
0x00a0,UBOGON,0x00a2,0x00a3,0x00a4,UBOGON,0x00a6,0x00a7,
|
||||
0x00d8,0x00a9,0x0156,0x00ab,0x00ac,0x00ad,0x00ae,0x00c6,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00f8,0x00b9,0x0157,0x00bb,0x00bc,0x00bd,0x00be,0x00e6,
|
||||
0x0104,0x012e,0x0100,0x0106,0x00c4,0x00c5,0x0118,0x0112,
|
||||
0x010c,0x00c9,0x0179,0x0116,0x0122,0x0136,0x012a,0x013b,
|
||||
0x0160,0x0143,0x0145,0x00d3,0x014c,0x00d5,0x00d6,0x00d7,
|
||||
0x0172,0x0141,0x015a,0x016a,0x00dc,0x017b,0x017d,0x00df,
|
||||
0x0105,0x012f,0x0101,0x0107,0x00e4,0x00e5,0x0119,0x0113,
|
||||
0x010d,0x00e9,0x017a,0x0117,0x0123,0x0137,0x012b,0x013c,
|
||||
0x0161,0x0144,0x0146,0x00f3,0x014d,0x00f5,0x00f6,0x00f7,
|
||||
0x0173,0x0142,0x015b,0x016b,0x00fc,0x017c,0x017e,0x02d9
|
||||
};
|
||||
|
||||
/* Windows Vietnamese */
|
||||
static const unsigned short windows_1258tab[128] = {
|
||||
0x20ac,UBOGON,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
|
||||
0x02c6,0x2030,UBOGON,0x2039,0x0152,UBOGON,UBOGON,UBOGON,
|
||||
UBOGON,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
|
||||
0x02dc,0x2122,UBOGON,0x203a,0x0153,UBOGON,UBOGON,0x0178,
|
||||
0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
|
||||
0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
|
||||
0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
|
||||
0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
|
||||
0x00c0,0x00c1,0x00c2,0x0102,0x00c4,0x00c5,0x00c6,0x00c7,
|
||||
0x00c8,0x00c9,0x00ca,0x00cb,0x0300,0x00cd,0x00ce,0x00cf,
|
||||
0x0110,0x00d1,0x0309,0x00d3,0x00d4,0x01a0,0x00d6,0x00d7,
|
||||
0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x01af,0x0303,0x00df,
|
||||
0x00e0,0x00e1,0x00e2,0x0103,0x00e4,0x00e5,0x00e6,0x00e7,
|
||||
0x00e8,0x00e9,0x00ea,0x00eb,0x0301,0x00ed,0x00ee,0x00ef,
|
||||
0x0111,0x00f1,0x0323,0x00f3,0x00f4,0x01a1,0x00f6,0x00f7,
|
||||
0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x01b0,0x20ab,0x00ff
|
||||
};
|
||||
53
src/dmail/Makefile
Normal file
53
src/dmail/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: dmail Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 5 April 1993
|
||||
# Last Edited: 10 September 2007
|
||||
|
||||
|
||||
C = ../c-client
|
||||
CCLIENTLIB = $C/c-client.a
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = -I$C `cat $C/CFLAGS`
|
||||
LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
|
||||
|
||||
dmail: $(CCLIENTLIB) dmail.o dquota.o
|
||||
$(CC) $(CFLAGS) -o dmail dmail.o dquota.o $(LDFLAGS)
|
||||
|
||||
dmail.o: $C/mail.h $C/misc.h $C/osdep.h dquota.h
|
||||
|
||||
dquota.o: dquota.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
cd $C;make
|
||||
|
||||
clean:
|
||||
rm -f *.o dmail
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
121
src/dmail/dmail.1
Normal file
121
src/dmail/dmail.1
Normal file
@@ -0,0 +1,121 @@
|
||||
.ig
|
||||
* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
..
|
||||
.TH DMAIL 1 "June 18, 2007"
|
||||
.SH NAME
|
||||
dmail \- procmail Mail Delivery Module
|
||||
.nh
|
||||
.SH SYNOPSIS
|
||||
.B dmail
|
||||
.I [\-D] [\-f from_name] [-s] [-k keyword_list] [user][+folder]
|
||||
.SH DESCRIPTION
|
||||
.I dmail
|
||||
delivers mail to a user's INBOX or a designated folder.
|
||||
.I dmail
|
||||
may be configured as a drop-in replacement for
|
||||
.IR binmail (1),
|
||||
.IR mail.local (1)
|
||||
for use with a mail delivery filter such as
|
||||
.IR procmail (1) .
|
||||
.PP
|
||||
Because of security considerations (see below)
|
||||
.I dmail
|
||||
is not intended to be used for direct delivery by the mailer daemon;
|
||||
.IR tmail (1)
|
||||
is the preferred tool for this purpose. If
|
||||
.I dmail
|
||||
is used for mailer daemon delivery, the mailer daemon must invoke
|
||||
.I dmail
|
||||
with the
|
||||
.I dmail
|
||||
process' user id set to the recipient's user id.
|
||||
.PP
|
||||
When
|
||||
.I dmail
|
||||
exits, it returns exit status values to enable
|
||||
.IR procmail (1)
|
||||
to determine whether a message was delivered successfully or had a
|
||||
temporary (requeue for later delivery) or permanent (return to sender)
|
||||
failure.
|
||||
.PP
|
||||
If the
|
||||
.I user
|
||||
name is present, it must be the same as the logged-in user name.
|
||||
.PP
|
||||
If the
|
||||
.I +folder
|
||||
extension is included in the user argument (or appears by itself if there
|
||||
is no user argument),
|
||||
.I dmail
|
||||
will attempt to deliver to the designated folder. If the folder does not
|
||||
exist or the extension is not included, the message is delivered to the
|
||||
user's INBOX.
|
||||
If delivery is to INBOX and no INBOX currently exists,
|
||||
.I dmail
|
||||
will create a new INBOX.
|
||||
.I dmail
|
||||
recognizes the format of an existing INBOX or folder, and appends the new
|
||||
message in that format.
|
||||
.PP
|
||||
The \fB-D\fR flag specifies debugging; this enables additional message
|
||||
telemetry.
|
||||
.PP
|
||||
The \fB-f\fR or \fB-r\fR flag is used to specify a Return-Path. The header
|
||||
.br
|
||||
Return-Path: <\fIfrom_name\fR>
|
||||
.br
|
||||
is prepended to the message before delivery.
|
||||
.PP
|
||||
The
|
||||
.B -s
|
||||
flag specifies that the message will be flagged as being "seen".
|
||||
.PP
|
||||
The \fB-k\fR flag is used to specify delivery keywords, which are set on
|
||||
the message at delivery time if and
|
||||
.B only
|
||||
if the keywords are already defined in the mailbox. Multiple keywords can be
|
||||
specified by using a quoted string, e.g.,
|
||||
.br
|
||||
dmail -k "$Junk Discard" +junkbox
|
||||
.br
|
||||
.SH RESTRICTIONS
|
||||
Absolute pathnames and
|
||||
.I ~user
|
||||
specifications are not permitted in
|
||||
.I +folder
|
||||
extensions.
|
||||
.SH SECURITY CONSIDERATIONS
|
||||
Unlike
|
||||
.I tmail
|
||||
you can use
|
||||
.I dmail
|
||||
to deliver to IMAP4 namespace names via
|
||||
.I +folder
|
||||
extensions. This means that it is possible to deliver to
|
||||
.IR mh (1)
|
||||
format mailboxes.
|
||||
.PP
|
||||
However, this can also include such namespaces as #shared, #public,
|
||||
and #ftp. In most cases, it is undesirable to allow anybody sending
|
||||
mail to the user to deliver to these namespaces. Consequently, there
|
||||
needs to be a rule in place in the configuration of either
|
||||
.IR sendmail (8)
|
||||
or
|
||||
.IR procmail (1)
|
||||
to prevent such abuse.
|
||||
.SH AUTHOR
|
||||
Mark Crispin, MRC@CAC.Washington.EDU
|
||||
.SH "SEE ALSO"
|
||||
binmail(1)
|
||||
.br
|
||||
procmail(1)
|
||||
661
src/dmail/dmail.c
Normal file
661
src/dmail/dmail.c
Normal file
@@ -0,0 +1,661 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Procmail-Callable Mail Delivery Module
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 5 April 1993
|
||||
* Last Edited: 30 October 2008
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
extern int errno; /* just in case */
|
||||
#include <sysexits.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include "c-client.h"
|
||||
#include "dquota.h"
|
||||
|
||||
|
||||
/* Globals */
|
||||
|
||||
char *version = "18"; /* dmail edit version */
|
||||
int debug = NIL; /* debugging (don't fork) */
|
||||
int flagseen = NIL; /* flag message as seen */
|
||||
int trycreate = NIL; /* flag saying gotta create before appending */
|
||||
int critical = NIL; /* flag saying in critical code */
|
||||
char *sender = NIL; /* message origin */
|
||||
char *keywords = NIL; /* keyword list */
|
||||
long precedence = 0; /* delivery precedence - used by quota hook */
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void file_string_init (STRING *s,void *data,unsigned long size);
|
||||
char file_string_next (STRING *s);
|
||||
void file_string_setpos (STRING *s,unsigned long i);
|
||||
int main (int argc,char *argv[]);
|
||||
int deliver (FILE *f,unsigned long msglen,char *user);
|
||||
long ibxpath (MAILSTREAM *ds,char **mailbox,char *path);
|
||||
int deliver_safely (MAILSTREAM *prt,STRING *st,char *mailbox,char *path,
|
||||
char *tmp);
|
||||
int delivery_unsafe (char *path,struct stat *sbuf,char *tmp);
|
||||
int fail (char *string,int code);
|
||||
|
||||
|
||||
/* File string driver for file stringstructs */
|
||||
|
||||
STRINGDRIVER file_string = {
|
||||
file_string_init, /* initialize string structure */
|
||||
file_string_next, /* get next byte in string structure */
|
||||
file_string_setpos /* set position in string structure */
|
||||
};
|
||||
|
||||
|
||||
/* Cache buffer for file stringstructs */
|
||||
|
||||
#define CHUNKLEN 16384
|
||||
char chunk[CHUNKLEN];
|
||||
|
||||
/* Initialize file string structure for file stringstruct
|
||||
* Accepts: string structure
|
||||
* pointer to string
|
||||
* size of string
|
||||
*/
|
||||
|
||||
void file_string_init (STRING *s,void *data,unsigned long size)
|
||||
{
|
||||
s->data = data; /* note fd */
|
||||
s->size = size; /* note size */
|
||||
s->chunk = chunk;
|
||||
s->chunksize = (unsigned long) CHUNKLEN;
|
||||
SETPOS (s,0); /* set initial position */
|
||||
}
|
||||
|
||||
|
||||
/* Get next character from file stringstruct
|
||||
* Accepts: string structure
|
||||
* Returns: character, string structure chunk refreshed
|
||||
*/
|
||||
|
||||
char file_string_next (STRING *s)
|
||||
{
|
||||
char c = *s->curpos++; /* get next byte */
|
||||
SETPOS (s,GETPOS (s)); /* move to next chunk */
|
||||
return c; /* return the byte */
|
||||
}
|
||||
|
||||
|
||||
/* Set string pointer position for file stringstruct
|
||||
* Accepts: string structure
|
||||
* new position
|
||||
*/
|
||||
|
||||
void file_string_setpos (STRING *s,unsigned long i)
|
||||
{
|
||||
if (i > s->size) i = s->size; /* don't permit setting beyond EOF */
|
||||
s->offset = i; /* set new offset */
|
||||
s->curpos = s->chunk; /* reset position */
|
||||
/* set size of data */
|
||||
if (s->cursize = min (s->chunksize,SIZE (s))) {
|
||||
/* move to that position in the file */
|
||||
fseek ((FILE *) s->data,s->offset,SEEK_SET);
|
||||
fread (s->curpos,sizeof (char),(unsigned int) s->cursize,(FILE *) s->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main program */
|
||||
|
||||
int main (int argc,char *argv[])
|
||||
{
|
||||
FILE *f = NIL;
|
||||
int c,ret = 0;
|
||||
unsigned long msglen;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
uid_t ruid = getuid ();
|
||||
struct passwd *pwd = ruid ? getpwnam ("daemon") : NIL;
|
||||
openlog ("dmail",LOG_PID,LOG_MAIL);
|
||||
/* must not be root or daemon! */
|
||||
if (!ruid || (pwd && (pwd->pw_uid == ruid)))
|
||||
_exit (fail ("dmail may not be invoked by root or daemon",EX_USAGE));
|
||||
#include "linkage.c"
|
||||
/* process all flags */
|
||||
for (--argc; argc && (*(s = *++argv)) == '-'; argc--) switch (s[1]) {
|
||||
case 'D': /* debug */
|
||||
debug = T; /* extra debugging */
|
||||
break;
|
||||
case 's': /* deliver as seen */
|
||||
flagseen = T;
|
||||
break;
|
||||
case 'f':
|
||||
case 'r': /* flag giving return path */
|
||||
if (sender) _exit (fail ("duplicate -r",EX_USAGE));
|
||||
if (argc--) sender = cpystr (*++argv);
|
||||
else _exit (fail ("missing argument to -r",EX_USAGE));
|
||||
break;
|
||||
case 'k':
|
||||
if (keywords) _exit (fail ("duplicate -k",EX_USAGE));
|
||||
if (argc--) keywords = cpystr (*++argv);
|
||||
else _exit (fail ("missing argument to -k",EX_USAGE));
|
||||
break;
|
||||
case 'p':
|
||||
if (s[2] && ((s[2] == '-') || isdigit (s[2]))) precedence = atol (s + 2);
|
||||
else if (argc-- && ((*(s = *++argv) == '-') || isdigit (*s)))
|
||||
precedence = atol (s);
|
||||
else _exit (fail ("missing argument to -p",EX_USAGE));
|
||||
break;
|
||||
default: /* anything else */
|
||||
_exit (fail ("unknown switch",EX_USAGE));
|
||||
}
|
||||
|
||||
if (argc > 1) _exit (fail ("too many recipients",EX_USAGE));
|
||||
else if (!(f = tmpfile ())) _exit(fail ("can't make temp file",EX_TEMPFAIL));
|
||||
/* build delivery headers */
|
||||
if (sender) fprintf (f,"Return-Path: <%s>\015\012",sender);
|
||||
/* start Received line: */
|
||||
fprintf (f,"Received: via dmail-%s.%s for %s; ",CCLIENTVERSION,version,
|
||||
(argc == 1) ? *argv : myusername ());
|
||||
rfc822_date (tmp);
|
||||
fputs (tmp,f);
|
||||
fputs ("\015\012",f);
|
||||
/* copy text from standard input */
|
||||
if (!fgets (tmp,MAILTMPLEN-1,stdin) || !(s = strchr (tmp,'\n')) ||
|
||||
(s == tmp) || s[1]) _exit (fail ("bad first message line",EX_USAGE));
|
||||
else if (s[-1] == '\015') { /* nuke leading "From " line */
|
||||
if ((tmp[0] != 'F') || (tmp[1] != 'r') || (tmp[2] != 'o') ||
|
||||
(tmp[3] != 'm') || (tmp[4] != ' ')) fputs (tmp,f);
|
||||
while ((c = getchar ()) != EOF) putc (c,f);
|
||||
}
|
||||
else {
|
||||
if ((tmp[0] != 'F') || (tmp[1] != 'r') || (tmp[2] != 'o') ||
|
||||
(tmp[3] != 'm') || (tmp[4] != ' ')) {
|
||||
*s++ = '\015'; /* overwrite NL with CRLF */
|
||||
*s++ = '\012';
|
||||
*s = '\0'; /* tie off string */
|
||||
fputs (tmp,f); /* write line */
|
||||
}
|
||||
}
|
||||
/* copy text from standard input */
|
||||
while ((c = getchar ()) != EOF) {
|
||||
/* add CR if needed */
|
||||
if (c == '\012') putc ('\015',f);
|
||||
putc (c,f);
|
||||
}
|
||||
msglen = ftell (f); /* size of message */
|
||||
fflush (f); /* make sure all changes written out */
|
||||
if (ferror (f)) ret = fail ("error writing temp file",EX_TEMPFAIL);
|
||||
else if (!msglen) ret = fail ("empty message",EX_TEMPFAIL);
|
||||
/* single delivery */
|
||||
else ret = deliver (f,msglen,argc ? *argv : myusername ());
|
||||
fclose (f); /* all done with temporary file */
|
||||
_exit (ret); /* normal exit */
|
||||
return 0; /* stupid gcc */
|
||||
}
|
||||
|
||||
/* Deliver message to recipient list
|
||||
* Accepts: file description of message temporary file
|
||||
* size of message temporary file in bytes
|
||||
* recipient name
|
||||
* Returns: NIL if success, else error code
|
||||
*/
|
||||
|
||||
int deliver (FILE *f,unsigned long msglen,char *user)
|
||||
{
|
||||
MAILSTREAM *ds = NIL;
|
||||
char *s,*mailbox,tmp[MAILTMPLEN],path[MAILTMPLEN];
|
||||
STRING st;
|
||||
struct stat sbuf;
|
||||
/* have a mailbox specifier? */
|
||||
if (mailbox = strchr (user,'+')) {
|
||||
*mailbox++ = '\0'; /* yes, tie off user name */
|
||||
if (!*mailbox || !compare_cstring ((unsigned char *) mailbox,"INBOX"))
|
||||
mailbox = NIL; /* user+ and user+INBOX same as user */
|
||||
}
|
||||
if (!*user) user = myusername ();
|
||||
else if (strcmp (user,myusername ()))
|
||||
return fail ("can't deliver to other user",EX_CANTCREAT);
|
||||
sprintf (tmp,"delivering to %.80s+%.80s",user,mailbox ? mailbox : "INBOX");
|
||||
mm_dlog (tmp);
|
||||
/* prepare stringstruct */
|
||||
INIT (&st,file_string,(void *) f,msglen);
|
||||
if (mailbox) { /* non-INBOX name */
|
||||
switch (mailbox[0]) { /* make sure a valid name */
|
||||
default: /* other names, try to deliver if not INBOX */
|
||||
if (!strstr (mailbox,"..") && !strstr (mailbox,"//") &&
|
||||
!strstr (mailbox,"/~") && mailboxfile (path,mailbox) && path[0] &&
|
||||
!deliver_safely (NIL,&st,mailbox,path,tmp)) return NIL;
|
||||
case '%': case '*': /* wildcards not valid */
|
||||
case '/': /* absolute path names not valid */
|
||||
case '~': /* user names not valid */
|
||||
sprintf (tmp,"invalid mailbox name %.80s+%.80s",user,mailbox);
|
||||
mm_log (tmp,WARN);
|
||||
break;
|
||||
}
|
||||
mm_dlog ("retrying delivery to INBOX");
|
||||
SETPOS (&st,0); /* rewind stringstruct just in case */
|
||||
}
|
||||
|
||||
/* no -I, resolve "INBOX" into path */
|
||||
if (mailboxfile (path,mailbox = "INBOX") && !path[0]) {
|
||||
/* clear box, get generic INBOX prototype */
|
||||
if (!(ds = mail_open (NIL,"INBOX",OP_PROTOTYPE)))
|
||||
fatal ("no INBOX prototype");
|
||||
/* standard system driver? */
|
||||
if (!strcmp (ds->dtb->name,"unix") || !strcmp (ds->dtb->name,"mmdf")) {
|
||||
strcpy (path,sysinbox ());/* use system INBOX */
|
||||
if (!lstat (path,&sbuf)) /* deliver to existing system INBOX */
|
||||
return deliver_safely (ds,&st,mailbox,path,tmp);
|
||||
}
|
||||
else { /* other driver, try ~/INBOX */
|
||||
if ((mailboxfile (path,"&&&&&") == path) &&
|
||||
(s = strstr (path,"&&&&&")) && strcpy (s,"INBOX") &&
|
||||
!lstat (path,&sbuf)){ /* deliver to existing ~/INBOX */
|
||||
sprintf (tmp,"#driver.%s/INBOX",ds->dtb->name);
|
||||
return deliver_safely (ds,&st,cpystr (tmp),path,tmp);
|
||||
}
|
||||
}
|
||||
/* not dummy, deliver to driver imputed path */
|
||||
if (strcmp (ds->dtb->name,"dummy"))
|
||||
return (ibxpath (ds,&mailbox,path) && !lstat (path,&sbuf)) ?
|
||||
deliver_safely (ds,&st,mailbox,path,tmp) :
|
||||
fail ("unable to resolve INBOX path",EX_CANTCREAT);
|
||||
/* dummy, empty imputed append path exist? */
|
||||
if (ibxpath (ds = default_proto (T),&mailbox,path) &&
|
||||
!lstat (path,&sbuf) && !sbuf.st_size)
|
||||
return deliver_safely (ds,&st,mailbox,path,tmp);
|
||||
/* impute path that we will create */
|
||||
if (!ibxpath (ds = default_proto (NIL),&mailbox,path))
|
||||
return fail ("unable to resolve INBOX",EX_CANTCREAT);
|
||||
}
|
||||
/* black box, must create, get create proto */
|
||||
else if (lstat (path,&sbuf)) ds = default_proto (NIL);
|
||||
else { /* black box, existing file */
|
||||
/* empty file, get append prototype */
|
||||
if (!sbuf.st_size) ds = default_proto (T);
|
||||
/* non-empty, get prototype from its data */
|
||||
else if (!(ds = mail_open (NIL,"INBOX",OP_PROTOTYPE)))
|
||||
fatal ("no INBOX prototype");
|
||||
/* error if unknown format */
|
||||
if (!strcmp (ds->dtb->name,"phile"))
|
||||
return fail ("unknown format INBOX",EX_UNAVAILABLE);
|
||||
/* otherwise can deliver to it */
|
||||
return deliver_safely (ds,&st,mailbox,path,tmp);
|
||||
}
|
||||
sprintf (tmp,"attempting to create mailbox %.80s path %.80s",mailbox,path);
|
||||
mm_dlog (tmp);
|
||||
/* supplicate to the Evil One */
|
||||
if (!path_create (ds,path)) return fail ("can't create INBOX",EX_CANTCREAT);
|
||||
sprintf (tmp,"created %.80s",path);
|
||||
mm_dlog (tmp);
|
||||
/* deliver the message */
|
||||
return deliver_safely (ds,&st,mailbox,path,tmp);
|
||||
}
|
||||
|
||||
/* Resolve INBOX from driver prototype into mailbox name and filesystem path
|
||||
* Accepts: driver prototype
|
||||
* pointer to mailbox name string pointer
|
||||
* buffer to return mailbox path
|
||||
* Returns: T if success, NIL if error
|
||||
*/
|
||||
|
||||
long ibxpath (MAILSTREAM *ds,char **mailbox,char *path)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
long ret = T;
|
||||
if (!ds) return NIL;
|
||||
else if (!strcmp (ds->dtb->name,"unix") || !strcmp (ds->dtb->name,"mmdf"))
|
||||
strcpy (path,sysinbox ()); /* use system INBOX for unix and MMDF */
|
||||
else if (!strcmp (ds->dtb->name,"tenex"))
|
||||
ret = (mailboxfile (path,"mail.txt") == path) ? T : NIL;
|
||||
else if (!strcmp (ds->dtb->name,"mtx"))
|
||||
ret = (mailboxfile (path,"INBOX.MTX") == path) ? T : NIL;
|
||||
else if (!strcmp (ds->dtb->name,"mbox"))
|
||||
ret = (mailboxfile (path,"mbox") == path) ? T : NIL;
|
||||
/* better not be a namespace driver */
|
||||
else if (ds->dtb->flags & DR_NAMESPACE) return NIL;
|
||||
/* INBOX in home directory */
|
||||
else ret = ((mailboxfile (path,"&&&&&") == path) &&
|
||||
(s = strstr (path,"&&&&&")) && strcpy (s,"INBOX")) ? T : NIL;
|
||||
if (ret) { /* don't bother if lossage */
|
||||
sprintf (tmp,"#driver.%s/INBOX",ds->dtb->name);
|
||||
*mailbox = cpystr (tmp); /* name of INBOX in this namespace */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Deliver safely
|
||||
* Accepts: prototype stream to force mailbox format
|
||||
* stringstruct of message temporary file or NIL for check only
|
||||
* mailbox name
|
||||
* filesystem path name
|
||||
* scratch buffer for messages
|
||||
* Returns: NIL if success, else error code
|
||||
*/
|
||||
|
||||
int deliver_safely (MAILSTREAM *prt,STRING *st,char *mailbox,char *path,
|
||||
char *tmp)
|
||||
{
|
||||
struct stat sbuf;
|
||||
char *flags = NIL;
|
||||
int i = delivery_unsafe (path,&sbuf,tmp);
|
||||
if (i) return i; /* give up now if delivery unsafe */
|
||||
/* directory, not file */
|
||||
if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
|
||||
if (sbuf.st_mode & 0001) { /* listable directories may be worrisome */
|
||||
sprintf (tmp,"WARNING: directory %.80s is listable",path);
|
||||
mm_log (tmp,WARN);
|
||||
}
|
||||
}
|
||||
else { /* file, not directory */
|
||||
if (sbuf.st_nlink != 1) { /* multiple links may be worrisome */
|
||||
sprintf (tmp,"WARNING: multiple links to file %.80s",path);
|
||||
mm_log (tmp,WARN);
|
||||
}
|
||||
if (sbuf.st_mode & 0111) { /* executable files may be worrisome */
|
||||
sprintf (tmp,"WARNING: file %.80s is executable",path);
|
||||
mm_log (tmp,WARN);
|
||||
}
|
||||
}
|
||||
if (sbuf.st_mode & 0002) { /* public-write files may be worrisome */
|
||||
sprintf (tmp,"WARNING: file %.80s is publicly-writable",path);
|
||||
mm_log (tmp,WARN);
|
||||
}
|
||||
if (sbuf.st_mode & 0004) { /* public-write files may be worrisome */
|
||||
sprintf (tmp,"WARNING: file %.80s is publicly-readable",path);
|
||||
mm_log (tmp,WARN);
|
||||
}
|
||||
/* check site-written quota procedure */
|
||||
if (!dmail_quota (st,path,tmp,sender,precedence))
|
||||
return fail (tmp,EX_CANTCREAT);
|
||||
/* so far, so good */
|
||||
sprintf (tmp,"%s appending to %.80s (%s %.80s)",
|
||||
prt ? prt->dtb->name : "default",mailbox,
|
||||
((sbuf.st_mode & S_IFMT) == S_IFDIR) ? "directory" : "file",path);
|
||||
mm_dlog (tmp);
|
||||
if (keywords) { /* any keywords requested? */
|
||||
if (flagseen) sprintf (flags = tmp,"\\Seen %.1000s",keywords);
|
||||
else flags = keywords;
|
||||
}
|
||||
else if (flagseen) flags = "\\Seen";
|
||||
/* do the append now! */
|
||||
if (!mail_append_full (prt,mailbox,flags,NIL,st)) {
|
||||
sprintf (tmp,"message delivery failed to %.80s",path);
|
||||
return fail (tmp,EX_CANTCREAT);
|
||||
}
|
||||
/* note success */
|
||||
sprintf (tmp,"delivered to %.80s",path);
|
||||
mm_log (tmp,NIL);
|
||||
/* make sure nothing evil this way comes */
|
||||
return delivery_unsafe (path,&sbuf,tmp);
|
||||
}
|
||||
|
||||
/* Verify that delivery is safe
|
||||
* Accepts: path name
|
||||
* stat buffer
|
||||
* scratch buffer for messages
|
||||
* Returns: NIL if delivery is safe, error code if unsafe
|
||||
*/
|
||||
|
||||
int delivery_unsafe (char *path,struct stat *sbuf,char *tmp)
|
||||
{
|
||||
u_short type;
|
||||
sprintf (tmp,"Verifying safe delivery to %.80s",path);
|
||||
mm_dlog (tmp);
|
||||
/* prepare message just in case */
|
||||
sprintf (tmp,"delivery to %.80s unsafe: ",path);
|
||||
/* unsafe if can't get its status */
|
||||
if (lstat (path,sbuf)) strcat (tmp,strerror (errno));
|
||||
/* check file type */
|
||||
else switch (sbuf->st_mode & S_IFMT) {
|
||||
case S_IFDIR: /* directory is always OK */
|
||||
return NIL;
|
||||
case S_IFREG: /* file is unsafe if setuid */
|
||||
if (sbuf->st_mode & S_ISUID) strcat (tmp,"setuid file");
|
||||
/* or setgid */
|
||||
else if (sbuf->st_mode & S_ISGID) strcat (tmp,"setgid file");
|
||||
else return NIL; /* otherwise safe */
|
||||
break;
|
||||
case S_IFCHR: strcat (tmp,"character special"); break;
|
||||
case S_IFBLK: strcat (tmp,"block special"); break;
|
||||
case S_IFLNK: strcat (tmp,"symbolic link"); break;
|
||||
case S_IFSOCK: strcat (tmp,"socket"); break;
|
||||
default:
|
||||
sprintf (tmp + strlen (tmp),"file type %07o",(unsigned int) type);
|
||||
}
|
||||
return fail (tmp,EX_CANTCREAT);
|
||||
}
|
||||
|
||||
/* Report an error
|
||||
* Accepts: string to output
|
||||
*/
|
||||
|
||||
int fail (char *string,int code)
|
||||
{
|
||||
mm_log (string,ERROR); /* pass up the string */
|
||||
switch (code) {
|
||||
#if T
|
||||
case EX_USAGE:
|
||||
case EX_OSERR:
|
||||
case EX_SOFTWARE:
|
||||
case EX_NOUSER:
|
||||
case EX_CANTCREAT:
|
||||
code = EX_TEMPFAIL; /* coerce these to TEMPFAIL */
|
||||
break;
|
||||
#endif
|
||||
case -1: /* quota failure... */
|
||||
code = EX_CANTCREAT; /* ...really returns this code */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code; /* error code to return */
|
||||
}
|
||||
|
||||
/* Co-routines from MAIL library */
|
||||
|
||||
|
||||
/* Message matches a search
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_searched (MAILSTREAM *stream,unsigned long msgno)
|
||||
{
|
||||
fatal ("mm_searched() call");
|
||||
}
|
||||
|
||||
|
||||
/* Message exists (i.e. there are that many messages in the mailbox)
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_exists (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
fatal ("mm_exists() call");
|
||||
}
|
||||
|
||||
|
||||
/* Message expunged
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_expunged (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
fatal ("mm_expunged() call");
|
||||
}
|
||||
|
||||
|
||||
/* Message flags update seen
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_flags (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
}
|
||||
|
||||
/* Mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
fatal ("mm_list() call");
|
||||
}
|
||||
|
||||
|
||||
/* Subscribed mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
fatal ("mm_lsub() call");
|
||||
}
|
||||
|
||||
|
||||
/* Mailbox status
|
||||
* Accepts: MAIL stream
|
||||
* mailbox name
|
||||
* mailbox status
|
||||
*/
|
||||
|
||||
void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
||||
{
|
||||
fatal ("mm_status() call");
|
||||
}
|
||||
|
||||
/* Notification event
|
||||
* Accepts: MAIL stream
|
||||
* string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
tmp[11] = '\0'; /* see if TRYCREATE */
|
||||
if (!strcmp (ucase (strncpy (tmp,string,11)),"[TRYCREATE]")) trycreate = T;
|
||||
mm_log (string,errflg); /* just do mm_log action */
|
||||
}
|
||||
|
||||
|
||||
/* Log an event for the user to see
|
||||
* Accepts: string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_log (char *string,long errflg)
|
||||
{
|
||||
if (trycreate)mm_dlog(string);/* debug logging only if trycreate in effect */
|
||||
else { /* ordinary logging */
|
||||
fprintf (stderr,"%s\n",string);
|
||||
switch (errflg) {
|
||||
case NIL: /* no error */
|
||||
syslog (LOG_INFO,"%s",string);
|
||||
break;
|
||||
case PARSE: /* parsing problem */
|
||||
case WARN: /* warning */
|
||||
syslog (LOG_WARNING,"%s",string);
|
||||
break;
|
||||
case ERROR: /* error */
|
||||
default:
|
||||
syslog (LOG_ERR,"%s",string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log an event to debugging telemetry
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_dlog (char *string)
|
||||
{
|
||||
if (debug) fprintf (stderr,"%s\n",string);
|
||||
syslog (LOG_DEBUG,"%s",string);
|
||||
}
|
||||
|
||||
/* Get user name and password for this host
|
||||
* Accepts: parse of network mailbox name
|
||||
* where to return user name
|
||||
* where to return password
|
||||
* trial count
|
||||
*/
|
||||
|
||||
void mm_login (NETMBX *mb,char *username,char *password,long trial)
|
||||
{
|
||||
fatal ("mm_login() call");
|
||||
}
|
||||
|
||||
|
||||
/* About to enter critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_critical (MAILSTREAM *stream)
|
||||
{
|
||||
critical = T; /* note in critical code */
|
||||
}
|
||||
|
||||
|
||||
/* About to exit critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_nocritical (MAILSTREAM *stream)
|
||||
{
|
||||
critical = NIL; /* note not in critical code */
|
||||
}
|
||||
|
||||
|
||||
/* Disk error found
|
||||
* Accepts: stream
|
||||
* system error code
|
||||
* flag indicating that mailbox may be clobbered
|
||||
* Returns: T if user wants to abort
|
||||
*/
|
||||
|
||||
long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
|
||||
{
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
/* Log a fatal error event
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_fatal (char *string)
|
||||
{
|
||||
printf ("?%s\n",string); /* shouldn't happen normally */
|
||||
}
|
||||
44
src/dmail/dquota.c
Normal file
44
src/dmail/dquota.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Procmail-Callable Mail Delivery Module Quota Hook
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 10 September 2007
|
||||
* Last Edited: 10 September 2007
|
||||
*/
|
||||
|
||||
#include "c-client.h"
|
||||
|
||||
/* Site-written routine to validate delivery per quota and policy
|
||||
* Accepts: stringstruct of message temporary file
|
||||
* filesystem path
|
||||
* return path
|
||||
* buffer to write error message
|
||||
* precedence setting
|
||||
* Returns: T if can deliver, or NIL if quota issue and must bounce
|
||||
*/
|
||||
|
||||
long dmail_quota (STRING *msg,char *path,char *tmp,char *sender,
|
||||
long precedence)
|
||||
{
|
||||
return LONGT; /* dummy success return */
|
||||
}
|
||||
32
src/dmail/dquota.h
Normal file
32
src/dmail/dquota.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Procmail-Callable Mail Delivery Module Quota Hook
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 10 September 2007
|
||||
* Last Edited: 10 September 2007
|
||||
*/
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
long dmail_quota (STRING *msg,char *path,char *tmp,char *sender,
|
||||
long precedence);
|
||||
68
src/imapd/Makefile
Normal file
68
src/imapd/Makefile
Normal file
@@ -0,0 +1,68 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IMAPD Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 5 November 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
ALERT=/etc/imapd.alert
|
||||
USERALERT=.imapalert
|
||||
SHUTDOWN=/etc/nologin
|
||||
ANO=/etc/anonymous.newsgroups
|
||||
NNTP=/etc/imapd.nntp
|
||||
SHELL= /bin/sh
|
||||
|
||||
|
||||
# Un-comment this to get somewhat better interoperability with Netscape. It
|
||||
# causes the "Manage Mail" menu item to open the given URL, e.g. to point to
|
||||
# an alternative IMAP client (e.g. Pine) or perhaps to a homebrew mail
|
||||
# account management page.
|
||||
#NSBD= -DNETSCAPE_BRAIN_DAMAGE=\"http://www.washington.edu/pine\"
|
||||
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
C = ../c-client
|
||||
CCLIENTLIB = $C/c-client.a
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = -I$C `cat $C/CFLAGS` $(NSBD) $(ENBD) -DANOFILE=\"$(ANO)\" \
|
||||
-DALERTFILE=\"$(ALERT)\" -DNNTPFILE=\"$(NNTP)\" \
|
||||
-DUSERALERTFILE=\"$(USERALERT)\" -DSHUTDOWNFILE=\"$(SHUTDOWN)\"
|
||||
LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
|
||||
|
||||
all: imapd
|
||||
|
||||
imapd: $(CCLIENTLIB) imapd.o
|
||||
$(CC) $(CFLAGS) -o imapd imapd.o $(LDFLAGS)
|
||||
|
||||
imapd.o: $C/mail.h $C/misc.h $C/osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
cd $C;make
|
||||
|
||||
clean:
|
||||
rm -f *.o imapd || true
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
48
src/imapd/imapd.8
Normal file
48
src/imapd/imapd.8
Normal file
@@ -0,0 +1,48 @@
|
||||
.ig
|
||||
* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
..
|
||||
.TH IMAPD 8 "August 30, 2006"
|
||||
.UC 5
|
||||
.SH NAME
|
||||
IMAPd \- Internet Message Access Protocol server
|
||||
.SH SYNOPSIS
|
||||
.B /usr/etc/imapd
|
||||
.SH DESCRIPTION
|
||||
.I imapd
|
||||
is a server which supports the
|
||||
.B IMAP4rev1
|
||||
remote mail access protocol as documented in RFC-3501.
|
||||
.I imapd
|
||||
is invoked by the internet server (see
|
||||
.IR inetd (8)),
|
||||
normally for requests to connect to the
|
||||
.B IMAP
|
||||
port as indicated by the
|
||||
.I /etc/services
|
||||
file (see
|
||||
.IR services (5)).
|
||||
Normally, this is port 143 for plaintext IMAP and 993 for SSL IMAP.
|
||||
.PP
|
||||
This daemons contains CRAM-MD5 support. See the md5.txt documentation
|
||||
file for additional information.
|
||||
.PP
|
||||
.I imapd
|
||||
can also be accessed via
|
||||
.IR rsh (1)
|
||||
by many Unix-based clients. To do this, the
|
||||
.I imapd
|
||||
binary must have a link to
|
||||
.I /etc/rimapd
|
||||
since this is where this software expects it to be located.
|
||||
.SH "SEE ALSO"
|
||||
rsh(1) ipopd(8)
|
||||
4608
src/imapd/imapd.c
Normal file
4608
src/imapd/imapd.c
Normal file
File diff suppressed because it is too large
Load Diff
55
src/imapd/makefile.nt
Normal file
55
src/imapd/makefile.nt
Normal file
@@ -0,0 +1,55 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IMAPD Makefile for Windows 9x and Windows NT
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 5 November 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
ALERT=\\imapd.alert
|
||||
USERALERT=alert.txt
|
||||
SHUTDOWN=\\nologin
|
||||
ANO=\\anonymous.newsgroups
|
||||
NNTP=\\imapd.nntp
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS) -DALERTFILE=\"$(ALERT)\" -DNNTPFILE=\"$(NNTP)\" -DUSERALERTFILE=\"$(USERALERT)\" -DANOFILE=\"$(ANO)\" -DSHUTDOWNFILE=\"$(SHUTDOWN)\"
|
||||
|
||||
imapd: $(CCLIENTLIB) imapd.obj
|
||||
LINK /NOLOGO imapd.obj $(LIBS)
|
||||
|
||||
imapd.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
58
src/imapd/makefile.ntk
Normal file
58
src/imapd/makefile.ntk
Normal file
@@ -0,0 +1,58 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IMAPD Makefile for Windows 9x and Windows NT + Kerberos
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 5 November 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
ALERT=\\imapd.alert
|
||||
USERALERT=alert.txt
|
||||
SHUTDOWN=\\nologin
|
||||
ANO=\\anonymous.newsgroups
|
||||
NNTP=\\imapd.nntp
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
K5 = \k5\lib
|
||||
K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
|
||||
LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS) -DALERTFILE=\"$(ALERT)\" -DNNTPFILE=\"$(NNTP)\" -DUSERALERTFILE=\"$(USERALERT)\" -DANOFILE=\"$(ANO)\" -DSHUTDOWNFILE=\"$(SHUTDOWN)\"
|
||||
|
||||
imapd: $(CCLIENTLIB) imapd.obj
|
||||
LINK /NOLOGO imapd.obj $(LIBS)
|
||||
|
||||
imapd.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
56
src/imapd/makefile.w2k
Normal file
56
src/imapd/makefile.w2k
Normal file
@@ -0,0 +1,56 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IMAPD Makefile for Windows 2000/XP
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 5 November 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
ALERT=\\imapd.alert
|
||||
USERALERT=alert.txt
|
||||
SHUTDOWN=\\nologin
|
||||
ANO=\\anonymous.newsgroups
|
||||
NNTP=\\imapd.nntp
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
|
||||
OSCOMPAT = /DWIN32
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS) -DALERTFILE=\"$(ALERT)\" -DNNTPFILE=\"$(NNTP)\" -DUSERALERTFILE=\"$(USERALERT)\" -DANOFILE=\"$(ANO)\" -DSHUTDOWNFILE=\"$(SHUTDOWN)\"
|
||||
|
||||
imapd: $(CCLIENTLIB) imapd.obj
|
||||
LINK /NOLOGO imapd.obj $(LIBS)
|
||||
|
||||
imapd.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
58
src/ipopd/Makefile
Normal file
58
src/ipopd/Makefile
Normal file
@@ -0,0 +1,58 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IPOPD client Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 28 October 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ../c-client
|
||||
CCLIENTLIB = $C/c-client.a
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = -I$C `cat $C/CFLAGS`
|
||||
LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
|
||||
|
||||
ipopd: ipop2d ipop3d
|
||||
|
||||
ipop2d: $(CCLIENTLIB) ipop2d.o
|
||||
$(CC) $(CFLAGS) -o ipop2d ipop2d.o $(LDFLAGS)
|
||||
|
||||
ipop3d: $(CCLIENTLIB) ipop3d.o
|
||||
$(CC) $(CFLAGS) -o ipop3d ipop3d.o $(LDFLAGS)
|
||||
|
||||
ipop2d.o: $C/mail.h $C/misc.h $C/osdep.h
|
||||
|
||||
ipop3d.o: $C/mail.h $C/misc.h $C/osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
cd $C;make
|
||||
|
||||
clean:
|
||||
rm -f *.o ipop2d ipop3d || true
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
711
src/ipopd/ipop2d.c
Normal file
711
src/ipopd/ipop2d.c
Normal file
@@ -0,0 +1,711 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: IPOP2D - IMAP to POP2 conversion server
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* UW Technology
|
||||
* University of Washington
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@Washington.EDU
|
||||
*
|
||||
* Date: 28 October 1990
|
||||
* Last Edited: 13 February 2008
|
||||
*/
|
||||
|
||||
|
||||
/* Parameter files */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
extern int errno; /* just in case */
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include "c-client.h"
|
||||
|
||||
|
||||
/* Autologout timer */
|
||||
#define KODTIMEOUT 60*5
|
||||
#define LOGINTIMEOUT 60*3
|
||||
#define TIMEOUT 60*30
|
||||
|
||||
|
||||
/* Size of temporary buffers */
|
||||
#define TMPLEN 1024
|
||||
|
||||
|
||||
/* Server states */
|
||||
|
||||
#define LISN 0
|
||||
#define AUTH 1
|
||||
#define MBOX 2
|
||||
#define ITEM 3
|
||||
#define NEXT 4
|
||||
#define DONE 5
|
||||
|
||||
/* Global storage */
|
||||
|
||||
char *version = "75"; /* edit number of this server */
|
||||
short state = LISN; /* server state */
|
||||
short critical = NIL; /* non-zero if in critical code */
|
||||
MAILSTREAM *stream = NIL; /* mailbox stream */
|
||||
time_t idletime = 0; /* time we went idle */
|
||||
unsigned long nmsgs = 0; /* number of messages */
|
||||
unsigned long current = 1; /* current message number */
|
||||
unsigned long size = 0; /* size of current message */
|
||||
char status[MAILTMPLEN]; /* space for status string */
|
||||
char *user = ""; /* user name */
|
||||
char *pass = ""; /* password */
|
||||
unsigned long *msg = NIL; /* message translation vector */
|
||||
char *logout = "Logout";
|
||||
char *goodbye = "+ Sayonara\015\012";
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
int main (int argc,char *argv[]);
|
||||
void sayonara (int status);
|
||||
void clkint ();
|
||||
void kodint ();
|
||||
void hupint ();
|
||||
void trmint ();
|
||||
short c_helo (char *t,int argc,char *argv[]);
|
||||
short c_fold (char *t);
|
||||
short c_read (char *t);
|
||||
short c_retr (char *t);
|
||||
short c_acks (char *t);
|
||||
short c_ackd (char *t);
|
||||
short c_nack (char *t);
|
||||
|
||||
/* Main program */
|
||||
|
||||
int main (int argc,char *argv[])
|
||||
{
|
||||
char *s,*t;
|
||||
char cmdbuf[TMPLEN];
|
||||
char *pgmname = (argc && argv[0]) ?
|
||||
(((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ?
|
||||
s+1 : argv[0]) : "ipop2d";
|
||||
/* set service name before linkage */
|
||||
mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");
|
||||
#include "linkage.c"
|
||||
if (mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) {
|
||||
goodbye = "- POP2 server disabled on this system\015\012";
|
||||
sayonara (1);
|
||||
}
|
||||
/* initialize server */
|
||||
server_init (pgmname,"pop",NIL,clkint,kodint,hupint,trmint,NIL);
|
||||
/* There are reports of POP2 clients which get upset if anything appears
|
||||
* between the "+" and the "POP2" in the greeting.
|
||||
*/
|
||||
printf ("+ POP2 %s %s.%s server ready\015\012",tcp_serverhost (),
|
||||
CCLIENTVERSION,version);
|
||||
fflush (stdout); /* dump output buffer */
|
||||
state = AUTH; /* initial server state */
|
||||
while (state != DONE) { /* command processing loop */
|
||||
idletime = time (0); /* get a command under timeout */
|
||||
alarm ((state != AUTH) ? TIMEOUT : LOGINTIMEOUT);
|
||||
clearerr (stdin); /* clear stdin errors */
|
||||
while (!fgets (cmdbuf,TMPLEN-1,stdin)) {
|
||||
if (ferror (stdin) && (errno == EINTR)) clearerr (stdin);
|
||||
else {
|
||||
char *e = ferror (stdin) ?
|
||||
strerror (errno) : "Unexpected client disconnect";
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
sprintf (logout = cmdbuf,"%.80s while reading line",e);
|
||||
state = DONE;
|
||||
stream = mail_close (stream);
|
||||
goodbye = NIL;
|
||||
sayonara (1);
|
||||
}
|
||||
}
|
||||
alarm (0); /* make sure timeout disabled */
|
||||
idletime = 0; /* no longer idle */
|
||||
/* find end of line */
|
||||
if (!strchr (cmdbuf,'\012')) {
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
logout = "- Command line too long\015\012";
|
||||
state = DONE;
|
||||
}
|
||||
else if (!(s = strtok (cmdbuf," \015\012"))) {
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = "- Missing or null command\015\012";
|
||||
state = DONE;
|
||||
}
|
||||
else { /* dispatch based on command */
|
||||
ucase (s); /* canonicalize case */
|
||||
/* snarf argument */
|
||||
t = strtok (NIL,"\015\012");
|
||||
if ((state == AUTH) && !strcmp (s,"HELO")) state = c_helo (t,argc,argv);
|
||||
else if ((state == MBOX || state == ITEM) && !strcmp (s,"FOLD"))
|
||||
state = c_fold (t);
|
||||
else if ((state == MBOX || state == ITEM) && !strcmp (s,"READ"))
|
||||
state = c_read (t);
|
||||
else if ((state == ITEM) && !strcmp (s,"RETR")) state = c_retr (t);
|
||||
else if ((state == NEXT) && !strcmp (s,"ACKS")) state = c_acks (t);
|
||||
else if ((state == NEXT) && !strcmp (s,"ACKD")) state = c_ackd (t);
|
||||
else if ((state == NEXT) && !strcmp (s,"NACK")) state = c_nack (t);
|
||||
else if ((state == AUTH || state == MBOX || state == ITEM) &&
|
||||
!strcmp (s,"QUIT")) {
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
state = DONE; /* done in either case */
|
||||
if (t) goodbye = "- Bogus argument given to QUIT\015\012";
|
||||
else { /* expunge the stream */
|
||||
if (stream && nmsgs) stream = mail_close_full (stream,CL_EXPUNGE);
|
||||
stream = NIL; /* don't repeat it */
|
||||
}
|
||||
}
|
||||
else { /* some other or inappropriate command */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = "- Bogus or out of sequence command\015\012";
|
||||
state = DONE;
|
||||
}
|
||||
}
|
||||
fflush (stdout); /* make sure output blatted */
|
||||
}
|
||||
/* clean up the stream */
|
||||
if (stream) mail_close (stream);
|
||||
sayonara (0);
|
||||
return 0; /* stupid compilers */
|
||||
}
|
||||
|
||||
|
||||
/* Say goodbye
|
||||
* Accepts: exit status
|
||||
*
|
||||
* Does not return
|
||||
*/
|
||||
|
||||
void sayonara (int status)
|
||||
{
|
||||
logouthook_t lgoh = (logouthook_t) mail_parameters (NIL,GET_LOGOUTHOOK,NIL);
|
||||
if (goodbye) { /* have a goodbye message? */
|
||||
fputs (goodbye,stdout);
|
||||
fflush (stdout); /* make sure blatted */
|
||||
}
|
||||
syslog (LOG_INFO,"%s user=%.80s host=%.80s",logout,
|
||||
user ? (char *) user : "???",tcp_clienthost ());
|
||||
/* do logout hook if needed */
|
||||
if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL));
|
||||
_exit (status); /* all done */
|
||||
}
|
||||
|
||||
/* Clock interrupt
|
||||
*/
|
||||
|
||||
void clkint ()
|
||||
{
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = "- Autologout; idle for too long\015\012";
|
||||
logout = "Autologout";
|
||||
state = DONE; /* mark state done in either case */
|
||||
if (!critical) { /* badly host if in critical code */
|
||||
if (stream && !stream->lock) mail_close (stream);
|
||||
stream = NIL;
|
||||
sayonara (1); /* die die die */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Kiss Of Death interrupt
|
||||
*/
|
||||
|
||||
void kodint ()
|
||||
{
|
||||
/* only if in command wait */
|
||||
if (idletime && ((time (0) - idletime) > KODTIMEOUT)) {
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = "- Killed (lost mailbox lock)\015\012";
|
||||
logout = "Killed (lost mailbox lock)";
|
||||
state = DONE; /* mark state done in either case */
|
||||
if (!critical) { /* badly host if in critical code */
|
||||
if (stream && !stream->lock) mail_close (stream);
|
||||
stream = NIL;
|
||||
sayonara (1); /* die die die */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hangup interrupt
|
||||
*/
|
||||
|
||||
void hupint ()
|
||||
{
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = NIL;
|
||||
logout = "Hangup";
|
||||
state = DONE; /* mark state done in either case */
|
||||
if (!critical) { /* badly host if in critical code */
|
||||
if (stream && !stream->lock) mail_close (stream);
|
||||
stream = NIL;
|
||||
sayonara (1); /* die die die */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Termination interrupt
|
||||
*/
|
||||
|
||||
void trmint ()
|
||||
{
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
goodbye = "- Killed (terminated)\015\012";
|
||||
logout = "Killed (terminated)";
|
||||
if (critical) state = DONE; /* mark state done in either case */
|
||||
/* Make no attempt at graceful closure since a shutdown may be in
|
||||
* progress, and we won't have any time to do mail_close() actions.
|
||||
*/
|
||||
else sayonara (1); /* die die die */
|
||||
}
|
||||
|
||||
/* Parse HELO command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_helo (char *t,int argc,char *argv[])
|
||||
{
|
||||
char *s,*u,*p;
|
||||
char tmp[TMPLEN];
|
||||
if ((!(t && *t && (u = strtok (t," ")) && (p = strtok (NIL,"\015\012")))) ||
|
||||
(strlen (p) >= TMPLEN)) { /* get user name and password */
|
||||
fputs ("- Missing user or password\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
/* copy password, handle quoting */
|
||||
for (s = tmp; *p; p++) *s++ = (*p == '\\') ? *++p : *p;
|
||||
*s = '\0'; /* tie off string */
|
||||
pass = cpystr (tmp);
|
||||
if (!(s = strchr (u,':'))) { /* want remote mailbox? */
|
||||
/* no, delimit user from possible admin */
|
||||
if (s = strchr (u,'*')) *s++ = '\0';
|
||||
if (server_login (user = cpystr (u),pass,s,argc,argv)) {
|
||||
syslog (LOG_INFO,"%sLogin user=%.80s host=%.80s",s ? "Admin " : "",
|
||||
user,tcp_clienthost ());
|
||||
return c_fold ("INBOX"); /* local; select INBOX */
|
||||
}
|
||||
}
|
||||
#ifndef DISABLE_POP_PROXY
|
||||
/* can't do if can't log in as anonymous */
|
||||
else if (anonymous_login (argc,argv)) {
|
||||
*s++ = '\0'; /* separate host name from user name */
|
||||
user = cpystr (s); /* note user name */
|
||||
syslog (LOG_INFO,"IMAP login to host=%.80s user=%.80s host=%.80s",u,user,
|
||||
tcp_clienthost ());
|
||||
/* initially remote INBOX */
|
||||
sprintf (tmp,"{%.128s/user=%.128s}INBOX",u,user);
|
||||
/* disable rimap just in case */
|
||||
mail_parameters (NIL,SET_RSHTIMEOUT,0);
|
||||
return c_fold (tmp);
|
||||
}
|
||||
#endif
|
||||
fputs ("- Bad login\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
|
||||
/* Parse FOLD command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_fold (char *t)
|
||||
{
|
||||
unsigned long i,j,flags;
|
||||
char *s = NIL,tmp[2*TMPLEN];
|
||||
NETMBX mb;
|
||||
if (!(t && *t)) { /* make sure there's an argument */
|
||||
fputs ("- Missing mailbox name\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
myusername_full (&flags); /* get user type flags */
|
||||
/* expunge old stream */
|
||||
if (stream && nmsgs) mail_expunge (stream);
|
||||
nmsgs = 0; /* no more messages */
|
||||
if (msg) fs_give ((void **) &msg);
|
||||
#ifndef DISABLE_POP_PROXY
|
||||
if (flags == MU_ANONYMOUS) { /* don't permit proxy to leave IMAP */
|
||||
if (stream) { /* not first time */
|
||||
if (!(stream->mailbox && (s = strchr (stream->mailbox,'}'))))
|
||||
fatal ("bad previous mailbox name");
|
||||
strncpy (tmp,stream->mailbox,i = (++s - stream->mailbox));
|
||||
if (i >= TMPLEN) fatal ("ridiculous network prefix");
|
||||
strcpy (tmp+i,t); /* append mailbox to initial spec */
|
||||
t = tmp;
|
||||
}
|
||||
/* must be net name first time */
|
||||
else if (!mail_valid_net_parse (t,&mb)) fatal ("anonymous folder bogon");
|
||||
}
|
||||
#endif
|
||||
/* open mailbox, note # of messages */
|
||||
if (j = (stream = mail_open (stream,t,NIL)) ? stream->nmsgs : 0) {
|
||||
sprintf (tmp,"1:%lu",j); /* fetch fast information for all messages */
|
||||
mail_fetch_fast (stream,tmp,NIL);
|
||||
msg = (unsigned long *) fs_get ((stream->nmsgs + 1) *
|
||||
sizeof (unsigned long));
|
||||
for (i = 1; i <= j; i++) /* find undeleted messages, add to vector */
|
||||
if (!mail_elt (stream,i)->deleted) msg[++nmsgs] = i;
|
||||
}
|
||||
#ifndef DISABLE_POP_PROXY
|
||||
if (!stream && (flags == MU_ANONYMOUS)) {
|
||||
fputs ("- Bad login\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
#endif
|
||||
printf ("#%lu messages in %s\015\012",nmsgs,stream ? stream->mailbox :
|
||||
"<none>");
|
||||
return MBOX;
|
||||
}
|
||||
|
||||
/* Parse READ command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_read (char *t)
|
||||
{
|
||||
MESSAGECACHE *elt = NIL;
|
||||
if (t && *t) { /* have a message number argument? */
|
||||
/* validity check message number */
|
||||
if (((current = strtoul (t,NIL,10)) < 1) || (current > nmsgs)) {
|
||||
fputs ("- Invalid message number given to READ\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
else if (current > nmsgs) { /* at end of mailbox? */
|
||||
fputs ("=0 No more messages\015\012",stdout);
|
||||
return MBOX;
|
||||
}
|
||||
/* set size if message valid and exists */
|
||||
size = msg[current] ? (elt = mail_elt(stream,msg[current]))->rfc822_size : 0;
|
||||
if (elt) sprintf (status,"Status: %s%s\015\012",
|
||||
elt->seen ? "R" : " ",elt->recent ? " " : "O");
|
||||
else status[0] = '\0'; /* no status */
|
||||
size += strlen (status); /* update size to reflect status */
|
||||
/* display results */
|
||||
printf ("=%lu characters in message %lu\015\012",size + 2,current);
|
||||
return ITEM;
|
||||
}
|
||||
|
||||
|
||||
/* Parse RETR command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_retr (char *t)
|
||||
{
|
||||
unsigned long i,j;
|
||||
STRING *bs;
|
||||
if (t) { /* disallow argument */
|
||||
fputs ("- Bogus argument given to RETR\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
if (size) { /* message size valid? */
|
||||
t = mail_fetch_header (stream,msg[current],NIL,NIL,&i,FT_PEEK);
|
||||
if (i > 2) { /* only if there is something */
|
||||
i -= 2; /* lop off last two octets */
|
||||
while (i) { /* blat the header */
|
||||
if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
|
||||
if (i -= j) t += j; /* advance to incomplete data */
|
||||
}
|
||||
}
|
||||
fputs (status,stdout); /* yes, output message */
|
||||
fputs ("\015\012",stdout); /* delimit header from text */
|
||||
if (t = mail_fetch_text (stream,msg[current],NIL,&i,FT_RETURNSTRINGSTRUCT))
|
||||
while (i) { /* blat the text */
|
||||
if (!(j = fwrite (t,sizeof (char),i,stdout))) return DONE;
|
||||
if (i -= j) t += j; /* advance to incomplete data */
|
||||
}
|
||||
else for (bs = &stream->private.string; i--; )
|
||||
if (putc (SNX (bs),stdout) == EOF) return DONE;
|
||||
fputs ("\015\012",stdout); /* trailer to coddle PCNFS' NFSMAIL */
|
||||
}
|
||||
else return DONE; /* otherwise go away */
|
||||
return NEXT;
|
||||
}
|
||||
|
||||
/* Parse ACKS command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_acks (char *t)
|
||||
{
|
||||
char tmp[TMPLEN];
|
||||
if (t) { /* disallow argument */
|
||||
fputs ("- Bogus argument given to ACKS\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
/* mark message as seen */
|
||||
sprintf (tmp,"%lu",msg[current++]);
|
||||
mail_setflag (stream,tmp,"\\Seen");
|
||||
return c_read (NIL); /* end message reading transaction */
|
||||
}
|
||||
|
||||
|
||||
/* Parse ACKD command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_ackd (char *t)
|
||||
{
|
||||
char tmp[TMPLEN];
|
||||
if (t) { /* disallow argument */
|
||||
fputs ("- Bogus argument given to ACKD\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
/* mark message as seen and deleted */
|
||||
sprintf (tmp,"%lu",msg[current]);
|
||||
mail_setflag (stream,tmp,"\\Seen \\Deleted");
|
||||
msg[current++] = 0; /* mark message as deleted */
|
||||
return c_read (NIL); /* end message reading transaction */
|
||||
}
|
||||
|
||||
|
||||
/* Parse NACK command
|
||||
* Accepts: pointer to command argument
|
||||
* Returns: new state
|
||||
*/
|
||||
|
||||
short c_nack (char *t)
|
||||
{
|
||||
if (t) { /* disallow argument */
|
||||
fputs ("- Bogus argument given to NACK\015\012",stdout);
|
||||
return DONE;
|
||||
}
|
||||
return c_read (NIL); /* end message reading transaction */
|
||||
}
|
||||
|
||||
/* Co-routines from MAIL library */
|
||||
|
||||
|
||||
/* Message matches a search
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_searched (MAILSTREAM *stream,unsigned long msgno)
|
||||
{
|
||||
/* Never called */
|
||||
}
|
||||
|
||||
|
||||
/* Message exists (i.e. there are that many messages in the mailbox)
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_exists (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
/* Can't use this mechanism. POP has no means of notifying the client of
|
||||
new mail during the session. */
|
||||
}
|
||||
|
||||
|
||||
/* Message expunged
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_expunged (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
if (state != DONE) { /* ignore if closing */
|
||||
/* someone else screwed us */
|
||||
goodbye = "- Mailbox expunged from under me!\015\012";
|
||||
if (stream && !stream->lock) mail_close (stream);
|
||||
stream = NIL;
|
||||
sayonara (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Message status changed
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_flags (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
/* This isn't used */
|
||||
}
|
||||
|
||||
|
||||
/* Mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* hierarchy delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
/* This isn't used */
|
||||
}
|
||||
|
||||
|
||||
/* Subscribe mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* hierarchy delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
/* This isn't used */
|
||||
}
|
||||
|
||||
|
||||
/* Mailbox status
|
||||
* Accepts: MAIL stream
|
||||
* mailbox name
|
||||
* mailbox status
|
||||
*/
|
||||
|
||||
void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
||||
{
|
||||
/* This isn't used */
|
||||
}
|
||||
|
||||
/* Notification event
|
||||
* Accepts: MAIL stream
|
||||
* string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
{
|
||||
mm_log (string,errflg); /* just do mm_log action */
|
||||
}
|
||||
|
||||
|
||||
/* Log an event for the user to see
|
||||
* Accepts: string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_log (char *string,long errflg)
|
||||
{
|
||||
switch (errflg) {
|
||||
case NIL: /* information message */
|
||||
case PARSE: /* parse glitch */
|
||||
break; /* too many of these to log */
|
||||
case WARN: /* warning */
|
||||
syslog (LOG_DEBUG,"%s",string);
|
||||
break;
|
||||
case BYE: /* driver broke connection */
|
||||
if (state != DONE) {
|
||||
char tmp[MAILTMPLEN];
|
||||
alarm (0); /* disable all interrupts */
|
||||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN);
|
||||
sprintf (logout = tmp,"Mailbox closed (%.80s)",string);
|
||||
sayonara (1);
|
||||
}
|
||||
break;
|
||||
case ERROR: /* error that broke command */
|
||||
default: /* default should never happen */
|
||||
syslog (LOG_NOTICE,"%s",string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log an event to debugging telemetry
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_dlog (char *string)
|
||||
{
|
||||
/* Not doing anything here for now */
|
||||
}
|
||||
|
||||
|
||||
/* Get user name and password for this host
|
||||
* Accepts: parse of network mailbox name
|
||||
* where to return user name
|
||||
* where to return password
|
||||
* trial count
|
||||
*/
|
||||
|
||||
void mm_login (NETMBX *mb,char *username,char *password,long trial)
|
||||
{
|
||||
/* set user name */
|
||||
strncpy (username,*mb->user ? mb->user : user,NETMAXUSER-1);
|
||||
strncpy (password,pass,255); /* and password */
|
||||
username[NETMAXUSER] = password[255] = '\0';
|
||||
}
|
||||
|
||||
/* About to enter critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_critical (MAILSTREAM *stream)
|
||||
{
|
||||
++critical;
|
||||
}
|
||||
|
||||
|
||||
/* About to exit critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_nocritical (MAILSTREAM *stream)
|
||||
{
|
||||
--critical;
|
||||
}
|
||||
|
||||
|
||||
/* Disk error found
|
||||
* Accepts: stream
|
||||
* system error code
|
||||
* flag indicating that mailbox may be clobbered
|
||||
* Returns: abort flag
|
||||
*/
|
||||
|
||||
long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
|
||||
{
|
||||
if (serious) { /* try your damnest if clobberage likely */
|
||||
syslog (LOG_ALERT,
|
||||
"Retrying after disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
|
||||
user,tcp_clienthost (),
|
||||
(stream && stream->mailbox) ? stream->mailbox : "???",
|
||||
strerror (errcode));
|
||||
alarm (0); /* make damn sure timeout disabled */
|
||||
sleep (60); /* give it some time to clear up */
|
||||
return NIL;
|
||||
}
|
||||
syslog (LOG_ALERT,"Fatal disk error user=%.80s host=%.80s mbx=%.80s: %.80s",
|
||||
user,tcp_clienthost (),
|
||||
(stream && stream->mailbox) ? stream->mailbox : "???",
|
||||
strerror (errcode));
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
/* Log a fatal error event
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_fatal (char *string)
|
||||
{
|
||||
mm_log (string,ERROR); /* shouldn't happen normally */
|
||||
}
|
||||
1082
src/ipopd/ipop3d.c
Normal file
1082
src/ipopd/ipop3d.c
Normal file
File diff suppressed because it is too large
Load Diff
75
src/ipopd/ipopd.8
Normal file
75
src/ipopd/ipopd.8
Normal file
@@ -0,0 +1,75 @@
|
||||
.ig
|
||||
* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
..
|
||||
.TH IPOPD 8 "August 30, 2006"
|
||||
.UC 5
|
||||
.SH NAME
|
||||
IPOPd \- Post Office Protocol server
|
||||
.SH SYNOPSIS
|
||||
.B /usr/etc/ipop2d
|
||||
.PP
|
||||
.B /usr/etc/ipop3d
|
||||
.SH DESCRIPTION
|
||||
.I ipop2d
|
||||
and
|
||||
.I ipop3d
|
||||
are servers which support the
|
||||
.B POP2
|
||||
and
|
||||
.B POP3
|
||||
remote mail access protocols respectively.
|
||||
.I ipop2d
|
||||
and
|
||||
.I ipop3d
|
||||
can also be used by
|
||||
.B POP2
|
||||
and
|
||||
.B POP3
|
||||
clients respecitively to access mailboxes on
|
||||
.B IMAP
|
||||
servers by specifying a login user name in the form <host>:<user>
|
||||
e.g.,
|
||||
.B SERVER.WASHINGTON.EDU:SMITH.
|
||||
.PP
|
||||
These daemons contain CRAM-MD5 and APOP support. See the md5.txt
|
||||
documentation file for additional information.
|
||||
.PP
|
||||
.I ipop2d
|
||||
and
|
||||
.I ipop3d
|
||||
are invoked by the internet server (see
|
||||
.IR inetd (8)),
|
||||
normally for requests to connect to the
|
||||
.B POP
|
||||
port as indicated by the
|
||||
.I /etc/services
|
||||
file (see
|
||||
.IR services (5)).
|
||||
.SH "SEE ALSO"
|
||||
imapd(8)
|
||||
.SH BUGS
|
||||
The
|
||||
.B POP2
|
||||
and
|
||||
.B POP3
|
||||
protocols are intrinsically less flexible than
|
||||
.B IMAP
|
||||
and do not maintain `read' vs `unread' state on the server. As a result,
|
||||
most
|
||||
.B POP
|
||||
based software transfers all the mail from the server to the client and
|
||||
deletes it from the server. This necessarily locks the user into using only
|
||||
a single client.
|
||||
.PP
|
||||
.B POP3
|
||||
does not allow you to specify an alternate folder from the user's default.
|
||||
57
src/ipopd/makefile.nt
Normal file
57
src/ipopd/makefile.nt
Normal file
@@ -0,0 +1,57 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IPOPD Makefile for Windows 9x and Windows NT
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 28 October 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
|
||||
ipopd: ipop2d ipop3d
|
||||
|
||||
ipop2d: $(CCLIENTLIB) ipop2d.obj
|
||||
LINK /NOLOGO ipop2d.obj $(LIBS)
|
||||
|
||||
ipop3d: $(CCLIENTLIB) ipop3d.obj
|
||||
LINK /NOLOGO ipop3d.obj $(LIBS)
|
||||
|
||||
ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
58
src/ipopd/makefile.ntk
Normal file
58
src/ipopd/makefile.ntk
Normal file
@@ -0,0 +1,58 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IPOPD Makefile for Windows 9x and Windows NT + Kerberos
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 28 October 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
K5 = \k5\lib
|
||||
K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
|
||||
LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
ipopd: ipop2d ipop3d
|
||||
|
||||
ipop2d: $(CCLIENTLIB) ipop2d.obj
|
||||
LINK /NOLOGO ipop2d.obj $(LIBS)
|
||||
|
||||
ipop3d: $(CCLIENTLIB) ipop3d.obj
|
||||
LINK /NOLOGO ipop3d.obj $(LIBS)
|
||||
|
||||
ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
56
src/ipopd/makefile.w2k
Normal file
56
src/ipopd/makefile.w2k
Normal file
@@ -0,0 +1,56 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: IPOPD Makefile for Windows 2000/XP
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 28 October 1990
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
|
||||
OSCOMPAT = /DWIN32
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
ipopd: ipop2d ipop3d
|
||||
|
||||
ipop2d: $(CCLIENTLIB) ipop2d.obj
|
||||
LINK /NOLOGO ipop2d.obj $(LIBS)
|
||||
|
||||
ipop3d: $(CCLIENTLIB) ipop3d.obj
|
||||
LINK /NOLOGO ipop3d.obj $(LIBS)
|
||||
|
||||
ipop2d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
ipop3d.obj: $C\mail.h $C\misc.h $C\osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
51
src/mailutil/Makefile
Normal file
51
src/mailutil/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: mailutil Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 2 February 1993
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ../c-client
|
||||
CCLIENTLIB = $C/c-client.a
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = -I$C `cat $C/CFLAGS`
|
||||
LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
|
||||
|
||||
mailutil: $(CCLIENTLIB) mailutil.o
|
||||
$(CC) $(CFLAGS) -o mailutil mailutil.o $(LDFLAGS)
|
||||
|
||||
mailutil.o: $C/mail.h $C/misc.h $C/osdep.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
cd $C;make
|
||||
|
||||
clean:
|
||||
rm -f *.o mailutil
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
264
src/mailutil/mailutil.1
Normal file
264
src/mailutil/mailutil.1
Normal file
@@ -0,0 +1,264 @@
|
||||
.ig
|
||||
* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
..
|
||||
.TH mailutil 1 "March 3, 2008"
|
||||
.SH NAME
|
||||
mailutil - mail utility program
|
||||
.nh
|
||||
.SH SYNTAX
|
||||
.B mailutil command [switches] [arguments]
|
||||
.PP
|
||||
All commands accept the -d, -v, and -u switches in addition to any
|
||||
command-specific switches.
|
||||
.PP
|
||||
.B mailutil check [MAILBOX]
|
||||
.PP
|
||||
.B mailutil create MAILBOX
|
||||
.PP
|
||||
.B mailutil delete MAILBOX
|
||||
.PP
|
||||
.B mailutil rename SOURCE DESTINATION
|
||||
.PP
|
||||
.B mailutil copy [-rw] [-kw] [-ig] SOURCE DESTINATION
|
||||
.PP
|
||||
.B mailutil move [-rw] [-kw] [-ig] SOURCE DESTINATION
|
||||
.PP
|
||||
.B mailutil append [-rw] [-kw] [-ig] SOURCE DESTINATION
|
||||
.PP
|
||||
.B mailutil appenddelete [-rw] [-kw] [-ig] SOURCE DESTINATION
|
||||
.PP
|
||||
.B mailutil prune MAILBOX CRITERIA
|
||||
.PP
|
||||
.B mailutil transfer [-m mode] [-rw] [-kw] [-ig] SOURCE DESTINATION
|
||||
.SH DESCRIPTION
|
||||
.B mailutil
|
||||
replaces the old chkmail, imapcopy, imapmove, imapxfer, mbxcopy,
|
||||
mbxcreat, and mbxcvt programs.
|
||||
.PP
|
||||
.B mailutil check
|
||||
determines whether new mail exists in the given mailbox (the default
|
||||
is INBOX). The number of new messages is defined as the number of
|
||||
messages that have "Recent" status set. If the mailbox contains no
|
||||
new messages,
|
||||
.B mailutil check
|
||||
will indicate that no new mail is present;
|
||||
otherwise, it will report the number of new messages. In either case,
|
||||
it will also indicate the canonical form of the name of the mailbox.
|
||||
.PP
|
||||
.B mailutil create
|
||||
creates a new
|
||||
.I mailbox
|
||||
with the given name. The mailbox name must not already exist. A mailbox
|
||||
can be created in a particular format by prefixing the name with
|
||||
.I #driver.
|
||||
followed by the format name and a
|
||||
.I /
|
||||
character. For example, the command
|
||||
.br
|
||||
mailutil create #driver.mbx/junkmail
|
||||
.br
|
||||
will create a new mailbox named "junkmail" in mbx format.
|
||||
.PP
|
||||
.B mailutil delete
|
||||
deletes an existing
|
||||
.I mailbox
|
||||
with the given name.
|
||||
.PP
|
||||
.B mailutil rename
|
||||
renames an existing mailbox to a new name (which must not already exist).
|
||||
This only works if the old and new names are in the same mail store. A
|
||||
more general means to rename a mailbox is to do a
|
||||
.B mailutil copy
|
||||
of the old name to the new name, followed by a
|
||||
.B mailutil delete
|
||||
of the old name.
|
||||
.PP
|
||||
.B mailutil copy
|
||||
creates a new mailbox and copies messages from the old mailbox to the
|
||||
new mailbox. As in
|
||||
.B mailutil create
|
||||
a mailbox format can be specified with the new mailbox. For example, the
|
||||
command
|
||||
.br
|
||||
mailutil copy INBOX #driver.mbx/INBOX
|
||||
.br
|
||||
will copy messages from your existing INBOX to an mbx-format INBOX.
|
||||
.PP
|
||||
.B mailutil move
|
||||
is similar to
|
||||
.B mailutil copy
|
||||
but in addition will also remove (delete and expunge) the messages from the
|
||||
old mailbox after copying them to the new mailbox.
|
||||
.PP
|
||||
.B mailutil append
|
||||
and
|
||||
.B mailutil appenddelete
|
||||
are similar to
|
||||
.B mailutil copy
|
||||
and
|
||||
.B mailutil move
|
||||
respectively except that they do not create the destination mailbox.
|
||||
.PP
|
||||
.B mailutil prune
|
||||
prunes the mailbox of messages which match certain criteria, which are
|
||||
in the form of IMAP2 (RFC 1176) SEARCH arguments. For example, the
|
||||
command.
|
||||
.br
|
||||
mailutil prune INBOX "before 1-jan-2004"
|
||||
.br
|
||||
will delete and expunge all messages written before January 1, 2004.
|
||||
.PP
|
||||
Note that mailutil implements pruning by deleting the matching messages,
|
||||
and then expunging the mailbox. Consequently, mailutil will also expunge
|
||||
any messages which were deleted at the time of the pruning.
|
||||
.PP
|
||||
.B mailutil transfer
|
||||
copies an entire hierarchy of mailboxes from the named source to the
|
||||
named destination. Mailboxes are created on the destination as
|
||||
needed. Any error in copying messages will cause the transfer to stop.
|
||||
.PP
|
||||
Normally, any error in creation will cause the transfer to stop.
|
||||
However, if
|
||||
.B -m MODE
|
||||
or
|
||||
.B -merge MODE
|
||||
is specified, a merging transfer is performed. The
|
||||
.B MODE
|
||||
argument indicats the type of merge:
|
||||
.PP
|
||||
.B -m[erge] prompt
|
||||
indicates that the user should be asked for an alternative name to create.
|
||||
If creating the new name fails, the user will be asked again.
|
||||
.PP
|
||||
.B -m[erge] append
|
||||
indicates that it's alright to copy the messages into an existing mailbox
|
||||
with that name. If the mailbox does not exist, the user will be prompted
|
||||
for an alternative name.
|
||||
.PP
|
||||
.B -m[erge] suffix=XXXX
|
||||
where XXXX is any string, indicates that an alternative name should be
|
||||
built by appending the given suffix to the name. It that alternative name
|
||||
can't be created, then the user will be prompted for an alternative name.
|
||||
.PP
|
||||
The source hierarchy consists of all mailboxes which start
|
||||
with the given source name. With the exception of a remote system
|
||||
specification (within "{}" braces), the source name is used as the
|
||||
name of the destination. The destination hierarchy is a prefix
|
||||
applied to any new names being created. For example,
|
||||
.br
|
||||
mailutil transfer foo bar
|
||||
.br
|
||||
will copy all mailboxes with names beginning with "foo" to names
|
||||
beginning with "bar" (hence "foobar" will be copied to "barfoobar").
|
||||
Similarly,
|
||||
.br
|
||||
mailutil transfer "{imap.foo.com}" "{imap.bar.com}old/"
|
||||
.br
|
||||
will copy all mailboxes from the imap.foo.com IMAP server to
|
||||
equivalent names starting with "old/" on the imap.bar.com IMAP server.
|
||||
.SH FLAGS
|
||||
The
|
||||
.B -d
|
||||
or
|
||||
.B -debug
|
||||
flag prints full debugging telemetry including protocol operations.
|
||||
.PP
|
||||
The
|
||||
.B -v
|
||||
or
|
||||
.B -verbose
|
||||
flag prints verbose (non-error) telemetry.
|
||||
.PP
|
||||
The
|
||||
.B -u USERID
|
||||
or
|
||||
.B -user USERID
|
||||
switch attempts to become the indicated user. This is for the benefit of
|
||||
system administrators who want to do mailutil operations on a userid that
|
||||
does not normally have shell access.
|
||||
.PP
|
||||
The
|
||||
.B -rw
|
||||
or
|
||||
.B -rwcopy
|
||||
flag causes the source mailbox to be open in readwrite mode rather than
|
||||
readonly mode. Normally, mailutil tries to use readonly mode to avoid
|
||||
altering any flags in the source mailbox, but some mailbox types, e.g.
|
||||
POP3, can't be open in readonly mode.
|
||||
.PP
|
||||
The
|
||||
.B -kw
|
||||
or
|
||||
.B -kwcopy
|
||||
flag causes the keywords of the source mailbox to be created in the
|
||||
destination mailbox. Normally, mailutil does not create keywords in
|
||||
the destination mailbox so only those keywords that are already defined
|
||||
in the destination mailbox will be preserved. Note that some IMAP servers
|
||||
may automatically create keywords, so this flag may not be necessary.
|
||||
.PP
|
||||
The
|
||||
.B -ig
|
||||
or
|
||||
.B -ignore
|
||||
flag causes the keywords of the source mailbox to be ignored completely
|
||||
and no attempt is made to copy them to the destination mailbox.
|
||||
.PP
|
||||
The
|
||||
.B -ig[nore]
|
||||
and
|
||||
.B -kw[copy]
|
||||
flags are mutually exclusive.
|
||||
.SH ARGUMENTS
|
||||
The arguments are standard c-client mailbox names. A
|
||||
variety of mailbox name formats and types of mailboxes are supported
|
||||
by c-client; examples of the most common forms of names are:
|
||||
.PP
|
||||
.I
|
||||
.IP Name 15
|
||||
.I Meaning
|
||||
.IP INBOX
|
||||
primary incoming mail folder on the local system
|
||||
.IP archive/tx-project
|
||||
mail folder named "tx-project" in "archive" subdirectory of local
|
||||
filesystem home directory
|
||||
.IP {imapserver.foo.com}INBOX
|
||||
primary incoming mail folder on IMAP server system
|
||||
"imapserver.foo.com"
|
||||
.IP {imapserver.foo.com}archive/tx-project
|
||||
mail folder named "tx-project" in "archive" subdirectory on IMAP
|
||||
server system "imapserver.foo.com"
|
||||
.IP #news.comp.mail.misc
|
||||
newsgroup "comp.mail.misc" on local filesystem
|
||||
.IP {newserver.foo.com/nntp}comp.mail.misc
|
||||
newsgroup "comp.mail.misc" on NNTP server system "newserver.foo.com"
|
||||
.IP {popserver.foo.com/pop3}
|
||||
mail folder on POP3 server system "popserver.foo.com"
|
||||
.LP
|
||||
See your system manager for more information about the types of
|
||||
mailboxes which are available on your system.
|
||||
.SH RESTRICTIONS
|
||||
You must surround a
|
||||
.I {host}mailbox
|
||||
argument with quotation marks if you run
|
||||
.B mailutil
|
||||
from
|
||||
.IR csh (1)
|
||||
or another shell for which braces have special meaning.
|
||||
.PP
|
||||
You must surround a
|
||||
.I #driver.format/mailbox
|
||||
argument with quotation marks if you run
|
||||
.B mailutil
|
||||
from a shell in which "#" is the comment character.
|
||||
.SH AUTHOR
|
||||
Mark Crispin, MRC@Washington.EDU
|
||||
942
src/mailutil/mailutil.c
Normal file
942
src/mailutil/mailutil.c
Normal file
@@ -0,0 +1,942 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Mail utility
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* UW Technology
|
||||
* University of Washington
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@Washington.EDU
|
||||
*
|
||||
* Date: 2 February 1994
|
||||
* Last Edited: 19 February 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
extern int errno; /* just in case */
|
||||
#include "c-client.h"
|
||||
#ifdef SYSCONFIG /* defined in env_unix.h */
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
/* Globals */
|
||||
|
||||
char *version = "13"; /* edit number */
|
||||
int debugp = NIL; /* flag saying debug */
|
||||
int verbosep = NIL; /* flag saying verbose */
|
||||
int rwcopyp = NIL; /* flag saying readwrite copy (for POP) */
|
||||
int kwcopyp = NIL; /* flag saying keyword copy */
|
||||
int ignorep = NIL; /* flag saying ignore keywords */
|
||||
int critical = NIL; /* flag saying in critical code */
|
||||
int trycreate = NIL; /* [TRYCREATE] seen */
|
||||
char *suffix = NIL; /* suffer merge mode suffix text */
|
||||
int ddelim = -1; /* destination delimiter */
|
||||
FILE *f = NIL;
|
||||
|
||||
/* Usage strings */
|
||||
|
||||
char *usage2 = "usage: %s %s\n\n%s\n";
|
||||
char *usage3 = "usage: %s %s %s\n\n%s\n";
|
||||
char *usgchk = "check [MAILBOX]";
|
||||
char *usgcre = "create MAILBOX";
|
||||
char *usgdel = "delete MAILBOX";
|
||||
char *usgren = "rename SOURCE DESTINATION";
|
||||
char *usgcpymov = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
|
||||
char *usgappdel = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
|
||||
char *usgprn = "prune mailbox SEARCH_CRITERIA";
|
||||
char *usgxfr = "transfer [-rw[copy]] [-kw[copy]] [-ig[nore]] [-m[erge] m] SOURCE DEST";
|
||||
#ifdef SYSCONFIG
|
||||
char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]] [-u[ser] userid] [--]";
|
||||
#else
|
||||
char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]]";
|
||||
#endif
|
||||
|
||||
/* Merge modes */
|
||||
|
||||
#define mPROMPT 1
|
||||
#define mAPPEND 2
|
||||
#define mSUFFIX 3
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
void ms_init (STRING *s,void *data,unsigned long size);
|
||||
char ms_next (STRING *s);
|
||||
void ms_setpos (STRING *s,unsigned long i);
|
||||
int main (int argc,char *argv[]);
|
||||
SEARCHPGM *prune_criteria (char *criteria);
|
||||
int prune_criteria_number (unsigned long *number,char **r);
|
||||
int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
|
||||
int mode);
|
||||
long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
|
||||
STRING **message);
|
||||
|
||||
|
||||
/* Append package */
|
||||
|
||||
typedef struct append_package {
|
||||
MAILSTREAM *stream; /* source stream */
|
||||
unsigned long msgno; /* current message number */
|
||||
unsigned long msgmax; /* maximum message number */
|
||||
char *flags; /* current flags */
|
||||
char *date; /* message internal date */
|
||||
STRING *message; /* stringstruct of message */
|
||||
} APPENDPACKAGE;
|
||||
|
||||
|
||||
/* Message string driver for message stringstructs */
|
||||
|
||||
STRINGDRIVER mstring = {
|
||||
ms_init, /* initialize string structure */
|
||||
ms_next, /* get next byte in string structure */
|
||||
ms_setpos /* set position in string structure */
|
||||
};
|
||||
|
||||
/* Initialize file string structure for file stringstruct
|
||||
* Accepts: string structure
|
||||
* pointer to message data structure
|
||||
* size of string
|
||||
*/
|
||||
|
||||
void ms_init (STRING *s,void *data,unsigned long size)
|
||||
{
|
||||
APPENDPACKAGE *md = (APPENDPACKAGE *) data;
|
||||
s->data = data; /* note stream/msgno and header length */
|
||||
mail_fetch_header (md->stream,md->msgno,NIL,NIL,&s->data1,
|
||||
FT_PREFETCHTEXT|FT_PEEK);
|
||||
#if 0
|
||||
s->size = size; /* message size */
|
||||
#else /* This kludge is necessary because of broken IMAP servers (sigh!) */
|
||||
mail_fetch_text (md->stream,md->msgno,NIL,&s->size,FT_PEEK);
|
||||
s->size += s->data1; /* header + body size */
|
||||
#endif
|
||||
SETPOS (s,0);
|
||||
}
|
||||
|
||||
|
||||
/* Get next character from file stringstruct
|
||||
* Accepts: string structure
|
||||
* Returns: character, string structure chunk refreshed
|
||||
*/
|
||||
|
||||
char ms_next (STRING *s)
|
||||
{
|
||||
char c = *s->curpos++; /* get next byte */
|
||||
SETPOS (s,GETPOS (s)); /* move to next chunk */
|
||||
return c; /* return the byte */
|
||||
}
|
||||
|
||||
|
||||
/* Set string pointer position for file stringstruct
|
||||
* Accepts: string structure
|
||||
* new position
|
||||
*/
|
||||
|
||||
void ms_setpos (STRING *s,unsigned long i)
|
||||
{
|
||||
APPENDPACKAGE *md = (APPENDPACKAGE *) s->data;
|
||||
if (i < s->data1) { /* want header? */
|
||||
s->chunk = mail_fetch_header (md->stream,md->msgno,NIL,NIL,NIL,FT_PEEK);
|
||||
s->chunksize = s->data1; /* header length */
|
||||
s->offset = 0; /* offset is start of message */
|
||||
}
|
||||
else if (i < s->size) { /* want body */
|
||||
s->chunk = mail_fetch_text (md->stream,md->msgno,NIL,NIL,FT_PEEK);
|
||||
s->chunksize = s->size - s->data1;
|
||||
s->offset = s->data1; /* offset is end of header */
|
||||
}
|
||||
else { /* off end of message */
|
||||
s->chunk = NIL; /* make sure that we crack on this then */
|
||||
s->chunksize = 1; /* make sure SNX cracks the right way... */
|
||||
s->offset = i;
|
||||
}
|
||||
/* initial position and size */
|
||||
s->curpos = s->chunk + (i -= s->offset);
|
||||
s->cursize = s->chunksize - i;
|
||||
}
|
||||
|
||||
/* Main program */
|
||||
|
||||
int main (int argc,char *argv[])
|
||||
{
|
||||
MAILSTREAM *source = NIL;
|
||||
MAILSTREAM *dest = NIL;
|
||||
SEARCHPGM *criteria;
|
||||
char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN];
|
||||
unsigned long m,len,curlen,start,last;
|
||||
int i;
|
||||
int merge = NIL;
|
||||
int retcode = 1;
|
||||
int moreswitchp = T;
|
||||
char *cmd = NIL;
|
||||
char *src = NIL;
|
||||
char *dst = NIL;
|
||||
char *pgm = argc ? argv[0] : "mailutil";
|
||||
#include "linkage.c"
|
||||
for (i = 1; i < argc; i++) {
|
||||
s = argv[i]; /* pick up argument */
|
||||
/* parse switches */
|
||||
if (moreswitchp && (*s == '-')) {
|
||||
if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T;
|
||||
else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T;
|
||||
else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T;
|
||||
else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T;
|
||||
else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T;
|
||||
else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) {
|
||||
if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT;
|
||||
else if (!strcmp (s,"append")) merge = mAPPEND;
|
||||
else if (!strncmp (s,"suffix=",7) && s[7]) {
|
||||
merge = mSUFFIX;
|
||||
suffix = cpystr (s+7);
|
||||
}
|
||||
else {
|
||||
printf ("unknown merge option: %s\n",s);
|
||||
exit (retcode);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SYSCONFIG
|
||||
else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) {
|
||||
struct passwd *pw = getpwnam (s = argv[i]);
|
||||
if (!pw) {
|
||||
printf ("unknown user id: %s\n",argv[i]);
|
||||
exit (retcode);
|
||||
}
|
||||
else if (setuid (pw->pw_uid)) {
|
||||
perror ("unable to change user id");
|
||||
exit (retcode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* -- means no more switches, so mailbox
|
||||
name can start with "-" */
|
||||
else if ((s[1] == '-') && !s[2]) moreswitchp = NIL;
|
||||
else {
|
||||
printf ("unknown switch: %s\n",s);
|
||||
exit (retcode);
|
||||
}
|
||||
}
|
||||
else if (!cmd) cmd = s; /* first non-switch is command */
|
||||
else if (!src) src = s; /* second non-switch is source */
|
||||
else if (!dst) dst = s; /* third non-switch is destination */
|
||||
else {
|
||||
printf ("unknown argument: %s\n",s);
|
||||
exit (retcode);
|
||||
}
|
||||
}
|
||||
if (kwcopyp && ignorep) {
|
||||
puts ("-kwcopy and -ignore are mutually exclusive");
|
||||
exit (retcode);
|
||||
}
|
||||
if (!cmd) cmd = ""; /* prevent SEGV */
|
||||
|
||||
if (!strcmp (cmd,"check")) { /* check for new messages */
|
||||
if (!src) src = "INBOX";
|
||||
if (dst || merge || rwcopyp || kwcopyp || ignorep)
|
||||
printf (usage2,pgm,usgchk,stdsw);
|
||||
else if (mail_status (source = (*src == '{') ?
|
||||
mail_open (NIL,src,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)) : NIL,
|
||||
src,SA_MESSAGES | SA_RECENT | SA_UNSEEN))
|
||||
retcode = 0;
|
||||
}
|
||||
else if (!strcmp (cmd,"create")) {
|
||||
if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
|
||||
printf (usage2,pgm,usgcre,stdsw);
|
||||
else if (mail_create (source = (*src == '{') ?
|
||||
mail_open (NIL,src,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)) : NIL,src))
|
||||
retcode = 0;
|
||||
}
|
||||
else if (!strcmp (cmd,"delete")) {
|
||||
if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
|
||||
printf (usage2,pgm,usgdel,stdsw);
|
||||
else if (mail_delete (source = (*src == '{') ?
|
||||
mail_open (NIL,src,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)) : NIL,src))
|
||||
retcode = 0;
|
||||
}
|
||||
else if (!strcmp (cmd,"rename")) {
|
||||
if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep)
|
||||
printf (usage2,pgm,usgren,stdsw);
|
||||
else if (mail_rename (source = (*src == '{') ?
|
||||
mail_open (NIL,src,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)) : NIL,src,dst))
|
||||
retcode = 0;
|
||||
}
|
||||
|
||||
else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) {
|
||||
if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw);
|
||||
else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
|
||||
(debugp ? OP_DEBUG : NIL))) {
|
||||
dest = NIL; /* open destination stream if network */
|
||||
if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)))) {
|
||||
if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) {
|
||||
if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw);
|
||||
else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
|
||||
(debugp ? OP_DEBUG : NIL))) {
|
||||
dest = NIL; /* open destination stream if network */
|
||||
if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL)))) {
|
||||
if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strcmp (cmd,"prune")) {
|
||||
if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep ||
|
||||
!(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw);
|
||||
else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) &&
|
||||
mail_search_full (source,NIL,criteria,SE_FREE)) {
|
||||
for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++)
|
||||
if (mail_elt (source,m)->searched) {
|
||||
if (s) { /* continuing a range? */
|
||||
if (m == last + 1) last = m;
|
||||
else { /* no, end of previous range? */
|
||||
if (last != start) sprintf (t,":%lu,%lu",last,m);
|
||||
/* no, just this message */
|
||||
else sprintf (t,",%lu",m);
|
||||
start = last = m; /* either way, start new range */
|
||||
/* running out of space? */
|
||||
if ((len - (curlen = (t += strlen (t)) - s)) < 20) {
|
||||
fs_resize ((void **) &s,len += MAILTMPLEN);
|
||||
t = s + curlen; /* relocate current pointer */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* first time, start new buffer */
|
||||
s = (char *) fs_get (len = MAILTMPLEN);
|
||||
sprintf (s,"%lu",start = last = m);
|
||||
t = s + strlen (s); /* end of buffer */
|
||||
}
|
||||
}
|
||||
/* finish last range if necessary */
|
||||
if (last != start) sprintf (t,":%lu",last);
|
||||
if (s) { /* delete/expunge any matching messages */
|
||||
mail_flag (source,s,"\\Deleted",ST_SET);
|
||||
m = source->nmsgs; /* get number of messages before purge */
|
||||
mail_expunge (source);
|
||||
printf ("%lu message(s) purged\n",m - source->nmsgs);
|
||||
fs_give ((void **) &s); /* flush buffer */
|
||||
}
|
||||
else puts ("No matching messages, so nothing purged");
|
||||
source = mail_close (source);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strcmp (cmd,"transfer")) {
|
||||
if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw);
|
||||
else if ((*src == '{') && /* open source mailbox */
|
||||
!(source = mail_open (NIL,src,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL))));
|
||||
else if ((*dst == '{') && /* open destination server */
|
||||
!(dest = mail_open (NIL,dst,OP_HALFOPEN |
|
||||
(debugp ? OP_DEBUG : NIL))));
|
||||
else if (!(f = tmpfile ())) puts ("can't open temporary file");
|
||||
else {
|
||||
if (verbosep) puts ("Listing mailboxes...");
|
||||
if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1,
|
||||
dp = strchr (dst,'}') + 1);
|
||||
else {
|
||||
dp = dst;
|
||||
tmp[0] = '\0';
|
||||
}
|
||||
mail_list (dest,tmp,"");
|
||||
rewind (f); /* list all mailboxes matching prefix */
|
||||
if (ddelim < 0) { /* if server failed to give delimiter */
|
||||
puts ("warning: unable to get destination hierarchy delimiter!");
|
||||
ddelim = 0; /* default to none */
|
||||
}
|
||||
if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1,
|
||||
strchr (src,'}') + 1);
|
||||
else strcpy (tmp,src);
|
||||
mail_list (source,tmp,"*");
|
||||
rewind (f);
|
||||
/* read back mailbox names */
|
||||
for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) {
|
||||
if (t = strchr (tmp+1,'\n')) *t = '\0';
|
||||
for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1;
|
||||
*t++ = c= *t1++);
|
||||
for (t1 = dp; *t1; *t++ = *t1++);
|
||||
/* point to name without delim or netspec */
|
||||
t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1;
|
||||
/* src and mbx have different delimiters? */
|
||||
if (ddelim && (ddelim != tmp[0]))
|
||||
while (c = *t1++) { /* swap delimiters then */
|
||||
if (c == ddelim) c = tmp[0] ? tmp[0] : 'x';
|
||||
else if (c == tmp[0]) c = ddelim;
|
||||
*t++ = c;
|
||||
}
|
||||
/* easy case */
|
||||
else while (*t1) *t++ = *t1++;
|
||||
*t++ = '\0';
|
||||
if (verbosep) {
|
||||
printf ("Copying %s\n => %s\n",tmp+1,mbx);
|
||||
fflush (stdout);
|
||||
}
|
||||
if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) |
|
||||
(rwcopyp ? NIL : OP_READONLY))) {
|
||||
if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1;
|
||||
if (source->dtb->flags & DR_LOCAL) source = mail_close (source);
|
||||
}
|
||||
else printf ("can't open source mailbox %s\n",tmp+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version);
|
||||
printf (usage2,pgm,"command [switches] arguments",stdsw);
|
||||
printf ("\nCommands:\n %s\n",usgchk);
|
||||
puts (" ;; report number of messages and new messages");
|
||||
printf (" %s\n",usgcre);
|
||||
puts (" ;; create new mailbox");
|
||||
printf (" %s\n",usgdel);
|
||||
puts (" ;; delete existing mailbox");
|
||||
printf (" %s\n",usgren);
|
||||
puts (" ;; rename mailbox to a new name");
|
||||
printf (" copy %s\n",usgcpymov);
|
||||
printf (" move %s\n",usgcpymov);
|
||||
puts (" ;; create new mailbox and copy/move messages");
|
||||
printf (" append %s\n",usgappdel);
|
||||
printf (" appenddelete %s\n",usgappdel);
|
||||
puts (" ;; copy/move messages to existing mailbox");
|
||||
printf (" %s\n",usgprn);
|
||||
puts (" ;; prune mailbox of messages matching criteria");
|
||||
printf (" %s\n",usgxfr);
|
||||
puts (" ;; copy source hierarchy to destination");
|
||||
puts (" ;; -merge modes are prompt, append, or suffix=xxxx");
|
||||
}
|
||||
/* close streams */
|
||||
if (source) mail_close (source);
|
||||
if (dest) mail_close (dest);
|
||||
exit (retcode);
|
||||
return retcode; /* stupid compilers */
|
||||
}
|
||||
|
||||
/* Pruning criteria, somewhat extended from mail_criteria()
|
||||
* Accepts: criteria
|
||||
* Returns: search program if parse successful, else NIL
|
||||
*/
|
||||
|
||||
SEARCHPGM *prune_criteria (char *criteria)
|
||||
{
|
||||
SEARCHPGM *pgm = NIL;
|
||||
char *criterion,*r,tmp[MAILTMPLEN];
|
||||
int f;
|
||||
if (criteria) { /* only if criteria defined */
|
||||
/* make writeable copy of criteria */
|
||||
criteria = cpystr (criteria);
|
||||
/* for each criterion */
|
||||
for (pgm = mail_newsearchpgm (), criterion = strtok_r (criteria," ",&r);
|
||||
criterion; (criterion = strtok_r (NIL," ",&r))) {
|
||||
f = NIL; /* init then scan the criterion */
|
||||
switch (*ucase (criterion)) {
|
||||
case 'A': /* possible ALL, ANSWERED */
|
||||
if (!strcmp (criterion+1,"LL")) f = T;
|
||||
else if (!strcmp (criterion+1,"NSWERED")) f = pgm->answered = T;
|
||||
break;
|
||||
case 'B': /* possible BCC, BEFORE, BODY */
|
||||
if (!strcmp (criterion+1,"CC"))
|
||||
f = mail_criteria_string (&pgm->bcc,&r);
|
||||
else if (!strcmp (criterion+1,"EFORE"))
|
||||
f = mail_criteria_date (&pgm->before,&r);
|
||||
else if (!strcmp (criterion+1,"ODY"))
|
||||
f = mail_criteria_string (&pgm->body,&r);
|
||||
break;
|
||||
case 'C': /* possible CC */
|
||||
if (!strcmp (criterion+1,"C")) f = mail_criteria_string (&pgm->cc,&r);
|
||||
break;
|
||||
case 'D': /* possible DELETED, DRAFT */
|
||||
if (!strcmp (criterion+1,"ELETED")) f = pgm->deleted = T;
|
||||
else if (!strcmp (criterion+1,"RAFT")) f = pgm->draft = T;
|
||||
break;
|
||||
case 'F': /* possible FLAGGED, FROM */
|
||||
if (!strcmp (criterion+1,"LAGGED")) f = pgm->flagged = T;
|
||||
else if (!strcmp (criterion+1,"ROM"))
|
||||
f = mail_criteria_string (&pgm->from,&r);
|
||||
break;
|
||||
case 'K': /* possible KEYWORD */
|
||||
if (!strcmp (criterion+1,"EYWORD"))
|
||||
f = mail_criteria_string (&pgm->keyword,&r);
|
||||
break;
|
||||
case 'L': /* possible LARGER */
|
||||
if (!strcmp (criterion+1,"ARGER"))
|
||||
f = prune_criteria_number (&pgm->larger,&r);
|
||||
|
||||
case 'N': /* possible NEW */
|
||||
if (!strcmp (criterion+1,"EW")) f = pgm->recent = pgm->unseen = T;
|
||||
break;
|
||||
case 'O': /* possible OLD, ON */
|
||||
if (!strcmp (criterion+1,"LD")) f = pgm->old = T;
|
||||
else if (!strcmp (criterion+1,"N"))
|
||||
f = mail_criteria_date (&pgm->on,&r);
|
||||
break;
|
||||
case 'R': /* possible RECENT */
|
||||
if (!strcmp (criterion+1,"ECENT")) f = pgm->recent = T;
|
||||
break;
|
||||
case 'S': /* possible SEEN, SENT*, SINCE, SMALLER,
|
||||
SUBJECT */
|
||||
if (!strcmp (criterion+1,"EEN")) f = pgm->seen = T;
|
||||
else if (!strncmp (criterion+1,"ENT",3)) {
|
||||
if (!strcmp (criterion+4,"BEFORE"))
|
||||
f = mail_criteria_date (&pgm->sentbefore,&r);
|
||||
else if (!strcmp (criterion+4,"ON"))
|
||||
f = mail_criteria_date (&pgm->senton,&r);
|
||||
else if (!strcmp (criterion+4,"SINCE"))
|
||||
f = mail_criteria_date (&pgm->sentsince,&r);
|
||||
}
|
||||
else if (!strcmp (criterion+1,"INCE"))
|
||||
f = mail_criteria_date (&pgm->since,&r);
|
||||
else if (!strcmp (criterion+1,"MALLER"))
|
||||
f = prune_criteria_number (&pgm->smaller,&r);
|
||||
else if (!strcmp (criterion+1,"UBJECT"))
|
||||
f = mail_criteria_string (&pgm->subject,&r);
|
||||
break;
|
||||
case 'T': /* possible TEXT, TO */
|
||||
if (!strcmp (criterion+1,"EXT"))
|
||||
f = mail_criteria_string (&pgm->text,&r);
|
||||
else if (!strcmp (criterion+1,"O"))
|
||||
f = mail_criteria_string (&pgm->to,&r);
|
||||
break;
|
||||
case 'U': /* possible UN* */
|
||||
if (criterion[1] == 'N') {
|
||||
if (!strcmp (criterion+2,"ANSWERED")) f = pgm->unanswered = T;
|
||||
else if (!strcmp (criterion+2,"DELETED")) f = pgm->undeleted = T;
|
||||
else if (!strcmp (criterion+2,"DRAFT")) f = pgm->undraft = T;
|
||||
else if (!strcmp (criterion+2,"FLAGGED")) f = pgm->unflagged = T;
|
||||
else if (!strcmp (criterion+2,"KEYWORD"))
|
||||
f = mail_criteria_string (&pgm->unkeyword,&r);
|
||||
else if (!strcmp (criterion+2,"SEEN")) f = pgm->unseen = T;
|
||||
}
|
||||
break;
|
||||
default: /* we will barf below */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!f) { /* if can't identify criterion */
|
||||
sprintf (tmp,"Unknown search criterion: %.30s",criterion);
|
||||
MM_LOG (tmp,ERROR);
|
||||
mail_free_searchpgm (&pgm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* no longer need copy of criteria */
|
||||
fs_give ((void **) &criteria);
|
||||
}
|
||||
return pgm;
|
||||
}
|
||||
|
||||
|
||||
/* Parse a number
|
||||
* Accepts: pointer to integer to return
|
||||
* pointer to strtok state
|
||||
* Returns: T if successful, else NIL
|
||||
*/
|
||||
|
||||
int prune_criteria_number (unsigned long *number,char **r)
|
||||
{
|
||||
char *t;
|
||||
STRINGLIST *s = NIL;
|
||||
/* parse the date and return fn if OK */
|
||||
int ret = (mail_criteria_string (&s,r) &&
|
||||
(*number = strtoul ((char *) s->text.data,&t,10)) && !*t) ?
|
||||
T : NIL;
|
||||
if (s) mail_free_stringlist (&s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Copy mailbox
|
||||
* Accepts: stream open on source
|
||||
* halfopen stream for destination or NIL
|
||||
* destination mailbox name
|
||||
* non-zero to create destination mailbox
|
||||
* non-zero to delete messages from source after copying
|
||||
* merge mode
|
||||
* Returns: T if success, NIL if error
|
||||
*/
|
||||
|
||||
int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
|
||||
int mode)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
APPENDPACKAGE ap;
|
||||
STRING st;
|
||||
char *ndst = NIL;
|
||||
int ret = NIL;
|
||||
trycreate = NIL; /* no TRYCREATE yet */
|
||||
if (create) while (!mail_create (dest,dst) && (mode != mAPPEND)) {
|
||||
switch (mode) {
|
||||
case mPROMPT: /* prompt user for new name */
|
||||
tmp[0] = '\0';
|
||||
while (!tmp[0]) { /* read name */
|
||||
fputs ("alternative name: ",stdout);
|
||||
fflush (stdout);
|
||||
fgets (tmp,MAILTMPLEN-1,stdin);
|
||||
if (s = strchr (tmp,'\n')) *s = '\0';
|
||||
}
|
||||
if (ndst) fs_give ((void **) &ndst);
|
||||
ndst = cpystr (tmp);
|
||||
break;
|
||||
case mSUFFIX: /* try again with new suffix */
|
||||
if (ndst) fs_give ((void **) &ndst);
|
||||
sprintf (ndst = (char *) fs_get (strlen (dst) + strlen (suffix) + 1),
|
||||
"%s%s",dst,suffix);
|
||||
printf ("retry to create %s\n",ndst);
|
||||
mode = mPROMPT; /* switch to prompt mode if name fails */
|
||||
break;
|
||||
case NIL: /* not merging */
|
||||
return NIL;
|
||||
}
|
||||
if (ndst) dst = ndst; /* if alternative name given, use it */
|
||||
}
|
||||
|
||||
if (kwcopyp) {
|
||||
int i;
|
||||
size_t len;
|
||||
char *dummymsg = "Date: Thu, 18 May 2006 00:00 -0700\r\nFrom: dummy@example.com\r\nSubject: dummy\r\n\r\ndummy\r\n";
|
||||
for (i = 0,len = 0; i < NUSERFLAGS; ++i)
|
||||
if (source->user_flags[i]) len += strlen (source->user_flags[i]) + 1;
|
||||
if (len) { /* easy if no user flags to copy... */
|
||||
char *t;
|
||||
char *tail = "\\Deleted)";
|
||||
char *flags = (char *) fs_get (1 + len + strlen (tail) + 1);
|
||||
s = flags; *s++ = '(';
|
||||
for (i = 0; i < NUSERFLAGS; ++i) if (t = source->user_flags[i]) {
|
||||
while (*t) *s++ = *t++;
|
||||
*s++ = ' ';
|
||||
}
|
||||
strcpy (s,tail); /* terminate flags list */
|
||||
if ((dst[0] == '#') && ((dst[1] == 'D') || (dst[1] == 'd')) &&
|
||||
((dst[2] == 'R') || (dst[2] == 'r')) &&
|
||||
((dst[3] == 'I') || (dst[3] == 'i')) &&
|
||||
((dst[4] == 'V') || (dst[4] == 'v')) &&
|
||||
((dst[5] == 'E') || (dst[5] == 'e')) &&
|
||||
((dst[6] == 'R') || (dst[6] == 'r')) && (dst[7] == '.') &&
|
||||
(t = strchr (dst+8,'/'))) ++t;
|
||||
else t = dst;
|
||||
INIT (&st,mail_string,dummymsg,strlen (dummymsg));
|
||||
if (!(mail_append (dest,dst,&st) &&
|
||||
(dest = mail_open (dest,t,debugp ? OP_DEBUG : NIL)))) {
|
||||
fs_give ((void **) &flags);
|
||||
return NIL;
|
||||
}
|
||||
mail_setflag (dest,"*",flags);
|
||||
mail_expunge (dest);
|
||||
fs_give ((void **) &flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (source->nmsgs) { /* non-empty source */
|
||||
if (verbosep) printf ("%s [%lu message(s)] => %s\n",
|
||||
source->mailbox,source->nmsgs,dst);
|
||||
ap.stream = source; /* prepare append package */
|
||||
ap.msgno = 0;
|
||||
ap.msgmax = source->nmsgs;
|
||||
ap.flags = ap.date = NIL;
|
||||
ap.message = &st;
|
||||
/* make sure we have all messages */
|
||||
sprintf (tmp,"1:%lu",ap.msgmax);
|
||||
mail_fetchfast (source,tmp);
|
||||
if (mail_append_multiple (dest,dst,mm_append,(void *) &ap)) {
|
||||
--ap.msgno; /* make sure user knows it won */
|
||||
if (verbosep) printf ("[Ok %lu messages(s)]\n",ap.msgno);
|
||||
if (del && ap.msgno) { /* delete source messages */
|
||||
sprintf (tmp,"1:%lu",ap.msgno);
|
||||
mail_flag (source,tmp,"\\Deleted",ST_SET);
|
||||
/* flush moved messages */
|
||||
mail_expunge (source);
|
||||
}
|
||||
ret = T;
|
||||
}
|
||||
else if ((mode == mAPPEND) && trycreate)
|
||||
ret = mbxcopy (source,dest,dst,create,del,mPROMPT);
|
||||
else if (verbosep) puts ("[Failed]");
|
||||
}
|
||||
else { /* empty source */
|
||||
if (verbosep) printf ("%s [empty] => %s\n",source->mailbox,dst);
|
||||
ret = T;
|
||||
}
|
||||
if (ndst) fs_give ((void **) &ndst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Append callback
|
||||
* Accepts: mail stream
|
||||
* append package
|
||||
* pointer to return flags
|
||||
* pointer to return date
|
||||
* pointer to return message stringstruct
|
||||
* Returns: T on success
|
||||
*/
|
||||
|
||||
long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
|
||||
STRING **message)
|
||||
{
|
||||
char *t,*t1,tmp[MAILTMPLEN];
|
||||
unsigned long u;
|
||||
MESSAGECACHE *elt;
|
||||
APPENDPACKAGE *ap = (APPENDPACKAGE *) data;
|
||||
*flags = *date = NIL; /* assume no flags or date */
|
||||
if (ap->flags) fs_give ((void **) &ap->flags);
|
||||
if (ap->date) fs_give ((void **) &ap->date);
|
||||
mail_gc (ap->stream,GC_TEXTS);
|
||||
if (++ap->msgno <= ap->msgmax) {
|
||||
/* initialize flag string */
|
||||
memset (t = tmp,0,MAILTMPLEN);
|
||||
/* output system flags */
|
||||
if ((elt = mail_elt (ap->stream,ap->msgno))->seen) strcat (t," \\Seen");
|
||||
if (elt->deleted) strcat (t," \\Deleted");
|
||||
if (elt->flagged) strcat (t," \\Flagged");
|
||||
if (elt->answered) strcat (t," \\Answered");
|
||||
if (elt->draft) strcat (t," \\Draft");
|
||||
/* any user flags? */
|
||||
if (!ignorep && (u = elt->user_flags)) do
|
||||
if ((t1 = ap->stream->user_flags[find_rightmost_bit (&u)]) &&
|
||||
(MAILTMPLEN - ((t += strlen (t)) - tmp)) > (long) (2 + strlen (t1))){
|
||||
*t++ = ' '; /* space delimiter */
|
||||
strcpy (t,t1); /* copy the user flag */
|
||||
}
|
||||
while (u); /* until no more user flags */
|
||||
*flags = ap->flags = cpystr (tmp + 1);
|
||||
*date = ap->date = cpystr (mail_date (tmp,elt));
|
||||
*message = ap->message; /* message stringstruct */
|
||||
INIT (ap->message,mstring,(void *) ap,elt->rfc822_size);
|
||||
}
|
||||
else *message = NIL; /* all done */
|
||||
return LONGT;
|
||||
}
|
||||
|
||||
/* Co-routines from MAIL library */
|
||||
|
||||
|
||||
/* Message matches a search
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_searched (MAILSTREAM *stream,unsigned long msgno)
|
||||
{
|
||||
/* dummy routine */
|
||||
}
|
||||
|
||||
|
||||
/* Message exists (i.e. there are that many messages in the mailbox)
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_exists (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
/* dummy routine */
|
||||
}
|
||||
|
||||
|
||||
/* Message expunged
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_expunged (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
/* dummy routine */
|
||||
}
|
||||
|
||||
|
||||
/* Message flags update seen
|
||||
* Accepts: MAIL stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void mm_flags (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
/* dummy routine */
|
||||
}
|
||||
|
||||
/* Mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* hierarchy delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
/* note destination delimiter */
|
||||
if (ddelim < 0) ddelim = delimiter;
|
||||
/* if got a selectable name */
|
||||
else if (!(attributes & LATT_NOSELECT) && *name)
|
||||
fprintf (f,"%c%s\n",delimiter,name);
|
||||
}
|
||||
|
||||
|
||||
/* Subscribe mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* hierarchy delimiter
|
||||
* mailbox name
|
||||
* mailbox attributes
|
||||
*/
|
||||
|
||||
void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
||||
{
|
||||
/* dummy routine */
|
||||
}
|
||||
|
||||
|
||||
/* Mailbox status
|
||||
* Accepts: MAIL stream
|
||||
* mailbox name
|
||||
* mailbox status
|
||||
*/
|
||||
|
||||
void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
||||
{
|
||||
if (status->recent || status->unseen)
|
||||
printf ("%lu new message(s) (%lu unseen),",status->recent,status->unseen);
|
||||
else fputs ("No new messages,",stdout);
|
||||
printf (" %lu total in %s\n",status->messages,mailbox);
|
||||
}
|
||||
|
||||
/* Notification event
|
||||
* Accepts: MAIL stream
|
||||
* string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
{
|
||||
if (!errflg && (string[0] == '[') &&
|
||||
((string[1] == 'T') || (string[1] == 't')) &&
|
||||
((string[2] == 'R') || (string[2] == 'r')) &&
|
||||
((string[3] == 'Y') || (string[3] == 'y')) &&
|
||||
((string[4] == 'C') || (string[4] == 'c')) &&
|
||||
((string[5] == 'R') || (string[5] == 'r')) &&
|
||||
((string[6] == 'E') || (string[6] == 'e')) &&
|
||||
((string[7] == 'A') || (string[7] == 'a')) &&
|
||||
((string[8] == 'T') || (string[8] == 't')) &&
|
||||
((string[9] == 'E') || (string[9] == 'e')) &&
|
||||
(string[10] == ']'))
|
||||
trycreate = T;
|
||||
mm_log (string,errflg); /* just do mm_log action */
|
||||
}
|
||||
|
||||
|
||||
/* Log an event for the user to see
|
||||
* Accepts: string to log
|
||||
* error flag
|
||||
*/
|
||||
|
||||
void mm_log (char *string,long errflg)
|
||||
{
|
||||
switch (errflg) {
|
||||
case BYE:
|
||||
case NIL: /* no error */
|
||||
if (verbosep) fprintf (stderr,"[%s]\n",string);
|
||||
break;
|
||||
case PARSE: /* parsing problem */
|
||||
case WARN: /* warning */
|
||||
fprintf (stderr,"warning: %s\n",string);
|
||||
break;
|
||||
case ERROR: /* error */
|
||||
default:
|
||||
fprintf (stderr,"%s\n",string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Log an event to debugging telemetry
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_dlog (char *string)
|
||||
{
|
||||
fprintf (stderr,"%s\n",string);
|
||||
}
|
||||
|
||||
/* Get user name and password for this host
|
||||
* Accepts: parse of network mailbox name
|
||||
* where to return user name
|
||||
* where to return password
|
||||
* trial count
|
||||
*/
|
||||
|
||||
void mm_login (NETMBX *mb,char *username,char *password,long trial)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
|
||||
if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",
|
||||
strcpy (username,mb->user));
|
||||
if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
|
||||
if (*mb->user) strcat (s = tmp,"} password:");
|
||||
else {
|
||||
printf ("%s} username: ",tmp);
|
||||
fgets (username,NETMAXUSER-1,stdin);
|
||||
username[NETMAXUSER-1] = '\0';
|
||||
if (s = strchr (username,'\n')) *s = '\0';
|
||||
s = "password: ";
|
||||
}
|
||||
strcpy (password,getpass (s));
|
||||
}
|
||||
|
||||
|
||||
/* About to enter critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_critical (MAILSTREAM *stream)
|
||||
{
|
||||
critical = T; /* note in critical code */
|
||||
}
|
||||
|
||||
|
||||
/* About to exit critical code
|
||||
* Accepts: stream
|
||||
*/
|
||||
|
||||
void mm_nocritical (MAILSTREAM *stream)
|
||||
{
|
||||
critical = NIL; /* note not in critical code */
|
||||
}
|
||||
|
||||
|
||||
/* Disk error found
|
||||
* Accepts: stream
|
||||
* system error code
|
||||
* flag indicating that mailbox may be clobbered
|
||||
* Returns: T if user wants to abort
|
||||
*/
|
||||
|
||||
long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
|
||||
{
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
/* Log a fatal error event
|
||||
* Accepts: string to log
|
||||
*/
|
||||
|
||||
void mm_fatal (char *string)
|
||||
{
|
||||
fprintf (stderr,"FATAL: %s\n",string);
|
||||
}
|
||||
50
src/mailutil/makefile.nt
Normal file
50
src/mailutil/makefile.nt
Normal file
@@ -0,0 +1,50 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MAILUTIL Makefile for Windows 9x and Windows NT
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
CFLAGS= -I$C /MT /W3 /DWIN32 /D_WIN32_WINNT=0x0400 -nologo $(EXTRACFLAGS)
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mailutil: $(CCLIENTLIB) mailutil.obj
|
||||
LINK /NOLOGO mailutil.obj $(LIBS)
|
||||
|
||||
mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
51
src/mailutil/makefile.ntk
Normal file
51
src/mailutil/makefile.ntk
Normal file
@@ -0,0 +1,51 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MAILUTIL Makefile for Windows 9x and Windows NT + Kerberos
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
K5 = \k5\lib
|
||||
K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
|
||||
LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mailutil: $(CCLIENTLIB) mailutil.obj
|
||||
LINK /NOLOGO mailutil.obj $(LIBS)
|
||||
|
||||
mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
49
src/mailutil/makefile.w2k
Normal file
49
src/mailutil/makefile.w2k
Normal file
@@ -0,0 +1,49 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MAILUTIL Makefile for Windows 2000/XP
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
|
||||
OSCOMPAT = /DWIN32
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mailutil: $(CCLIENTLIB) mailutil.obj
|
||||
LINK /NOLOGO mailutil.obj $(LIBS)
|
||||
|
||||
mailutil.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mailutil.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
51
src/mlock/Makefile
Normal file
51
src/mlock/Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MLOCK Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 8 February 1999
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ../c-client
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = `cat $C/CFLAGS`
|
||||
|
||||
all: mlock
|
||||
|
||||
mlock: mlock.o
|
||||
$(CC) $(CFLAGS) -o mlock mlock.o
|
||||
|
||||
install: mlock
|
||||
chgrp mail mlock
|
||||
chmod 3711 mlock
|
||||
cp -p mlock /etc/mlock
|
||||
|
||||
clean:
|
||||
rm -f *.o mlock || true
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
175
src/mlock/mlock.c
Normal file
175
src/mlock/mlock.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2008 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Standalone Mailbox Lock program
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 8 February 1999
|
||||
* Last Edited: 3 March 2008
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sysexits.h>
|
||||
#include <syslog.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOCKTIMEOUT 5 /* lock timeout in minutes */
|
||||
#define LOCKPROTECTION 0664
|
||||
|
||||
#ifndef MAXHOSTNAMELEN /* Solaris still sucks */
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
/* Fatal error
|
||||
* Accepts: Message string
|
||||
* exit code
|
||||
* Returns: code
|
||||
*/
|
||||
|
||||
int die (char *msg,int code)
|
||||
{
|
||||
syslog (LOG_NOTICE,"(%u) %s",code,msg);
|
||||
write (1,"?",1); /* indicate "impossible" failure */
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc,char *argv[])
|
||||
{
|
||||
int ld,i;
|
||||
int tries = LOCKTIMEOUT * 60 - 1;
|
||||
char *s,*dir,*file,*lock,*hitch,tmp[1024];
|
||||
size_t dlen,len;
|
||||
struct stat sb,fsb;
|
||||
struct group *grp = getgrnam ("mail");
|
||||
/* get syslog */
|
||||
openlog (argv[0],LOG_PID,LOG_MAIL);
|
||||
if (!grp || (grp->gr_gid != getegid ()))
|
||||
return die ("not setgid mail",EX_USAGE);
|
||||
if (argc != 3) return die ("invalid arguments",EX_USAGE);
|
||||
for (s = argv[1]; *s; s++)
|
||||
if (!isdigit (*s)) return die ("invalid fd",EX_USAGE);
|
||||
/* find directory */
|
||||
if ((*argv[2] != '/') || !(file = strrchr (argv[2],'/')) || !file[1])
|
||||
return die ("invalid path",EX_USAGE);
|
||||
/* calculate lengths of directory and file */
|
||||
if (!(dlen = file - argv[2])) dlen = 1;
|
||||
len = strlen (++file);
|
||||
/* make buffers */
|
||||
dir = (char *) malloc (dlen + 1);
|
||||
lock = (char *) malloc (len + 6);
|
||||
hitch = (char *) malloc (len + 6 + 40 + MAXHOSTNAMELEN);
|
||||
if (!dir || !lock || !hitch) return die ("malloc failure",errno);
|
||||
strncpy (dir,argv[2],dlen); /* connect to desired directory */
|
||||
dir[dlen] = '\0';
|
||||
printf ("dir=%s, file=%s\n",dir,file);
|
||||
chdir (dir);
|
||||
/* get device/inode of file descriptor */
|
||||
if (fstat (atoi (argv[1]),&fsb)) return die ("fstat failure",errno);
|
||||
/* better be a regular file */
|
||||
if ((fsb.st_mode & S_IFMT) != S_IFREG)
|
||||
return die ("fd not regular file",EX_USAGE);
|
||||
/* now get device/inode of file */
|
||||
if (lstat (file,&sb)) return die ("lstat failure",errno);
|
||||
/* does it match? */
|
||||
if ((sb.st_mode & S_IFMT) != S_IFREG)
|
||||
return die ("name not regular file",EX_USAGE);
|
||||
if ((sb.st_dev != fsb.st_dev) || (sb.st_ino != fsb.st_ino))
|
||||
return die ("fd and name different",EX_USAGE);
|
||||
/* build lock filename */
|
||||
sprintf (lock,"%s.lock",file);
|
||||
if (!lstat (lock,&sb) && ((sb.st_mode & S_IFMT) != S_IFREG))
|
||||
return die ("existing lock not regular file",EX_NOPERM);
|
||||
|
||||
do { /* until OK or out of tries */
|
||||
if (!stat (lock,&sb) && (time (0) > (sb.st_ctime + LOCKTIMEOUT * 60)))
|
||||
unlink (lock); /* time out lock if enough time has passed */
|
||||
/* SUN-OS had an NFS
|
||||
* As kludgy as an albatross;
|
||||
* And everywhere that it was installed,
|
||||
* It was a total loss.
|
||||
* -- MRC 9/25/91
|
||||
*/
|
||||
/* build hitching post file name */
|
||||
sprintf (hitch,"%s.%lu.%lu.",lock,(unsigned long) time (0),
|
||||
(unsigned long) getpid ());
|
||||
len = strlen (hitch); /* append local host name */
|
||||
gethostname (hitch + len,MAXHOSTNAMELEN);
|
||||
/* try to get hitching-post file */
|
||||
if ((ld = open (hitch,O_WRONLY|O_CREAT|O_EXCL,LOCKPROTECTION)) >= 0) {
|
||||
/* make sure others can break the lock */
|
||||
chmod (hitch,LOCKPROTECTION);
|
||||
/* get device/inode of hitch file */
|
||||
if (fstat (ld,&fsb)) return die ("hitch fstat failure",errno);
|
||||
close (ld); /* close the hitching-post */
|
||||
/* Note: link() may return an error even if it actually succeeded. So we
|
||||
* always check for success via the link count, and ignore the error if
|
||||
* the link count is right.
|
||||
*/
|
||||
/* tie hitching-post to lock */
|
||||
i = link (hitch,lock) ? errno : 0;
|
||||
/* success if link count now 2 */
|
||||
if (stat (hitch,&sb) || (sb.st_nlink != 2) ||
|
||||
(fsb.st_dev != sb.st_dev) || (fsb.st_ino != sb.st_ino)) {
|
||||
ld = -1; /* failed to hitch */
|
||||
if (i == EPERM) { /* was it because links not allowed? */
|
||||
/* Probably a FAT filesystem on Linux. It can't be NFS, so try
|
||||
* creating the lock file directly.
|
||||
*/
|
||||
if ((ld = open (lock,O_WRONLY|O_CREAT|O_EXCL,LOCKPROTECTION)) >= 0) {
|
||||
/* get device/inode of lock file */
|
||||
if (fstat (ld,&fsb)) return die ("lock fstat failure",errno);
|
||||
close (ld); /* close the file */
|
||||
}
|
||||
/* give up immediately if protection failure */
|
||||
else if (errno != EEXIST) tries = 0;
|
||||
}
|
||||
}
|
||||
unlink (hitch); /* flush hitching post */
|
||||
}
|
||||
/* give up immediately if protection failure */
|
||||
else if (errno == EACCES) tries = 0;
|
||||
if (ld < 0) { /* lock failed */
|
||||
if (tries--) sleep (1); /* sleep 1 second and try again */
|
||||
else {
|
||||
write (1,"-",1); /* hard failure */
|
||||
return EX_CANTCREAT;
|
||||
}
|
||||
}
|
||||
} while (ld < 0);
|
||||
write (1,"+",1); /* indicate that all is well */
|
||||
read (0,tmp,1); /* read continue signal from parent */
|
||||
/* flush the lock file */
|
||||
if (!stat (lock,&sb) && (fsb.st_dev == sb.st_dev) &&
|
||||
(fsb.st_ino == sb.st_ino)) unlink (lock);
|
||||
else syslog (LOG_NOTICE,"lock file %s/%s changed dev/inode",dir,lock);
|
||||
return EX_OK;
|
||||
}
|
||||
53
src/mtest/Makefile
Normal file
53
src/mtest/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MTEST Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ../c-client
|
||||
CCLIENTLIB = $C/c-client.a
|
||||
SHELL = /bin/sh
|
||||
|
||||
# Get local definitions from c-client directory
|
||||
|
||||
CC = `cat $C/CCTYPE`
|
||||
CFLAGS = -I$C `cat $C/CFLAGS`
|
||||
LDFLAGS = $(CCLIENTLIB) `cat $C/LDFLAGS`
|
||||
|
||||
all: mtest
|
||||
|
||||
mtest: $(CCLIENTLIB) mtest.o
|
||||
$(CC) $(CFLAGS) -o mtest mtest.o $(LDFLAGS)
|
||||
|
||||
mtest.o: $C/mail.h $C/misc.h $C/osdep.h $C/rfc822.h $C/smtp.h $C/nntp.h
|
||||
|
||||
$(CCLIENTLIB):
|
||||
cd $C;make
|
||||
|
||||
clean:
|
||||
rm -f *.o mtest || true
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo 'not war?'
|
||||
49
src/mtest/makefile.nt
Normal file
49
src/mtest/makefile.nt
Normal file
@@ -0,0 +1,49 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MTEST Makefile for Windows 9x and Windows NT
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mtest: $(CCLIENTLIB) mtest.obj
|
||||
LINK /NOLOGO mtest.obj $(LIBS)
|
||||
|
||||
mtest.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mtest.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
51
src/mtest/makefile.ntk
Normal file
51
src/mtest/makefile.ntk
Normal file
@@ -0,0 +1,51 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MTEST Makefile for Windows 9x and Windows NT + Kerberos
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
K5 = \k5\lib
|
||||
K5LIB = $(K5)\comerr32.lib $(K5)\gssapi32.lib $(K5)\krb5_32.lib
|
||||
LIBS = $(CCLIENTLIB) $(K5LIB) ws2_32.lib winmm.lib advapi32.lib
|
||||
OSCOMPAT = /DWIN32 /D_WIN32_WINNT=0x0400
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mtest: $(CCLIENTLIB) mtest.obj
|
||||
LINK /NOLOGO mtest.obj $(LIBS)
|
||||
|
||||
mtest.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mtest.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
53
src/mtest/makefile.os2
Normal file
53
src/mtest/makefile.os2
Normal file
@@ -0,0 +1,53 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MTEST Makefile
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
# Thanks to Nicholas Paul Sheppard who contributed the original version
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Zomf
|
||||
LD = gcc
|
||||
LDFLAGS = -s -Zomf -Zcrtdll
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\\c-client.lib
|
||||
LIBS = $(CCLIENTLIB) -l socket
|
||||
|
||||
mtest.exe: $(CCLIENTLIB) mtest.obj
|
||||
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
mtest.obj: mtest.c $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h
|
||||
$(CC) $(CFLAGS) -I$C -o $@ -c $<
|
||||
|
||||
clean:
|
||||
if exist *.obj del *.obj
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
49
src/mtest/makefile.w2k
Normal file
49
src/mtest/makefile.w2k
Normal file
@@ -0,0 +1,49 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: MTEST Makefile for Windows 2000/XP
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 25 February 1996
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
C = ..\c-client
|
||||
CCLIENTLIB = $C\cclient.lib
|
||||
LIBS = $(CCLIENTLIB) ws2_32.lib winmm.lib advapi32.lib secur32.lib crypt32.lib
|
||||
OSCOMPAT = /DWIN32
|
||||
VSCOMPAT = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
|
||||
CFLAGS= -I$C /MT /W3 $(OSCOMPAT) $(VSCOMPAT) -nologo $(EXTRACFLAGS)
|
||||
|
||||
mtest: $(CCLIENTLIB) mtest.obj
|
||||
LINK /NOLOGO mtest.obj $(LIBS)
|
||||
|
||||
mtest.obj: $C\mail.h $C\smtp.h $C\misc.h $C\osdep.h mtest.c
|
||||
|
||||
$(CCLIENTLIB):
|
||||
@echo Make c-client first
|
||||
false
|
||||
|
||||
clean:
|
||||
del *.obj *.exe *.lib *.exp || rem
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
love:
|
||||
@echo not war?
|
||||
813
src/mtest/mtest.c
Normal file
813
src/mtest/mtest.c
Normal file
@@ -0,0 +1,813 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Mail library test program
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 8 July 1988
|
||||
* Last Edited: 5 November 2007
|
||||
*
|
||||
* This original version of this file is
|
||||
* Copyright 1988 Stanford University
|
||||
* and was developed in the Symbolic Systems Resources Group of the Knowledge
|
||||
* Systems Laboratory at Stanford University in 1987-88, and was funded by the
|
||||
* Biomedical Research Technology Program of the NationalInstitutes of Health
|
||||
* under grant number RR-00785.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include "c-client.h"
|
||||
#include "imap4r1.h"
|
||||
|
||||
/* Excellent reasons to hate ifdefs, and why my real code never uses them */
|
||||
|
||||
#ifndef unix
|
||||
# define unix 0
|
||||
#endif
|
||||
|
||||
#if unix
|
||||
# define UNIXLIKE 1
|
||||
# define MACOS 0
|
||||
# include <pwd.h>
|
||||
#else
|
||||
# define UNIXLIKE 0
|
||||
# ifdef noErr
|
||||
# define MACOS 1
|
||||
# include <Memory.h>
|
||||
# else
|
||||
# define MACOS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char *curhst = NIL; /* currently connected host */
|
||||
char *curusr = NIL; /* current login user */
|
||||
char personalname[MAILTMPLEN]; /* user's personal name */
|
||||
|
||||
static char *hostlist[] = { /* SMTP server host list */
|
||||
"mailhost",
|
||||
"localhost",
|
||||
NIL
|
||||
};
|
||||
|
||||
static char *newslist[] = { /* Netnews server host list */
|
||||
"news",
|
||||
NIL
|
||||
};
|
||||
|
||||
int main (void);
|
||||
void mm (MAILSTREAM *stream,long debug);
|
||||
void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
|
||||
unsigned long msgno);
|
||||
void header (MAILSTREAM *stream,long msgno);
|
||||
void display_body (BODY *body,char *pfx,long i);
|
||||
void status (MAILSTREAM *stream);
|
||||
void prompt (char *msg,char *txt);
|
||||
void smtptest (long debug);
|
||||
|
||||
/* Main program - initialization */
|
||||
|
||||
int main ()
|
||||
{
|
||||
MAILSTREAM *stream = NIL;
|
||||
void *sdb = NIL;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
long debug;
|
||||
#include "linkage.c"
|
||||
#if MACOS
|
||||
{
|
||||
size_t *base = (size_t *) 0x000908;
|
||||
/* increase stack size on a Mac */
|
||||
SetApplLimit ((Ptr) (*base - (size_t) 65535L));
|
||||
}
|
||||
#endif
|
||||
curusr = cpystr (((s = myusername ()) && *s) ? s : "somebody");
|
||||
#if UNIXLIKE
|
||||
{
|
||||
char *suffix;
|
||||
struct passwd *pwd = getpwnam (curusr);
|
||||
if (pwd) {
|
||||
strcpy (tmp,pwd->pw_gecos);
|
||||
/* dyke out the office and phone poop */
|
||||
if (suffix = strchr (tmp,',')) suffix[0] = '\0';
|
||||
strcpy (personalname,tmp);/* make a permanent copy of it */
|
||||
}
|
||||
else personalname[0] = '\0';
|
||||
}
|
||||
#else
|
||||
personalname[0] = '\0';
|
||||
#endif
|
||||
curhst = cpystr (mylocalhost ());
|
||||
puts ("MTest -- C client test program");
|
||||
if (!*personalname) prompt ("Personal name: ",personalname);
|
||||
/* user wants protocol telemetry? */
|
||||
prompt ("Debug protocol (y/n)?",tmp);
|
||||
ucase (tmp);
|
||||
debug = (tmp[0] == 'Y') ? T : NIL;
|
||||
do {
|
||||
prompt ("Mailbox ('?' for help): ",tmp);
|
||||
if (!strcmp (tmp,"?")) {
|
||||
puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
|
||||
puts ("Known local mailboxes:");
|
||||
mail_list (NIL,NIL,"%");
|
||||
if (s = sm_read (&sdb)) {
|
||||
puts ("Local subscribed mailboxes:");
|
||||
do (mm_lsub (NIL,NIL,s,NIL));
|
||||
while (s = sm_read (&sdb));
|
||||
}
|
||||
puts ("or just hit return to quit");
|
||||
}
|
||||
else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
|
||||
} while (!stream && tmp[0]);
|
||||
mm (stream,debug); /* run user interface if opened */
|
||||
#if MACOS
|
||||
/* clean up resolver */
|
||||
if (resolveropen) CloseResolver ();
|
||||
#endif
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* MM command loop
|
||||
* Accepts: MAIL stream
|
||||
*/
|
||||
|
||||
void mm (MAILSTREAM *stream,long debug)
|
||||
{
|
||||
void *sdb = NIL;
|
||||
char cmd[MAILTMPLEN];
|
||||
char *s,*arg;
|
||||
unsigned long i;
|
||||
unsigned long last = 0;
|
||||
BODY *body;
|
||||
status (stream); /* first report message status */
|
||||
while (stream) {
|
||||
prompt ("MTest>",cmd); /* prompt user, get command */
|
||||
/* get argument */
|
||||
if (arg = strchr (cmd,' ')) *arg++ = '\0';
|
||||
switch (*ucase (cmd)) { /* dispatch based on command */
|
||||
case 'B': /* Body command */
|
||||
if (arg) last = atoi (arg);
|
||||
else if (!last) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
if (last && (last <= stream->nmsgs)) {
|
||||
mail_fetchstructure (stream,last,&body);
|
||||
if (body) display_body (body,NIL,(long) 0);
|
||||
else puts ("%No body information available");
|
||||
}
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'C': /* Check command */
|
||||
mail_check (stream);
|
||||
status (stream);
|
||||
break;
|
||||
case 'D': /* Delete command */
|
||||
if (arg) last = atoi (arg);
|
||||
else {
|
||||
if (last == 0) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
arg = cmd;
|
||||
sprintf (arg,"%lu",last);
|
||||
}
|
||||
if (last && (last <= stream->nmsgs))
|
||||
mail_setflag (stream,arg,"\\DELETED");
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'E': /* Expunge command */
|
||||
mail_expunge (stream);
|
||||
last = 0;
|
||||
break;
|
||||
case 'F': /* Find command */
|
||||
if (!arg) {
|
||||
arg = "%";
|
||||
if (s = sm_read (&sdb)) {
|
||||
puts ("Local network subscribed mailboxes:");
|
||||
do if (*s == '{') (mm_lsub (NIL,NIL,s,NIL));
|
||||
while (s = sm_read (&sdb));
|
||||
}
|
||||
}
|
||||
puts ("Subscribed mailboxes:");
|
||||
mail_lsub (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
|
||||
NIL,arg);
|
||||
puts ("Known mailboxes:");
|
||||
mail_list (((arg[0] == '{') && (*stream->mailbox == '{')) ? stream : NIL,
|
||||
NIL,arg);
|
||||
break;
|
||||
case 'G':
|
||||
mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
|
||||
break;
|
||||
case 'H': /* Headers command */
|
||||
if (arg) {
|
||||
if (!(last = atoi (arg))) {
|
||||
mail_search (stream,arg);
|
||||
for (i = 1; i <= stream->nmsgs; ++i)
|
||||
if (mail_elt (stream,i)->searched) header (stream,i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (last == 0) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
if (last && (last <= stream->nmsgs)) header (stream,last);
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'L': /* Literal command */
|
||||
if (arg) last = atoi (arg);
|
||||
else if (!last) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
if (last && (last <= stream->nmsgs))
|
||||
puts (mail_fetch_message (stream,last,NIL,NIL));
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'M':
|
||||
mail_status (NIL,arg ? arg : stream->mailbox,
|
||||
SA_MESSAGES|SA_RECENT|SA_UNSEEN|SA_UIDNEXT|SA_UIDVALIDITY);
|
||||
break;
|
||||
case 'N': /* New mailbox command */
|
||||
if (!arg) {
|
||||
puts ("?Missing mailbox");
|
||||
break;
|
||||
}
|
||||
/* get the new mailbox */
|
||||
while (!(stream = mail_open (stream,arg,debug))) {
|
||||
prompt ("Mailbox: ",arg);
|
||||
if (!arg[0]) break;
|
||||
}
|
||||
last = 0;
|
||||
status (stream);
|
||||
break;
|
||||
case 'O': /* Overview command */
|
||||
if (!arg) {
|
||||
puts ("?Missing UID");
|
||||
break;
|
||||
}
|
||||
mail_fetch_overview (stream,arg,overview_header);
|
||||
break;
|
||||
case 'P': /* Ping command */
|
||||
mail_ping (stream);
|
||||
status (stream);
|
||||
break;
|
||||
case 'Q': /* Quit command */
|
||||
mail_close (stream);
|
||||
stream = NIL;
|
||||
break;
|
||||
case 'S': /* Send command */
|
||||
smtptest (debug);
|
||||
break;
|
||||
case '\0': /* null command (type next message) */
|
||||
if (!last || (last++ >= stream->nmsgs)) {
|
||||
puts ("%No next message");
|
||||
break;
|
||||
}
|
||||
case 'T': /* Type command */
|
||||
if (arg) last = atoi (arg);
|
||||
else if (!last) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
if (last && (last <= stream->nmsgs)) {
|
||||
STRINGLIST *lines = mail_newstringlist ();
|
||||
STRINGLIST *cur = lines;
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("Date")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("From")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr (">From")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("Subject")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("To")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("cc")));
|
||||
cur = cur->next = mail_newstringlist ();
|
||||
cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
|
||||
cpystr ("Newsgroups")));
|
||||
printf ("%s",mail_fetchheader_full (stream,last,lines,NIL,NIL));
|
||||
puts (mail_fetchtext (stream,last));
|
||||
mail_free_stringlist (&lines);
|
||||
}
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'U': /* Undelete command */
|
||||
if (arg) last = atoi (arg);
|
||||
else {
|
||||
if (!last) {
|
||||
puts ("?Missing message number");
|
||||
break;
|
||||
}
|
||||
arg = cmd;
|
||||
sprintf (arg,"%lu",last);
|
||||
}
|
||||
if (last > 0 && last <= stream->nmsgs)
|
||||
mail_clearflag (stream,arg,"\\DELETED");
|
||||
else puts ("?Bad message number");
|
||||
break;
|
||||
case 'X': /* Xit command */
|
||||
mail_expunge (stream);
|
||||
mail_close (stream);
|
||||
stream = NIL;
|
||||
break;
|
||||
case '+':
|
||||
mail_debug (stream); debug = T;
|
||||
break;
|
||||
case '-':
|
||||
mail_nodebug (stream); debug = NIL;
|
||||
break;
|
||||
case '?': /* ? command */
|
||||
puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Literal,");
|
||||
puts (" MailboxStatus, New Mailbox, Overview, Ping, Quit, Send, Type,");
|
||||
puts ("Undelete, Xit, +, -, or <RETURN> for next message");
|
||||
break;
|
||||
default: /* bogus command */
|
||||
printf ("?Unrecognized command: %s\n",cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MM display header
|
||||
* Accepts: IMAP2 stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void overview_header (MAILSTREAM *stream,unsigned long uid,OVERVIEW *ov,
|
||||
unsigned long msgno)
|
||||
{
|
||||
if (ov) {
|
||||
unsigned long i;
|
||||
char *t,tmp[MAILTMPLEN];
|
||||
ADDRESS *adr;
|
||||
MESSAGECACHE *elt = mail_elt (stream,msgno);
|
||||
MESSAGECACHE selt;
|
||||
tmp[0] = elt->recent ? (elt->seen ? 'R': 'N') : ' ';
|
||||
tmp[1] = (elt->recent | elt->seen) ? ' ' : 'U';
|
||||
tmp[2] = elt->flagged ? 'F' : ' ';
|
||||
tmp[3] = elt->answered ? 'A' : ' ';
|
||||
tmp[4] = elt->deleted ? 'D' : ' ';
|
||||
mail_parse_date (&selt,ov->date);
|
||||
sprintf (tmp+5,"%4lu) ",elt->msgno);
|
||||
mail_date (tmp+11,&selt);
|
||||
tmp[17] = ' ';
|
||||
tmp[18] = '\0';
|
||||
memset (tmp+18,' ',(size_t) 20);
|
||||
tmp[38] = '\0'; /* tie off with null */
|
||||
/* get first from address from envelope */
|
||||
for (adr = ov->from; adr && !adr->host; adr = adr->next);
|
||||
if (adr) { /* if a personal name exists use it */
|
||||
if (!(t = adr->personal))
|
||||
sprintf (t = tmp+400,"%s@%s",adr->mailbox,adr->host);
|
||||
memcpy (tmp+18,t,(size_t) min (20,(long) strlen (t)));
|
||||
}
|
||||
strcat (tmp," ");
|
||||
if (i = elt->user_flags) {
|
||||
strcat (tmp,"{");
|
||||
while (i) {
|
||||
strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
|
||||
if (i) strcat (tmp," ");
|
||||
}
|
||||
strcat (tmp,"} ");
|
||||
}
|
||||
sprintf (tmp + strlen (tmp),"%.25s (%lu chars)",
|
||||
ov->subject ? ov->subject : " ",ov->optional.octets);
|
||||
puts (tmp);
|
||||
}
|
||||
else printf ("%%No overview for UID %lu\n",uid);
|
||||
}
|
||||
|
||||
/* MM display header
|
||||
* Accepts: IMAP2 stream
|
||||
* message number
|
||||
*/
|
||||
|
||||
void header (MAILSTREAM *stream,long msgno)
|
||||
{
|
||||
unsigned long i;
|
||||
char tmp[MAILTMPLEN];
|
||||
char *t;
|
||||
MESSAGECACHE *cache = mail_elt (stream,msgno);
|
||||
mail_fetchstructure (stream,msgno,NIL);
|
||||
tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
|
||||
tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
|
||||
tmp[2] = cache->flagged ? 'F' : ' ';
|
||||
tmp[3] = cache->answered ? 'A' : ' ';
|
||||
tmp[4] = cache->deleted ? 'D' : ' ';
|
||||
sprintf (tmp+5,"%4lu) ",cache->msgno);
|
||||
mail_date (tmp+11,cache);
|
||||
tmp[17] = ' ';
|
||||
tmp[18] = '\0';
|
||||
mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
|
||||
strcat (tmp," ");
|
||||
if (i = cache->user_flags) {
|
||||
strcat (tmp,"{");
|
||||
while (i) {
|
||||
strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
|
||||
if (i) strcat (tmp," ");
|
||||
}
|
||||
strcat (tmp,"} ");
|
||||
}
|
||||
mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
|
||||
sprintf (t += strlen (t)," (%lu chars)",cache->rfc822_size);
|
||||
puts (tmp);
|
||||
}
|
||||
|
||||
/* MM display body
|
||||
* Accepts: BODY structure pointer
|
||||
* prefix string
|
||||
* index
|
||||
*/
|
||||
|
||||
void display_body (BODY *body,char *pfx,long i)
|
||||
{
|
||||
char tmp[MAILTMPLEN];
|
||||
char *s = tmp;
|
||||
PARAMETER *par;
|
||||
PART *part; /* multipart doesn't have a row to itself */
|
||||
if (body->type == TYPEMULTIPART) {
|
||||
/* if not first time, extend prefix */
|
||||
if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
|
||||
else tmp[0] = '\0';
|
||||
for (i = 0,part = body->nested.part; part; part = part->next)
|
||||
display_body (&part->body,tmp,i++);
|
||||
}
|
||||
else { /* non-multipart, output oneline descriptor */
|
||||
if (!pfx) pfx = ""; /* dummy prefix if top level */
|
||||
sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
|
||||
if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
|
||||
if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
|
||||
if (par = body->parameter) do
|
||||
sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
|
||||
while (par = par->next);
|
||||
if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
|
||||
switch (body->type) { /* bytes or lines depending upon body type */
|
||||
case TYPEMESSAGE: /* encapsulated message */
|
||||
case TYPETEXT: /* plain text */
|
||||
sprintf (s += strlen (s)," (%lu lines)",body->size.lines);
|
||||
break;
|
||||
default:
|
||||
sprintf (s += strlen (s)," (%lu bytes)",body->size.bytes);
|
||||
break;
|
||||
}
|
||||
puts (tmp); /* output this line */
|
||||
/* encapsulated message? */
|
||||
if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype,"RFC822") &&
|
||||
(body = body->nested.msg->body)) {
|
||||
if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
|
||||
else { /* build encapsulation prefix */
|
||||
sprintf (tmp,"%s%ld.",pfx,i);
|
||||
display_body (body,tmp,(long) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MM status report
|
||||
* Accepts: MAIL stream
|
||||
*/
|
||||
|
||||
void status (MAILSTREAM *stream)
|
||||
{
|
||||
unsigned long i;
|
||||
char *s,date[MAILTMPLEN];
|
||||
THREADER *thr;
|
||||
AUTHENTICATOR *auth;
|
||||
rfc822_date (date);
|
||||
puts (date);
|
||||
if (stream) {
|
||||
if (stream->mailbox)
|
||||
printf (" %s mailbox: %s, %lu messages, %lu recent\n",
|
||||
stream->dtb->name,stream->mailbox,stream->nmsgs,stream->recent);
|
||||
else puts ("%No mailbox is open on this stream");
|
||||
if (stream->user_flags[0]) {
|
||||
printf ("Keywords: %s",stream->user_flags[0]);
|
||||
for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
|
||||
printf (", %s",stream->user_flags[i]);
|
||||
puts ("");
|
||||
}
|
||||
if (!strcmp (stream->dtb->name,"imap")) {
|
||||
if (LEVELIMAP4rev1 (stream)) s = "IMAP4rev1 (RFC 3501)";
|
||||
else if (LEVEL1730 (stream)) s = "IMAP4 (RFC 1730)";
|
||||
else if (LEVELIMAP2bis (stream)) s = "IMAP2bis";
|
||||
else if (LEVEL1176 (stream)) s = "IMAP2 (RFC 1176)";
|
||||
else s = "IMAP2 (RFC 1064)";
|
||||
printf ("%s server %s\n",s,imap_host (stream));
|
||||
if (LEVELIMAP4 (stream)) {
|
||||
if (i = imap_cap (stream)->auth) {
|
||||
s = "";
|
||||
printf ("Mutually-supported SASL mechanisms:");
|
||||
while (auth = mail_lookup_auth (find_rightmost_bit (&i) + 1)) {
|
||||
printf (" %s",auth->name);
|
||||
if (!strcmp (auth->name,"PLAIN"))
|
||||
s = "\n [LOGIN will not be listed here if PLAIN is supported]";
|
||||
}
|
||||
puts (s);
|
||||
}
|
||||
printf ("Supported standard extensions:\n");
|
||||
if (LEVELACL (stream)) puts (" Access Control lists (RFC 2086)");
|
||||
if (LEVELQUOTA (stream)) puts (" Quotas (RFC 2087)");
|
||||
if (LEVELLITERALPLUS (stream))
|
||||
puts (" Non-synchronizing literals (RFC 2088)");
|
||||
if (LEVELIDLE (stream)) puts (" IDLE unsolicited update (RFC 2177)");
|
||||
if (LEVELMBX_REF (stream)) puts (" Mailbox referrals (RFC 2193)");
|
||||
if (LEVELLOG_REF (stream)) puts (" Login referrals (RFC 2221)");
|
||||
if (LEVELANONYMOUS (stream)) puts (" Anonymous access (RFC 2245)");
|
||||
if (LEVELNAMESPACE (stream)) puts (" Multiple namespaces (RFC 2342)");
|
||||
if (LEVELUIDPLUS (stream)) puts (" Extended UID behavior (RFC 2359)");
|
||||
if (LEVELSTARTTLS (stream))
|
||||
puts (" Transport Layer Security (RFC 2595)");
|
||||
if (LEVELLOGINDISABLED (stream))
|
||||
puts (" LOGIN command disabled (RFC 2595)");
|
||||
if (LEVELID (stream))
|
||||
puts (" Implementation identity negotiation (RFC 2971)");
|
||||
if (LEVELCHILDREN (stream))
|
||||
puts (" LIST children announcement (RFC 3348)");
|
||||
if (LEVELMULTIAPPEND (stream))
|
||||
puts (" Atomic multiple APPEND (RFC 3502)");
|
||||
if (LEVELBINARY (stream))
|
||||
puts (" Binary body content (RFC 3516)");
|
||||
if (LEVELUNSELECT (stream)) puts (" Mailbox unselect (RFC 3691)");
|
||||
if (LEVELURLAUTH (stream))
|
||||
puts (" URL authenticated fetch (RFC 4467)");
|
||||
if (LEVELCATENATE (stream)) puts (" Catenation (RFC 4469)");
|
||||
if (LEVELCONDSTORE (stream)) puts (" Conditional STORE (RFC 4551)");
|
||||
if (LEVELESEARCH (stream)) puts (" Extended SEARCH (RFC 4731)");
|
||||
puts ("Supported draft extensions:");
|
||||
if (LEVELSASLIR (stream)) puts (" SASL initial client response");
|
||||
if (LEVELSORT (stream)) puts (" Server-based sorting");
|
||||
if (LEVELTHREAD (stream)) {
|
||||
printf (" Server-based threading:");
|
||||
for (thr = imap_cap (stream)->threader; thr; thr = thr->next)
|
||||
printf (" %s",thr->name);
|
||||
putchar ('\n');
|
||||
}
|
||||
if (LEVELSCAN (stream)) puts (" Mailbox text scan");
|
||||
if (i = imap_cap (stream)->extlevel) {
|
||||
printf ("Supported BODYSTRUCTURE extensions:");
|
||||
switch (i) {
|
||||
case BODYEXTLOC: printf (" location");
|
||||
case BODYEXTLANG: printf (" language");
|
||||
case BODYEXTDSP: printf (" disposition");
|
||||
case BODYEXTMD5: printf (" MD5\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else putchar ('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Prompt user for input
|
||||
* Accepts: pointer to prompt message
|
||||
* pointer to input buffer
|
||||
*/
|
||||
|
||||
void prompt (char *msg,char *txt)
|
||||
{
|
||||
printf ("%s",msg);
|
||||
gets (txt);
|
||||
}
|
||||
|
||||
/* Interfaces to C-client */
|
||||
|
||||
|
||||
void mm_searched (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mm_exists (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mm_expunged (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mm_flags (MAILSTREAM *stream,unsigned long number)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
||||
{
|
||||
mm_log (string,errflg);
|
||||
}
|
||||
|
||||
|
||||
void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
|
||||
{
|
||||
putchar (' ');
|
||||
if (delimiter) putchar (delimiter);
|
||||
else fputs ("NIL",stdout);
|
||||
putchar (' ');
|
||||
fputs (mailbox,stdout);
|
||||
if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
|
||||
if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
|
||||
if (attributes & LATT_MARKED) fputs (", marked",stdout);
|
||||
if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
|
||||
void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
|
||||
{
|
||||
putchar (' ');
|
||||
if (delimiter) putchar (delimiter);
|
||||
else fputs ("NIL",stdout);
|
||||
putchar (' ');
|
||||
fputs (mailbox,stdout);
|
||||
if (attributes & LATT_NOINFERIORS) fputs (", no inferiors",stdout);
|
||||
if (attributes & LATT_NOSELECT) fputs (", no select",stdout);
|
||||
if (attributes & LATT_MARKED) fputs (", marked",stdout);
|
||||
if (attributes & LATT_UNMARKED) fputs (", unmarked",stdout);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
|
||||
void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
||||
{
|
||||
printf (" Mailbox %s",mailbox);
|
||||
if (status->flags & SA_MESSAGES) printf (", %lu messages",status->messages);
|
||||
if (status->flags & SA_RECENT) printf (", %lu recent",status->recent);
|
||||
if (status->flags & SA_UNSEEN) printf (", %lu unseen",status->unseen);
|
||||
if (status->flags & SA_UIDVALIDITY) printf (", %lu UID validity",
|
||||
status->uidvalidity);
|
||||
if (status->flags & SA_UIDNEXT) printf (", %lu next UID",status->uidnext);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
void mm_log (char *string,long errflg)
|
||||
{
|
||||
switch ((short) errflg) {
|
||||
case NIL:
|
||||
printf ("[%s]\n",string);
|
||||
break;
|
||||
case PARSE:
|
||||
case WARN:
|
||||
printf ("%%%s\n",string);
|
||||
break;
|
||||
case ERROR:
|
||||
printf ("?%s\n",string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mm_dlog (char *string)
|
||||
{
|
||||
puts (string);
|
||||
}
|
||||
|
||||
|
||||
void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
if (curhst) fs_give ((void **) &curhst);
|
||||
curhst = (char *) fs_get (1+strlen (mb->host));
|
||||
strcpy (curhst,mb->host);
|
||||
sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
|
||||
if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",strcpy (user,mb->user));
|
||||
if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
|
||||
if (*mb->user) strcat (s = tmp,"} password:");
|
||||
else {
|
||||
printf ("%s} username: ",tmp);
|
||||
fgets (user,NETMAXUSER-1,stdin);
|
||||
user[NETMAXUSER-1] = '\0';
|
||||
if (s = strchr (user,'\n')) *s = '\0';
|
||||
s = "password: ";
|
||||
}
|
||||
if (curusr) fs_give ((void **) &curusr);
|
||||
curusr = cpystr (user);
|
||||
strcpy (pwd,getpass (s));
|
||||
}
|
||||
|
||||
|
||||
void mm_critical (MAILSTREAM *stream)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mm_nocritical (MAILSTREAM *stream)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
|
||||
{
|
||||
#if UNIXLIKE
|
||||
kill (getpid (),SIGSTOP);
|
||||
#else
|
||||
abort ();
|
||||
#endif
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
void mm_fatal (char *string)
|
||||
{
|
||||
printf ("?%s\n",string);
|
||||
}
|
||||
|
||||
/* SMTP tester */
|
||||
|
||||
void smtptest (long debug)
|
||||
{
|
||||
SENDSTREAM *stream = NIL;
|
||||
char line[MAILTMPLEN];
|
||||
char *text = (char *) fs_get (8*MAILTMPLEN);
|
||||
ENVELOPE *msg = mail_newenvelope ();
|
||||
BODY *body = mail_newbody ();
|
||||
msg->from = mail_newaddr ();
|
||||
msg->from->personal = cpystr (personalname);
|
||||
msg->from->mailbox = cpystr (curusr);
|
||||
msg->from->host = cpystr (curhst);
|
||||
msg->return_path = mail_newaddr ();
|
||||
msg->return_path->mailbox = cpystr (curusr);
|
||||
msg->return_path->host = cpystr (curhst);
|
||||
prompt ("To: ",line);
|
||||
rfc822_parse_adrlist (&msg->to,line,curhst);
|
||||
if (msg->to) {
|
||||
prompt ("cc: ",line);
|
||||
rfc822_parse_adrlist (&msg->cc,line,curhst);
|
||||
}
|
||||
else {
|
||||
prompt ("Newsgroups: ",line);
|
||||
if (*line) msg->newsgroups = cpystr (line);
|
||||
else {
|
||||
mail_free_body (&body);
|
||||
mail_free_envelope (&msg);
|
||||
fs_give ((void **) &text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
prompt ("Subject: ",line);
|
||||
msg->subject = cpystr (line);
|
||||
puts (" Msg (end with a line with only a '.'):");
|
||||
body->type = TYPETEXT;
|
||||
*text = '\0';
|
||||
while (gets (line)) {
|
||||
if (line[0] == '.') {
|
||||
if (line[1] == '\0') break;
|
||||
else strcat (text,".");
|
||||
}
|
||||
strcat (text,line);
|
||||
strcat (text,"\015\012");
|
||||
}
|
||||
body->contents.text.data = (unsigned char *) text;
|
||||
body->contents.text.size = strlen (text);
|
||||
rfc822_date (line);
|
||||
msg->date = (char *) fs_get (1+strlen (line));
|
||||
strcpy (msg->date,line);
|
||||
if (msg->to) {
|
||||
puts ("Sending...");
|
||||
if (stream = smtp_open (hostlist,debug)) {
|
||||
if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
|
||||
else printf ("[Failed - %s]\n",stream->reply);
|
||||
}
|
||||
}
|
||||
else {
|
||||
puts ("Posting...");
|
||||
if (stream = nntp_open (newslist,debug)) {
|
||||
if (nntp_mail (stream,msg,body)) puts ("[Ok]");
|
||||
else printf ("[Failed - %s]\n",stream->reply);
|
||||
}
|
||||
}
|
||||
if (stream) smtp_close (stream);
|
||||
else puts ("[Can't open connection to any server]");
|
||||
mail_free_envelope (&msg);
|
||||
mail_free_body (&body);
|
||||
}
|
||||
231
src/osdep/amiga/Makefile
Normal file
231
src/osdep/amiga/Makefile
Normal file
@@ -0,0 +1,231 @@
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
|
||||
# Program: C client makefile for Amiga
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 11 May 1989
|
||||
# Last Edited: 5 November 2006
|
||||
|
||||
|
||||
# Command line build parameters
|
||||
|
||||
EXTRAAUTHENTICATORS=
|
||||
EXTRADRIVERS=mbox
|
||||
PASSWDTYPE=std
|
||||
|
||||
|
||||
# Build parameters normally set by the individual port
|
||||
|
||||
AMICFLAGS=-O -DNO_INLINE_STDARG -Dunix
|
||||
AMILDFLAGS=/pine/libc.a -lamiga -lauto
|
||||
CHECKPW=std
|
||||
LOGINPW=std
|
||||
ACTIVEFILE=/UULib/News/Active
|
||||
SPOOLDIR=/usr/spool
|
||||
MAILSPOOL=/AmiTCP/Mail
|
||||
NEWSSPOOL=/UUNews
|
||||
MD5PWD="/etc/cram-md5.pwd"
|
||||
|
||||
|
||||
# Default formats for creating new mailboxes and for empty mailboxes in the
|
||||
# default namespace; must be set to the associated driver's prototype.
|
||||
#
|
||||
# The CREATEPROTO is the default format for new mailbox creation.
|
||||
# The EMPTYPROTO is the default format for handling zero-byte files.
|
||||
#
|
||||
# Normally, this is set by the individual port.
|
||||
#
|
||||
# NOTE: namespace formats (e.g. mh and news) can not be set as a default format
|
||||
# since they do not exist in the default namespace. Also, it is meaningless to
|
||||
# set certain other formats (e.g. mbx, mx, and mix) as the EMPTYPROTO since
|
||||
# these formats can never be empty files.
|
||||
|
||||
CREATEPROTO=unixproto
|
||||
EMPTYPROTO=unixproto
|
||||
|
||||
|
||||
# Commands possibly overriden by the individual port
|
||||
|
||||
ARRC=ar rc
|
||||
CC=cc
|
||||
LN=cp
|
||||
RANLIB=ranlib
|
||||
RM=rm -f
|
||||
|
||||
|
||||
# Standard distribution build parameters
|
||||
|
||||
DEFAULTAUTHENTICATORS=ext md5 pla log
|
||||
DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
|
||||
CHUNKSIZE=65536
|
||||
|
||||
|
||||
# Normally no need to change any of these
|
||||
|
||||
ARCHIVE=c-client.a
|
||||
BINARIES=mail.o misc.o newsrc.o smanager.o osdep.o utf8.o utf8aux.o \
|
||||
dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
|
||||
rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
|
||||
unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o
|
||||
CFLAGS=$(BASECFLAGS) $(EXTRACFLAGS)
|
||||
MAKE=make
|
||||
MV=mv
|
||||
SHELL=/bin/sh
|
||||
|
||||
|
||||
# Primary build command
|
||||
|
||||
BUILDOPTIONS= EXTRACFLAGS=$(EXTRACFLAGS) EXTRALDFLAGS=$(EXTRALDFLAGS)\
|
||||
EXTRADRIVERS=$(EXTRADRIVERS) EXTRAAUTHENTICATORS=$(EXTRAAUTHENTICATORS)\
|
||||
PASSWDTYPE=$(PASSWDTYPE)
|
||||
BUILD=$(MAKE) build $(BUILDOPTIONS) $(SPECIALS)
|
||||
|
||||
|
||||
# Here if no make argument established
|
||||
|
||||
missing: osdep.h
|
||||
$(MAKE) $(ARCHIVE) CC=`cat CCTYPE` CFLAGS="`cat CFLAGS`"
|
||||
|
||||
osdep.h:
|
||||
@echo You must specify what type of system
|
||||
@false
|
||||
|
||||
|
||||
# Current ports
|
||||
|
||||
ami: # AmigaDOS
|
||||
$(BUILD) OS=$@ \
|
||||
BASECFLAGS="-DOLD $(AMICFLAGS)" \
|
||||
BASELDFLAGS="$(AMILDFLAGS) -lamitcp000" \
|
||||
CC=gcc
|
||||
|
||||
am2: # AmigaDOS with a 68020+
|
||||
$(BUILD) OS=ami \
|
||||
BASECFLAGS="-DOLD -m68020 $(AMICFLAGS)" \
|
||||
BASELDFLAGS="$(AMILDFLAGS) -lamitcp" \
|
||||
CC=gcc
|
||||
|
||||
amn: # AmigaDOS with a 680x0 using "new" socket library
|
||||
$(BUILD) OS=ami \
|
||||
BASELDFLAGS="$(AMILDFLAGS) -lnewamitcp000" \
|
||||
CC=gcc
|
||||
|
||||
ama: # AmigaDOS using AS225R2
|
||||
$(BUILD) OS=ami \
|
||||
MAILSPOOL=/INet/Mail \
|
||||
BASECFLAGS="-m68020 $(AMICFLAGS)" \
|
||||
BASELDFLAGS="$(AMILDFLAGS) -las225r2" \
|
||||
CC=gcc
|
||||
|
||||
# Build it!
|
||||
|
||||
build: clean once ckp$(PASSWDTYPE) $(EXTRAAUTHENTICATORS) $(ARCHIVE)
|
||||
|
||||
$(ARCHIVE): $(BINARIES)
|
||||
$(RM) $(ARCHIVE) || true
|
||||
$(ARRC) $(ARCHIVE) $(BINARIES)
|
||||
$(RANLIB) $(ARCHIVE)
|
||||
|
||||
# Cleanup
|
||||
|
||||
clean:
|
||||
$(RM) *.o linkage.[ch] auths.c $(ARCHIVE) osdep.* *TYPE *FLAGS || true
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
dummy.o: mail.h misc.h osdep.h dummy.h
|
||||
fdstring.o: mail.h misc.h osdep.h fdstring.h
|
||||
flstring.o: mail.h misc.h osdep.h flstring.h
|
||||
imap4r1.o: mail.h misc.h osdep.h imap4r1.h rfc822.h
|
||||
mail.o: mail.h misc.h osdep.h rfc822.h linkage.h
|
||||
mbx.o: mail.h misc.h osdep.h dummy.h
|
||||
mh.o: mail.h misc.h osdep.h mh.h dummy.h
|
||||
mix.o: mail.h misc.h osdep.h dummy.h
|
||||
mx.o: mail.h misc.h osdep.h mx.h dummy.h
|
||||
misc.o: mail.h misc.h osdep.h
|
||||
mmdf.o: mail.h misc.h osdep.h pseudo.h dummy.h
|
||||
mtx.o: mail.h misc.h osdep.h dummy.h
|
||||
netmsg.o: mail.h misc.h osdep.h netmsg.h
|
||||
news.o: mail.h misc.h osdep.h
|
||||
newsrc.o: mail.h misc.h osdep.h newsrc.h
|
||||
nntp.o: mail.h misc.h osdep.h netmsg.h smtp.h nntp.h rfc822.h
|
||||
phile.o: mail.h misc.h osdep.h rfc822.h dummy.h
|
||||
pseudo.o: pseudo.h
|
||||
pop3.o: mail.h misc.h osdep.h pop3.h rfc822.h
|
||||
smanager.o: mail.h misc.h osdep.h
|
||||
smtp.o: mail.h misc.h osdep.h smtp.h rfc822.h
|
||||
rfc822.o: mail.h misc.h osdep.h rfc822.h
|
||||
tenex.o: mail.h misc.h osdep.h dummy.h
|
||||
unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
|
||||
utf8.o: mail.h misc.h osdep.h utf8.h
|
||||
utf8aux.o: mail.h misc.h osdep.h utf8.h
|
||||
|
||||
|
||||
# OS-dependent
|
||||
|
||||
osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
|
||||
osdep.h env_ami.h tcp_ami.h \
|
||||
osdep.c env_ami.c fs_ami.c ftl_ami.c nl_ami.c tcp_ami.c \
|
||||
auths.c gethstid.c \
|
||||
gr_waitp.c \
|
||||
auth_log.c auth_md5.c auth_pla.c \
|
||||
pmatch.c scandir.c \
|
||||
tz_bsd.c \
|
||||
write.c \
|
||||
strerror.c strpbrk.c strstr.c strtok.c strtoul.c \
|
||||
OSCFLAGS
|
||||
$(CC) $(CFLAGS) `cat OSCFLAGS` -c osdep.c
|
||||
|
||||
osdep.c: osdepbas.c osdepckp.c osdeplog.c osdepssl.c
|
||||
$(RM) osdep.c || true
|
||||
cat osdepbas.c osdepckp.c osdeplog.c osdepssl.c > osdep.c
|
||||
|
||||
|
||||
# Once-only environment setup
|
||||
|
||||
once:
|
||||
@echo Once-only environment setup...
|
||||
./drivers $(EXTRADRIVERS) $(DEFAULTDRIVERS) dummy
|
||||
./mkauths $(EXTRAAUTHENTICATORS) $(DEFAULTAUTHENTICATORS)
|
||||
echo $(CC) > CCTYPE
|
||||
echo $(CFLAGS) -DCHUNKSIZE=$(CHUNKSIZE) > CFLAGS
|
||||
echo -DCREATEPROTO=$(CREATEPROTO) -DEMPTYPROTO=$(EMPTYPROTO) \
|
||||
-DMD5ENABLE=\"$(MD5PWD)\" -DMAILSPOOL=\"$(MAILSPOOL)\" \
|
||||
-DACTIVEFILE=\"$(ACTIVEFILE)\" -DNEWSSPOOL=\"$(NEWSSPOOL)\" \
|
||||
-DANONYMOUSHOME=\"$(MAILSPOOL)/anonymous\" > OSCFLAGS
|
||||
echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
|
||||
$(LN) os_$(OS).h osdep.h
|
||||
$(LN) os_$(OS).c osdepbas.c
|
||||
$(LN) log_$(LOGINPW).c osdeplog.c
|
||||
$(LN) ssl_none.c osdepssl.c
|
||||
|
||||
|
||||
# Password checkers
|
||||
|
||||
ckpstd: # Port standard
|
||||
$(LN) ckp_$(CHECKPW).c osdepckp.c
|
||||
|
||||
|
||||
# A monument to a hack of long ago and far away...
|
||||
|
||||
love:
|
||||
@echo not war?
|
||||
42
src/osdep/amiga/ckp_std.c
Normal file
42
src/osdep/amiga/ckp_std.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Standard check password
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Check password
|
||||
* Accepts: login passwd struct
|
||||
* password string
|
||||
* argument count
|
||||
* argument vector
|
||||
* Returns: passwd struct if password validated, NIL otherwise
|
||||
*/
|
||||
|
||||
struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
|
||||
{
|
||||
return (pw->pw_passwd && pw->pw_passwd[0] && pw->pw_passwd[1] &&
|
||||
!strcmp (pw->pw_passwd,(char *) crypt (pass,pw->pw_passwd))) ?
|
||||
pw : NIL;
|
||||
}
|
||||
36
src/osdep/amiga/drivers
Executable file
36
src/osdep/amiga/drivers
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
# ========================================================================
|
||||
# Copyright 1988-2006 University of Washington
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
# Program: Driver Linkage Generator
|
||||
#
|
||||
# Author: Mark Crispin
|
||||
# Networks and Distributed Computing
|
||||
# Computing & Communications
|
||||
# University of Washington
|
||||
# Administration Building, AG-44
|
||||
# Seattle, WA 98195
|
||||
# Internet: MRC@CAC.Washington.EDU
|
||||
#
|
||||
# Date: 11 October 1989
|
||||
# Last Edited: 30 August 2006
|
||||
|
||||
|
||||
# Erase old driver linkage
|
||||
rm -f linkage.[ch]
|
||||
|
||||
# Now define the new list
|
||||
for driver
|
||||
do
|
||||
echo "extern DRIVER "$driver"driver;" >> linkage.h
|
||||
echo " mail_link (&"$driver"driver); /* link in the $driver driver */" | cat >> linkage.c
|
||||
done
|
||||
809
src/osdep/amiga/dummy.c
Normal file
809
src/osdep/amiga/dummy.c
Normal file
@@ -0,0 +1,809 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Dummy routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 9 May 1991
|
||||
* Last Edited: 1 June 2007
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
extern int errno; /* just in case */
|
||||
#include "mail.h"
|
||||
#include "osdep.h"
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "dummy.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
DRIVER *dummy_valid (char *name);
|
||||
void *dummy_parameters (long function,void *value);
|
||||
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents,
|
||||
long level);
|
||||
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
|
||||
long attributes,char *contents);
|
||||
long dummy_subscribe (MAILSTREAM *stream,char *mailbox);
|
||||
MAILSTREAM *dummy_open (MAILSTREAM *stream);
|
||||
void dummy_close (MAILSTREAM *stream,long options);
|
||||
long dummy_ping (MAILSTREAM *stream);
|
||||
void dummy_check (MAILSTREAM *stream);
|
||||
long dummy_expunge (MAILSTREAM *stream,char *sequence,long options);
|
||||
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
|
||||
long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
|
||||
|
||||
/* Dummy routines */
|
||||
|
||||
|
||||
/* Driver dispatch used by MAIL */
|
||||
|
||||
DRIVER dummydriver = {
|
||||
"dummy", /* driver name */
|
||||
DR_LOCAL|DR_MAIL, /* driver flags */
|
||||
(DRIVER *) NIL, /* next driver */
|
||||
dummy_valid, /* mailbox is valid for us */
|
||||
dummy_parameters, /* manipulate parameters */
|
||||
dummy_scan, /* scan mailboxes */
|
||||
dummy_list, /* list mailboxes */
|
||||
dummy_lsub, /* list subscribed mailboxes */
|
||||
dummy_subscribe, /* subscribe to mailbox */
|
||||
NIL, /* unsubscribe from mailbox */
|
||||
dummy_create, /* create mailbox */
|
||||
dummy_delete, /* delete mailbox */
|
||||
dummy_rename, /* rename mailbox */
|
||||
mail_status_default, /* status of mailbox */
|
||||
dummy_open, /* open mailbox */
|
||||
dummy_close, /* close mailbox */
|
||||
NIL, /* fetch message "fast" attributes */
|
||||
NIL, /* fetch message flags */
|
||||
NIL, /* fetch overview */
|
||||
NIL, /* fetch message structure */
|
||||
NIL, /* fetch header */
|
||||
NIL, /* fetch text */
|
||||
NIL, /* fetch message data */
|
||||
NIL, /* unique identifier */
|
||||
NIL, /* message number from UID */
|
||||
NIL, /* modify flags */
|
||||
NIL, /* per-message modify flags */
|
||||
NIL, /* search for message based on criteria */
|
||||
NIL, /* sort messages */
|
||||
NIL, /* thread messages */
|
||||
dummy_ping, /* ping mailbox to see if still alive */
|
||||
dummy_check, /* check for new messages */
|
||||
dummy_expunge, /* expunge deleted messages */
|
||||
dummy_copy, /* copy messages to another mailbox */
|
||||
dummy_append, /* append string message to mailbox */
|
||||
NIL /* garbage collect stream */
|
||||
};
|
||||
|
||||
/* prototype stream */
|
||||
MAILSTREAM dummyproto = {&dummydriver};
|
||||
|
||||
/* Dummy validate mailbox
|
||||
* Accepts: mailbox name
|
||||
* Returns: our driver if name is valid, NIL otherwise
|
||||
*/
|
||||
|
||||
DRIVER *dummy_valid (char *name)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
struct stat sbuf;
|
||||
/* must be valid local mailbox */
|
||||
if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) {
|
||||
/* indeterminate clearbox INBOX */
|
||||
if (!*s) return &dummydriver;
|
||||
else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
case S_IFDIR:
|
||||
return &dummydriver;
|
||||
}
|
||||
/* blackbox INBOX does not exist yet */
|
||||
else if (!compare_cstring (name,"INBOX")) return &dummydriver;
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
/* Dummy manipulate driver parameters
|
||||
* Accepts: function code
|
||||
* function-dependent value
|
||||
* Returns: function-dependent return value
|
||||
*/
|
||||
|
||||
void *dummy_parameters (long function,void *value)
|
||||
{
|
||||
void *ret = NIL;
|
||||
switch ((int) function) {
|
||||
case GET_INBOXPATH:
|
||||
if (value) ret = dummy_file ((char *) value,"INBOX");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Dummy scan mailboxes
|
||||
* Accepts: mail stream
|
||||
* reference
|
||||
* pattern to search
|
||||
* string to scan
|
||||
*/
|
||||
|
||||
void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
|
||||
{
|
||||
DRIVER *drivers;
|
||||
char *s,test[MAILTMPLEN],file[MAILTMPLEN];
|
||||
long i;
|
||||
if (!pat || !*pat) { /* empty pattern? */
|
||||
if (dummy_canonicalize (test,ref,"*")) {
|
||||
/* tie off name at root */
|
||||
if (s = strchr (test,'/')) *++s = '\0';
|
||||
else test[0] = '\0';
|
||||
dummy_listed (stream,'/',test,LATT_NOSELECT,NIL);
|
||||
}
|
||||
}
|
||||
/* get canonical form of name */
|
||||
else if (dummy_canonicalize (test,ref,pat)) {
|
||||
/* found any wildcards? */
|
||||
if (s = strpbrk (test,"%*")) {
|
||||
/* yes, copy name up to that point */
|
||||
strncpy (file,test,i = s - test);
|
||||
file[i] = '\0'; /* tie off */
|
||||
}
|
||||
else strcpy (file,test); /* use just that name then */
|
||||
if (s = strrchr (file,'/')){/* find directory name */
|
||||
*++s = '\0'; /* found, tie off at that point */
|
||||
s = file;
|
||||
}
|
||||
/* silly case */
|
||||
else if ((file[0] == '~') || (file[0] == '#')) s = file;
|
||||
/* do the work */
|
||||
dummy_list_work (stream,s,test,contents,0);
|
||||
/* always an INBOX */
|
||||
if (pmatch ("INBOX",ucase (test))) {
|
||||
/* done if have a dirfmt INBOX */
|
||||
for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL);
|
||||
drivers && !(!(drivers->flags & DR_DISABLE) &&
|
||||
(drivers->flags & DR_DIRFMT) &&
|
||||
(*drivers->valid) ("INBOX")); drivers = drivers->next);
|
||||
/* list INBOX appropriately */
|
||||
dummy_listed (stream,drivers ? '/' : NIL,"INBOX",
|
||||
drivers ? NIL : LATT_NOINFERIORS,contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dummy list mailboxes
|
||||
* Accepts: mail stream
|
||||
* reference
|
||||
* pattern to search
|
||||
*/
|
||||
|
||||
void dummy_list (MAILSTREAM *stream,char *ref,char *pat)
|
||||
{
|
||||
dummy_scan (stream,ref,pat,NIL);
|
||||
}
|
||||
|
||||
/* Dummy list subscribed mailboxes
|
||||
* Accepts: mail stream
|
||||
* reference
|
||||
* pattern to search
|
||||
*/
|
||||
|
||||
void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat)
|
||||
{
|
||||
void *sdb = NIL;
|
||||
char *s,*t,test[MAILTMPLEN],tmp[MAILTMPLEN];
|
||||
int showuppers = pat[strlen (pat) - 1] == '%';
|
||||
/* get canonical form of name */
|
||||
if (dummy_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) do
|
||||
if (*s != '{') {
|
||||
if (!compare_cstring (s,"INBOX") &&
|
||||
pmatch ("INBOX",ucase (strcpy (tmp,test))))
|
||||
mm_lsub (stream,NIL,s,LATT_NOINFERIORS);
|
||||
else if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);
|
||||
else while (showuppers && (t = strrchr (s,'/'))) {
|
||||
*t = '\0'; /* tie off the name */
|
||||
if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,LATT_NOSELECT);
|
||||
}
|
||||
}
|
||||
while (s = sm_read (&sdb)); /* until no more subscriptions */
|
||||
}
|
||||
|
||||
|
||||
/* Dummy subscribe to mailbox
|
||||
* Accepts: mail stream
|
||||
* mailbox to add to subscription list
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_subscribe (MAILSTREAM *stream,char *mailbox)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
struct stat sbuf;
|
||||
/* must be valid local mailbox */
|
||||
if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf))
|
||||
switch (sbuf.st_mode & S_IFMT) {
|
||||
case S_IFDIR: /* allow but snarl */
|
||||
sprintf (tmp,"CLIENT BUG DETECTED: subscribe of non-mailbox directory %.80s",
|
||||
mailbox);
|
||||
MM_NOTIFY (stream,tmp,WARN);
|
||||
case S_IFREG:
|
||||
return sm_subscribe (mailbox);
|
||||
}
|
||||
sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox);
|
||||
MM_LOG (tmp,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* Dummy list mailboxes worker routine
|
||||
* Accepts: mail stream
|
||||
* directory name to search
|
||||
* search pattern
|
||||
* string to scan
|
||||
* search level
|
||||
*/
|
||||
|
||||
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents,
|
||||
long level)
|
||||
{
|
||||
DRIVER *drivers;
|
||||
dirfmttest_t dt;
|
||||
DIR *dp;
|
||||
struct direct *d;
|
||||
struct stat sbuf;
|
||||
char tmp[MAILTMPLEN],path[MAILTMPLEN];
|
||||
size_t len = 0;
|
||||
/* punt if bogus name */
|
||||
if (!mailboxdir (tmp,dir,NIL)) return;
|
||||
if (dp = opendir (tmp)) { /* do nothing if can't open directory */
|
||||
/* see if a non-namespace directory format */
|
||||
for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = NIL;
|
||||
dir && !dt && drivers; drivers = drivers->next)
|
||||
if (!(drivers->flags & DR_DISABLE) && (drivers->flags & DR_DIRFMT) &&
|
||||
(*drivers->valid) (dir))
|
||||
dt = mail_parameters ((*drivers->open) (NIL),GET_DIRFMTTEST,NIL);
|
||||
/* list it if at top-level */
|
||||
if (!level && dir && pmatch_full (dir,pat,'/') && !pmatch (dir,"INBOX"))
|
||||
dummy_listed (stream,'/',dir,dt ? NIL : LATT_NOSELECT,contents);
|
||||
|
||||
/* scan directory, ignore . and .. */
|
||||
if (!dir || dir[(len = strlen (dir)) - 1] == '/') while (d = readdir (dp))
|
||||
if ((!(dt && (*dt) (d->d_name))) &&
|
||||
((d->d_name[0] != '.') ||
|
||||
(((long) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL :
|
||||
(d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]))))) &&
|
||||
((len + strlen (d->d_name)) <= NETMAXMBX)) {
|
||||
/* see if name is useful */
|
||||
if (dir) sprintf (tmp,"%s%s",dir,d->d_name);
|
||||
else strcpy (tmp,d->d_name);
|
||||
/* make sure useful and can get info */
|
||||
if ((pmatch_full (strcpy (path,tmp),pat,'/') ||
|
||||
pmatch_full (strcat (path,"/"),pat,'/') ||
|
||||
dmatch (path,pat,'/')) &&
|
||||
mailboxdir (path,dir,"x") && (len = strlen (path)) &&
|
||||
strcpy (path+len-1,d->d_name) && !stat (path,&sbuf)) {
|
||||
/* only interested in file type */
|
||||
switch (sbuf.st_mode & S_IFMT) {
|
||||
case S_IFDIR: /* directory? */
|
||||
/* form with trailing / */
|
||||
sprintf (path,"%s/",tmp);
|
||||
/* skip listing if INBOX */
|
||||
if (!pmatch (tmp,"INBOX")) {
|
||||
if (pmatch_full (tmp,pat,'/')) {
|
||||
if (!dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents))
|
||||
break;
|
||||
}
|
||||
/* try again with trailing / */
|
||||
else if (pmatch_full (path,pat,'/') &&
|
||||
!dummy_listed (stream,'/',path,LATT_NOSELECT,contents))
|
||||
break;
|
||||
}
|
||||
if (dmatch (path,pat,'/') &&
|
||||
(level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL)))
|
||||
dummy_list_work (stream,path,pat,contents,level+1);
|
||||
break;
|
||||
case S_IFREG: /* ordinary name */
|
||||
/* Must use ctime for systems that don't update mtime properly */
|
||||
if (pmatch_full (tmp,pat,'/') && compare_cstring (tmp,"INBOX"))
|
||||
dummy_listed (stream,'/',tmp,LATT_NOINFERIORS +
|
||||
((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime))?
|
||||
LATT_MARKED : LATT_UNMARKED),contents);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir (dp); /* all done, flush directory */
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan file for contents
|
||||
* Accepts: driver to use
|
||||
* file name
|
||||
* desired contents
|
||||
* length of contents
|
||||
* size of file
|
||||
* Returns: NIL if contents not found, T if found
|
||||
*/
|
||||
|
||||
long scan_contents (DRIVER *dtb,char *name,char *contents,
|
||||
unsigned long csiz,unsigned long fsiz)
|
||||
{
|
||||
scancontents_t sc = dtb ?
|
||||
(scancontents_t) (*dtb->parameters) (GET_SCANCONTENTS,NIL) : NIL;
|
||||
return (*(sc ? sc : dummy_scan_contents)) (name,contents,csiz,fsiz);
|
||||
}
|
||||
|
||||
|
||||
/* Scan file for contents
|
||||
* Accepts: file name
|
||||
* desired contents
|
||||
* length of contents
|
||||
* size of file
|
||||
* Returns: NIL if contents not found, T if found
|
||||
*/
|
||||
|
||||
#define BUFSIZE 4*MAILTMPLEN
|
||||
|
||||
long dummy_scan_contents (char *name,char *contents,unsigned long csiz,
|
||||
unsigned long fsiz)
|
||||
{
|
||||
int fd;
|
||||
unsigned long ssiz,bsiz;
|
||||
char *buf;
|
||||
/* forget it if can't select or open */
|
||||
if ((fd = open (name,O_RDONLY,NIL)) >= 0) {
|
||||
/* get buffer including slop */
|
||||
buf = (char *) fs_get (BUFSIZE + (ssiz = 4 * ((csiz / 4) + 1)) + 1);
|
||||
memset (buf,'\0',ssiz); /* no slop area the first time */
|
||||
while (fsiz) { /* until end of file */
|
||||
read (fd,buf+ssiz,bsiz = min (fsiz,BUFSIZE));
|
||||
if (search ((unsigned char *) buf,bsiz+ssiz,
|
||||
(unsigned char *) contents,csiz)) break;
|
||||
memcpy (buf,buf+BUFSIZE,ssiz);
|
||||
fsiz -= bsiz; /* note that we read that much */
|
||||
}
|
||||
fs_give ((void **) &buf); /* flush buffer */
|
||||
close (fd); /* finished with file */
|
||||
if (fsiz) return T; /* found */
|
||||
}
|
||||
return NIL; /* not found */
|
||||
}
|
||||
|
||||
/* Mailbox found
|
||||
* Accepts: MAIL stream
|
||||
* hierarchy delimiter
|
||||
* mailbox name
|
||||
* attributes
|
||||
* contents to search before calling mm_list()
|
||||
* Returns: NIL if should abort hierarchy search, else T (currently always)
|
||||
*/
|
||||
|
||||
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
|
||||
long attributes,char *contents)
|
||||
{
|
||||
DRIVER *d;
|
||||
DIR *dp;
|
||||
struct direct *dr;
|
||||
dirfmttest_t dt;
|
||||
unsigned long csiz;
|
||||
struct stat sbuf;
|
||||
int nochild;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
if (!(attributes & LATT_NOINFERIORS) && mailboxdir (tmp,name,NIL) &&
|
||||
(dp = opendir (tmp))) { /* if not \NoInferiors */
|
||||
/* locate dirfmttest if any */
|
||||
for (d = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = NIL;
|
||||
!dt && d; d = d->next)
|
||||
if (!(d->flags & DR_DISABLE) && (d->flags & DR_DIRFMT) &&
|
||||
(*d->valid) (name))
|
||||
dt = mail_parameters ((*d->open) (NIL),GET_DIRFMTTEST,NIL);
|
||||
/* scan directory for children */
|
||||
for (nochild = T; nochild && (dr = readdir (dp)); )
|
||||
if ((!(dt && (*dt) (dr->d_name))) &&
|
||||
((dr->d_name[0] != '.') ||
|
||||
(((long) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL :
|
||||
(dr->d_name[1] && ((dr->d_name[1] != '.') || dr->d_name[2])))))
|
||||
nochild = NIL;
|
||||
attributes |= nochild ? LATT_HASNOCHILDREN : LATT_HASCHILDREN;
|
||||
closedir (dp); /* all done, flush directory */
|
||||
}
|
||||
d = NIL; /* don't \NoSelect dir if it has a driver */
|
||||
if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
|
||||
(d != &dummydriver)) attributes &= ~LATT_NOSELECT;
|
||||
if (!contents || /* notify main program */
|
||||
(!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
|
||||
(s = mailboxfile (tmp,name)) &&
|
||||
(*s || (s = mail_parameters (NIL,GET_INBOXPATH,tmp))) &&
|
||||
!stat (s,&sbuf) && (d || (csiz <= sbuf.st_size)) &&
|
||||
SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size)))
|
||||
mm_list (stream,delimiter,name,attributes);
|
||||
return T;
|
||||
}
|
||||
|
||||
/* Dummy create mailbox
|
||||
* Accepts: mail stream
|
||||
* mailbox name to create
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_create (MAILSTREAM *stream,char *mailbox)
|
||||
{
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
long ret = NIL;
|
||||
/* validate name */
|
||||
if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) {
|
||||
sprintf (tmp,"Can't create %.80s: invalid name",mailbox);
|
||||
MM_LOG (tmp,ERROR);
|
||||
}
|
||||
/* create the name, done if made directory */
|
||||
else if ((ret = dummy_create_path (stream,tmp,get_dir_protection(mailbox)))&&
|
||||
(s = strrchr (s,'/')) && !s[1]) return T;
|
||||
return ret ? set_mbx_protections (mailbox,tmp) : NIL;
|
||||
}
|
||||
|
||||
/* Dummy create path
|
||||
* Accepts: mail stream
|
||||
* path name to create
|
||||
* directory mode
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode)
|
||||
{
|
||||
struct stat sbuf;
|
||||
char c,*s,tmp[MAILTMPLEN];
|
||||
int fd;
|
||||
long ret = NIL;
|
||||
char *t = strrchr (path,'/');
|
||||
int wantdir = t && !t[1];
|
||||
int mask = umask (0);
|
||||
if (wantdir) *t = '\0'; /* flush trailing delimiter for directory */
|
||||
if (s = strrchr (path,'/')) { /* found superior to this name? */
|
||||
c = *++s; /* remember first character of inferior */
|
||||
*s = '\0'; /* tie off to get just superior */
|
||||
/* name doesn't exist, create it */
|
||||
if ((stat (path,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
|
||||
!dummy_create_path (stream,path,dirmode)) {
|
||||
umask (mask); /* restore mask */
|
||||
return NIL;
|
||||
}
|
||||
*s = c; /* restore full name */
|
||||
}
|
||||
if (wantdir) { /* want to create directory? */
|
||||
ret = !mkdir (path,(int) dirmode);
|
||||
*t = '/'; /* restore directory delimiter */
|
||||
}
|
||||
/* create file */
|
||||
else if ((fd = open (path,O_WRONLY|O_CREAT|O_EXCL,
|
||||
(long) mail_parameters(NIL,GET_MBXPROTECTION,NIL))) >=0)
|
||||
ret = !close (fd);
|
||||
if (!ret) { /* error? */
|
||||
sprintf (tmp,"Can't create mailbox node %.80s: %.80s",path,strerror (errno));
|
||||
MM_LOG (tmp,ERROR);
|
||||
}
|
||||
umask (mask); /* restore mask */
|
||||
return ret; /* return status */
|
||||
}
|
||||
|
||||
/* Dummy delete mailbox
|
||||
* Accepts: mail stream
|
||||
* mailbox name to delete
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_delete (MAILSTREAM *stream,char *mailbox)
|
||||
{
|
||||
struct stat sbuf;
|
||||
char *s,tmp[MAILTMPLEN];
|
||||
if (!(s = dummy_file (tmp,mailbox))) {
|
||||
sprintf (tmp,"Can't delete - invalid name: %.80s",s);
|
||||
MM_LOG (tmp,ERROR);
|
||||
}
|
||||
/* no trailing / (workaround BSD kernel bug) */
|
||||
if ((s = strrchr (tmp,'/')) && !s[1]) *s = '\0';
|
||||
if (stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) == S_IFDIR) ?
|
||||
rmdir (tmp) : unlink (tmp)) {
|
||||
sprintf (tmp,"Can't delete mailbox %.80s: %.80s",mailbox,strerror (errno));
|
||||
MM_LOG (tmp,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
return T; /* return success */
|
||||
}
|
||||
|
||||
/* Mail rename mailbox
|
||||
* Accepts: mail stream
|
||||
* old mailbox name
|
||||
* new mailbox name
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
|
||||
{
|
||||
struct stat sbuf;
|
||||
char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
|
||||
/* no trailing / allowed */
|
||||
if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
|
||||
stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] &&
|
||||
((sbuf.st_mode & S_IFMT) != S_IFDIR))) {
|
||||
sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname);
|
||||
MM_LOG (mbx,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
if (s) { /* found a directory delimiter? */
|
||||
if (!s[1]) *s = '\0'; /* ignore trailing delimiter */
|
||||
else { /* found superior to destination name? */
|
||||
c = *++s; /* remember first character of inferior */
|
||||
*s = '\0'; /* tie off to get just superior */
|
||||
/* name doesn't exist, create it */
|
||||
if ((stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
|
||||
!dummy_create (stream,mbx)) return NIL;
|
||||
*s = c; /* restore full name */
|
||||
}
|
||||
}
|
||||
/* rename of non-ex INBOX creates dest */
|
||||
if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf))
|
||||
return dummy_create (NIL,mbx);
|
||||
if (rename (oldname,mbx)) {
|
||||
sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname,
|
||||
strerror (errno));
|
||||
MM_LOG (tmp,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
return T; /* return success */
|
||||
}
|
||||
|
||||
/* Dummy open
|
||||
* Accepts: stream to open
|
||||
* Returns: stream on success, NIL on failure
|
||||
*/
|
||||
|
||||
MAILSTREAM *dummy_open (MAILSTREAM *stream)
|
||||
{
|
||||
int fd;
|
||||
char err[MAILTMPLEN],tmp[MAILTMPLEN];
|
||||
struct stat sbuf;
|
||||
/* OP_PROTOTYPE call */
|
||||
if (!stream) return &dummyproto;
|
||||
err[0] = '\0'; /* no error message yet */
|
||||
/* can we open the file? */
|
||||
if (!dummy_file (tmp,stream->mailbox))
|
||||
sprintf (err,"Can't open this name: %.80s",stream->mailbox);
|
||||
else if ((fd = open (tmp,O_RDONLY,NIL)) < 0) {
|
||||
/* no, error unless INBOX */
|
||||
if (compare_cstring (stream->mailbox,"INBOX"))
|
||||
sprintf (err,"%.80s: %.80s",strerror (errno),stream->mailbox);
|
||||
}
|
||||
else { /* file had better be empty then */
|
||||
fstat (fd,&sbuf); /* sniff at its size */
|
||||
close (fd);
|
||||
if ((sbuf.st_mode & S_IFMT) != S_IFREG)
|
||||
sprintf (err,"Can't open %.80s: not a selectable mailbox",
|
||||
stream->mailbox);
|
||||
else if (sbuf.st_size) /* bogus format if non-empty */
|
||||
sprintf (err,"Can't open %.80s (file %.80s): not in valid mailbox format",
|
||||
stream->mailbox,tmp);
|
||||
}
|
||||
if (err[0]) { /* if an error happened */
|
||||
MM_LOG (err,stream->silent ? WARN : ERROR);
|
||||
return NIL;
|
||||
}
|
||||
else if (!stream->silent) { /* only if silence not requested */
|
||||
mail_exists (stream,0); /* say there are 0 messages */
|
||||
mail_recent (stream,0); /* and certainly no recent ones! */
|
||||
stream->uid_validity = time (0);
|
||||
}
|
||||
stream->inbox = T; /* note that it's an INBOX */
|
||||
return stream; /* return success */
|
||||
}
|
||||
|
||||
|
||||
/* Dummy close
|
||||
* Accepts: MAIL stream
|
||||
* options
|
||||
*/
|
||||
|
||||
void dummy_close (MAILSTREAM *stream,long options)
|
||||
{
|
||||
/* return silently */
|
||||
}
|
||||
|
||||
/* Dummy ping mailbox
|
||||
* Accepts: MAIL stream
|
||||
* Returns: T if stream alive, else NIL
|
||||
*/
|
||||
|
||||
long dummy_ping (MAILSTREAM *stream)
|
||||
{
|
||||
MAILSTREAM *test;
|
||||
if (time (0) >= /* time to do another test? */
|
||||
((time_t) (stream->gensym +
|
||||
(long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL)))) {
|
||||
/* has mailbox format changed? */
|
||||
if ((test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE)) &&
|
||||
(test->dtb != stream->dtb) &&
|
||||
(test = mail_open (NIL,stream->mailbox,NIL))) {
|
||||
/* preserve some resources */
|
||||
test->original_mailbox = stream->original_mailbox;
|
||||
stream->original_mailbox = NIL;
|
||||
test->sparep = stream->sparep;
|
||||
stream->sparep = NIL;
|
||||
test->sequence = stream->sequence;
|
||||
mail_close ((MAILSTREAM *) /* flush resources used by dummy stream */
|
||||
memcpy (fs_get (sizeof (MAILSTREAM)),stream,
|
||||
sizeof (MAILSTREAM)));
|
||||
/* swap the streams */
|
||||
memcpy (stream,test,sizeof (MAILSTREAM));
|
||||
fs_give ((void **) &test);/* flush test now that copied */
|
||||
/* make sure application knows */
|
||||
mail_exists (stream,stream->recent = stream->nmsgs);
|
||||
}
|
||||
/* still hasn't changed */
|
||||
else stream->gensym = time (0);
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
/* Dummy check mailbox
|
||||
* Accepts: MAIL stream
|
||||
* No-op for readonly files, since read/writer can expunge it from under us!
|
||||
*/
|
||||
|
||||
void dummy_check (MAILSTREAM *stream)
|
||||
{
|
||||
dummy_ping (stream); /* invoke ping */
|
||||
}
|
||||
|
||||
|
||||
/* Dummy expunge mailbox
|
||||
* Accepts: MAIL stream
|
||||
* sequence to expunge if non-NIL
|
||||
* expunge options
|
||||
* Returns: T, always
|
||||
*/
|
||||
|
||||
long dummy_expunge (MAILSTREAM *stream,char *sequence,long options)
|
||||
{
|
||||
return LONGT;
|
||||
}
|
||||
|
||||
/* Dummy copy message(s)
|
||||
* Accepts: MAIL stream
|
||||
* sequence
|
||||
* destination mailbox
|
||||
* options
|
||||
* Returns: T if copy successful, else NIL
|
||||
*/
|
||||
|
||||
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
|
||||
{
|
||||
if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :
|
||||
mail_sequence (stream,sequence)) fatal ("Impossible dummy_copy");
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
||||
/* Dummy append message string
|
||||
* Accepts: mail stream
|
||||
* destination mailbox
|
||||
* append callback function
|
||||
* data for callback
|
||||
* Returns: T on success, NIL on failure
|
||||
*/
|
||||
|
||||
long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
|
||||
{
|
||||
struct stat sbuf;
|
||||
int fd = -1;
|
||||
int e;
|
||||
char tmp[MAILTMPLEN];
|
||||
MAILSTREAM *ts = default_proto (T);
|
||||
/* append to INBOX? */
|
||||
if (!compare_cstring (mailbox,"INBOX")) {
|
||||
/* yes, if no empty proto try creating */
|
||||
if (!ts && !(*(ts = default_proto (NIL))->dtb->create) (ts,"INBOX"))
|
||||
ts = NIL;
|
||||
}
|
||||
else if (dummy_file (tmp,mailbox) && ((fd = open (tmp,O_RDONLY,NIL)) < 0)) {
|
||||
if ((e = errno) == ENOENT) /* failed, was it no such file? */
|
||||
MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);
|
||||
sprintf (tmp,"%.80s: %.80s",strerror (e),mailbox);
|
||||
MM_LOG (tmp,ERROR); /* pass up error */
|
||||
return NIL; /* always fails */
|
||||
}
|
||||
else if (fd >= 0) { /* found file? */
|
||||
fstat (fd,&sbuf); /* get its size */
|
||||
close (fd); /* toss out the fd */
|
||||
if (sbuf.st_size) ts = NIL; /* non-empty file? */
|
||||
}
|
||||
if (ts) return (*ts->dtb->append) (stream,mailbox,af,data);
|
||||
sprintf (tmp,"Indeterminate mailbox format: %.80s",mailbox);
|
||||
MM_LOG (tmp,ERROR);
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* Dummy mail generate file string
|
||||
* Accepts: temporary buffer to write into
|
||||
* mailbox name string
|
||||
* Returns: local file string or NIL if failure
|
||||
*/
|
||||
|
||||
char *dummy_file (char *dst,char *name)
|
||||
{
|
||||
char *s = mailboxfile (dst,name);
|
||||
/* return our standard inbox */
|
||||
return (s && !*s) ? strcpy (dst,sysinbox ()) : s;
|
||||
}
|
||||
|
||||
|
||||
/* Dummy canonicalize name
|
||||
* Accepts: buffer to write name
|
||||
* reference
|
||||
* pattern
|
||||
* Returns: T if success, NIL if failure
|
||||
*/
|
||||
|
||||
long dummy_canonicalize (char *tmp,char *ref,char *pat)
|
||||
{
|
||||
unsigned long i;
|
||||
char *s;
|
||||
if (ref) { /* preliminary reference check */
|
||||
if (*ref == '{') return NIL;/* remote reference not allowed */
|
||||
else if (!*ref) ref = NIL; /* treat empty reference as no reference */
|
||||
}
|
||||
switch (*pat) {
|
||||
case '#': /* namespace name */
|
||||
if (mailboxfile (tmp,pat)) strcpy (tmp,pat);
|
||||
else return NIL; /* unknown namespace */
|
||||
break;
|
||||
case '{': /* remote names not allowed */
|
||||
return NIL;
|
||||
case '/': /* rooted name */
|
||||
case '~': /* home directory name */
|
||||
if (!ref || (*ref != '#')) {/* non-namespace reference? */
|
||||
strcpy (tmp,pat); /* yes, ignore */
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default: /* apply reference for all other names */
|
||||
if (!ref) strcpy (tmp,pat); /* just copy if no namespace */
|
||||
else if ((*ref != '#') || mailboxfile (tmp,ref)) {
|
||||
/* wants root of name? */
|
||||
if (*pat == '/') strcpy (strchr (strcpy (tmp,ref),'/'),pat);
|
||||
/* otherwise just append */
|
||||
else sprintf (tmp,"%s%s",ref,pat);
|
||||
}
|
||||
else return NIL; /* unknown namespace */
|
||||
}
|
||||
/* count wildcards */
|
||||
for (i = 0, s = tmp; *s; *s++) if ((*s == '*') || (*s == '%')) ++i;
|
||||
if (i > MAXWILDCARDS) { /* ridiculous wildcarding? */
|
||||
MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR);
|
||||
return NIL;
|
||||
}
|
||||
return T;
|
||||
}
|
||||
43
src/osdep/amiga/dummy.h
Normal file
43
src/osdep/amiga/dummy.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: Dummy routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 9 May 1991
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
/* Exported function prototypes */
|
||||
|
||||
void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
|
||||
void dummy_list (MAILSTREAM *stream,char *ref,char *pat);
|
||||
void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat);
|
||||
long scan_contents (DRIVER *dtb,char *name,char *contents,
|
||||
unsigned long csiz,unsigned long fsiz);
|
||||
long dummy_scan_contents (char *name,char *contents,unsigned long csiz,
|
||||
unsigned long fsiz);
|
||||
long dummy_create (MAILSTREAM *stream,char *mailbox);
|
||||
long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode);
|
||||
long dummy_delete (MAILSTREAM *stream,char *mailbox);
|
||||
long dummy_rename (MAILSTREAM *stream,char *old,char *newname);
|
||||
char *dummy_file (char *dst,char *name);
|
||||
long dummy_canonicalize (char *tmp,char *ref,char *pat);
|
||||
1282
src/osdep/amiga/env_ami.c
Normal file
1282
src/osdep/amiga/env_ami.c
Normal file
File diff suppressed because it is too large
Load Diff
95
src/osdep/amiga/env_ami.h
Normal file
95
src/osdep/amiga/env_ami.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2006 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: UNIX environment routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 1 August 1988
|
||||
* Last Edited: 30 August 2006
|
||||
*/
|
||||
|
||||
|
||||
typedef struct dotlock_base {
|
||||
char lock[MAILTMPLEN];
|
||||
int pipei;
|
||||
int pipeo;
|
||||
} DOTLOCK;
|
||||
|
||||
|
||||
/* Bits that can be set in restrictBox */
|
||||
|
||||
#define RESTRICTROOT 0x1 /* restricted box doesn't allow root */
|
||||
#define RESTRICTOTHERUSER 0x2 /* restricted box doesn't allow other user */
|
||||
|
||||
/* Subscription definitions for UNIX */
|
||||
|
||||
#define SUBSCRIPTIONFILE(t) sprintf (t,"%s/.mailboxlist",myhomedir ())
|
||||
#define SUBSCRIPTIONTEMP(t) sprintf (t,"%s/.mlbxlsttmp",myhomedir ())
|
||||
|
||||
|
||||
/* dorc() options */
|
||||
|
||||
#define SYSCONFIG "/etc/c-client.cf"
|
||||
|
||||
|
||||
/* Special users */
|
||||
|
||||
#define ANONYMOUSUSER "nobody" /* anonymous user */
|
||||
#define UNLOGGEDUSER "root" /* unlogged-in user */
|
||||
#define ADMINGROUP "mailadm" /* mail administrator group */
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
#include "env.h"
|
||||
|
||||
void rfc822_fixed_date (char *date);
|
||||
long env_init (char *user,char *home);
|
||||
char *myusername_full (unsigned long *flags);
|
||||
#define MU_LOGGEDIN 0
|
||||
#define MU_NOTLOGGEDIN 1
|
||||
#define MU_ANONYMOUS 2
|
||||
#define myusername() \
|
||||
myusername_full (NIL)
|
||||
char *sysinbox ();
|
||||
char *mailboxdir (char *dst,char *dir,char *name);
|
||||
long dotlock_lock (char *file,DOTLOCK *base,int fd);
|
||||
long dotlock_unlock (DOTLOCK *base);
|
||||
int lockname (char *lock,char *fname,int op,long *pid);
|
||||
int lockfd (int fd,char *lock,int op);
|
||||
int lock_work (char *lock,void *sbuf,int op,long *pid);
|
||||
long chk_notsymlink (char *name,void *sbuf);
|
||||
void unlockfd (int fd,char *lock);
|
||||
long set_mbx_protections (char *mailbox,char *path);
|
||||
long get_dir_protection (char *mailbox);
|
||||
MAILSTREAM *user_flags (MAILSTREAM *stream);
|
||||
char *default_user_flag (unsigned long i);
|
||||
void dorc (char *file,long flag);
|
||||
long path_create (MAILSTREAM *stream,char *mailbox);
|
||||
void grim_pid_reap_status (int pid,int killreq,void *status);
|
||||
#define grim_pid_reap(pid,killreq) \
|
||||
grim_pid_reap_status (pid,killreq,NIL)
|
||||
long safe_write (int fd,char *buf,long nbytes);
|
||||
void *arm_signal (int sig,void *action);
|
||||
struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[]);
|
||||
long loginpw (struct passwd *pw,int argc,char *argv[]);
|
||||
long pw_login (struct passwd *pw,char *auser,char *user,char *home,int argc,
|
||||
char *argv[]);
|
||||
void *mm_blocknotify (int reason,void *data);
|
||||
99
src/osdep/amiga/fdstring.c
Normal file
99
src/osdep/amiga/fdstring.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ========================================================================
|
||||
* Copyright 1988-2007 University of Washington
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* ========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Program: File descriptor string routines
|
||||
*
|
||||
* Author: Mark Crispin
|
||||
* Networks and Distributed Computing
|
||||
* Computing & Communications
|
||||
* University of Washington
|
||||
* Administration Building, AG-44
|
||||
* Seattle, WA 98195
|
||||
* Internet: MRC@CAC.Washington.EDU
|
||||
*
|
||||
* Date: 15 April 1997
|
||||
* Last Edited: 4 April 2007
|
||||
*/
|
||||
|
||||
#include "mail.h"
|
||||
#include "osdep.h"
|
||||
#include "misc.h"
|
||||
#include "fdstring.h"
|
||||
|
||||
/* String driver for fd stringstructs */
|
||||
|
||||
static void fd_string_init (STRING *s,void *data,unsigned long size);
|
||||
static char fd_string_next (STRING *s);
|
||||
static void fd_string_setpos (STRING *s,unsigned long i);
|
||||
|
||||
STRINGDRIVER fd_string = {
|
||||
fd_string_init, /* initialize string structure */
|
||||
fd_string_next, /* get next byte in string structure */
|
||||
fd_string_setpos /* set position in string structure */
|
||||
};
|
||||
|
||||
|
||||
/* Initialize string structure for fd stringstruct
|
||||
* Accepts: string structure
|
||||
* pointer to string
|
||||
* size of string
|
||||
*/
|
||||
|
||||
static void fd_string_init (STRING *s,void *data,unsigned long size)
|
||||
{
|
||||
FDDATA *d = (FDDATA *) data;
|
||||
/* note fd */
|
||||
s->data = (void *) (unsigned long) d->fd;
|
||||
s->data1 = d->pos; /* note file offset */
|
||||
s->size = size; /* note size */
|
||||
s->curpos = s->chunk = d->chunk;
|
||||
s->chunksize = (unsigned long) d->chunksize;
|
||||
s->offset = 0; /* initial position */
|
||||
/* and size of data */
|
||||
s->cursize = min (s->chunksize,size);
|
||||
/* move to that position in the file */
|
||||
lseek (d->fd,d->pos,L_SET);
|
||||
read (d->fd,s->chunk,(size_t) s->cursize);
|
||||
}
|
||||
|
||||
/* Get next character from fd stringstruct
|
||||
* Accepts: string structure
|
||||
* Returns: character, string structure chunk refreshed
|
||||
*/
|
||||
|
||||
static char fd_string_next (STRING *s)
|
||||
{
|
||||
char c = *s->curpos++; /* get next byte */
|
||||
SETPOS (s,GETPOS (s)); /* move to next chunk */
|
||||
return c; /* return the byte */
|
||||
}
|
||||
|
||||
|
||||
/* Set string pointer position for fd stringstruct
|
||||
* Accepts: string structure
|
||||
* new position
|
||||
*/
|
||||
|
||||
static void fd_string_setpos (STRING *s,unsigned long i)
|
||||
{
|
||||
if (i > s->size) i = s->size; /* don't permit setting beyond EOF */
|
||||
s->offset = i; /* set new offset */
|
||||
s->curpos = s->chunk; /* reset position */
|
||||
/* set size of data */
|
||||
if (s->cursize = min (s->chunksize,SIZE (s))) {
|
||||
/* move to that position in the file */
|
||||
lseek ((long) s->data,s->data1 + s->offset,L_SET);
|
||||
read ((long) s->data,s->curpos,(size_t) s->cursize);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user