dslinux/user/pixil/apps/fltk/mail/lib Makefile cache.c cache.h encoding.c encoding.h mail_pop3.c mail_smtp.c mail_smtp.h mime.c mime.h net_util.c net_util.h nxmail.c nxmail.h rfc822.c rfc822.h str_util.c str_util.h
amadeus
dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:24:24 CEST 2006
Update of /cvsroot/dslinux/dslinux/user/pixil/apps/fltk/mail/lib
In directory antilope:/tmp/cvs-serv11916/apps/fltk/mail/lib
Added Files:
Makefile cache.c cache.h encoding.c encoding.h mail_pop3.c
mail_smtp.c mail_smtp.h mime.c mime.h net_util.c net_util.h
nxmail.c nxmail.h rfc822.c rfc822.h str_util.c str_util.h
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it
--- NEW FILE: encoding.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
static char alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789+/";
static int
cvt_ascii(unsigned char alpha)
{
if ((alpha >= 'A') && (alpha <= 'Z'))
return (int) (alpha - 'A');
else if ((alpha >= 'a') && (alpha <= 'z'))
return 26 + (int) (alpha - 'a');
else if ((alpha >= '0') && (alpha <= '9'))
return 52 + (int) (alpha - '0');
else if (alpha == '+')
return 62;
else if (alpha == '/')
return 63;
else if (alpha == '=')
return -2;
else
return -1;
}
int
decode_base64(unsigned char *in, unsigned char *out, int insize)
{
int index;
unsigned char outval;
unsigned char *outpointer = out;
int shift = 0;
unsigned long accum = 0;
unsigned long value = 0;
for (index = 0; index < insize; index++) {
value = cvt_ascii(in[index]);
if (value < 64) {
accum <<= 6;
shift += 6;
accum |= value;
if (shift >= 8) {
shift -= 8;
value = accum >> shift;
outval = (unsigned char) value & 0xFFl;
*outpointer++ = outval;
}
}
}
return ((int) (outpointer - out));
}
int
encode_base64(unsigned char *in, unsigned char *out, int insize)
{
int index;
unsigned char *outpointer = out;
unsigned char outval;
int shift = 0;
unsigned long accum = 0;
unsigned long value = 0;
for (index = 0; index < insize; index++) {
value = (unsigned long) in[index];
accum <<= 8;
shift += 8;
accum |= value;
while (shift >= 6) {
shift -= 6;
value = (accum >> shift) & 0x3Fl;
outval = alphabet[value];
*outpointer++ = outval;
}
}
return ((int) (outpointer - out));
}
--- NEW FILE: mail_smtp.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "nxmail.h"
#include "net_util.h"
#include "mail_smtp.h"
#define OK 0
#define FAILURE 1
#define ERROR 2
static char *SMTPProtoArray[] = { NULL, "HELO %s\n", "MAIL FROM:<%s>\n",
"RCPT TO:<%s>\n", "DATA\n", "\n.\n", "QUIT\n"
};
static int smtp_handle_response(SMTPCommands state, int response);
static int
smtp_send_command(int fd, char *command, int len)
{
#ifdef DEBUG
printf("SMTP: Sending <%s> <%d>\n", command, len);
#endif
if (tcp_wait_for_socket(fd, 5, TCP_WRITE) <= 0)
return (-1);
return (write(fd, command, len));
}
static int
smtp_get_response(int fd, char *response, int len)
{
int lindex;
int ret;
if (tcp_wait_for_socket(fd, 5, TCP_READ) <= 0)
return (-1);
bzero(response, len);
ret = fdgets(fd, response, len - 1);
if (ret <= 0)
return (-1);
/* Strip the CRLF and just turn it into a CR */
lindex = (strlen(response) - 1);
if (response[lindex] == '\n' && response[lindex - 1] == '\r') {
response[lindex - 1] = '\n';
response[lindex] = 0;
}
#ifdef DEBUG
printf("SMTP: Got <%s>", response);
#endif
return (0);
}
static int
smtp_command(int fd, SMTPCommands cmd, char *data)
{
char cmdstr[1024];
char response[1024];
if (SMTPProtoArray[cmd]) {
bzero(cmdstr, 1024);
if (data)
sprintf(cmdstr, SMTPProtoArray[cmd], data);
else
strcpy(cmdstr, SMTPProtoArray[cmd]);
if (smtp_send_command(fd, cmdstr, strlen(cmdstr)) == -1)
return (SMTP_NET_ERROR);
}
do {
if (smtp_get_response(fd, response, 1024) == -1)
return (SMTP_NET_ERROR);
}
while (atoi(response) == 0);
return (atoi(response));
}
static int
smtp_send_data(int fd, char *buffer, int bufferlen)
{
int len;
int outlen = 0;
while (1) {
#ifdef DEBUG
printf("SMTP: Sending %s\n", buffer + outlen);
#endif
if (tcp_wait_for_socket(fd, 5, TCP_WRITE) <= 0)
return (-1);
len = write(fd, buffer + outlen, bufferlen - outlen);
if (len <= 0) {
perror("SMTP_SEND_DATA (WRITE)\n");
return (-1);
}
if (len == (bufferlen - outlen))
break;
outlen += len;
}
return (0);
}
int
smtp_send_message(char *server, int port, nxmail_header_t * header,
char *body, int bodylen)
{
SMTPCommands state = 0;
int addrok = 0;
nxmail_address_t *tolist = &header->to;
char *hostname;
char str[100];
int ret;
int fd = tcp_open_stream(server, port);
if (fd == -1)
return (NXMAIL_SEND_ERROR);
printf("SEND: Opened up %d for socket\n", fd);
hostname = tcp_get_hostname(fd);
if (!hostname) {
printf("SMTP: Couldn't resolve the local host\n");
close(fd);
return (NXMAIL_SEND_ERROR);
}
state = SMTP_LOGON;
ret = smtp_command(fd, state, 0);
if (smtp_handle_response(state, ret) != OK)
goto end_session;
/* Send HELLO */
state = SMTP_HELLO;
ret = smtp_command(fd, state, hostname);
if (smtp_handle_response(state, ret) != OK)
goto end_session;
/* Send MAIL FROM */
state = SMTP_MAIL;
sprintf(str, "%s@%s", header->from.mailbox, header->from.host);
ret = smtp_command(fd, state, str);
if (smtp_handle_response(state, ret) != OK)
goto end_session;
/* Send RECT TO: for all names on the list */
state = SMTP_RECPT;
while (tolist) {
sprintf(str, "%s@%s", tolist->mailbox, tolist->host);
ret = smtp_command(fd, state, str);
switch (smtp_handle_response(state, ret)) {
case ERROR:
goto end_session;
case OK:
addrok++;
}
tolist->result = ret;
tolist = tolist->next;
}
if (!addrok) {
ret = SMTP_NO_MAILBOX;
goto end_session;
}
/* Send DATA */
state = SMTP_DATA;
ret = smtp_command(fd, state, 0);
if (smtp_handle_response(state, ret) != OK)
goto end_session;
smtp_send_data(fd, body, bodylen);
state = SMTP_DATA_END;
ret = smtp_command(fd, state, 0);
end_session:
printf("SEND: Sending quit!\n");
smtp_command(fd, SMTP_QUIT, 0);
close(fd);
switch (smtp_handle_response(state, ret)) {
case OK:
return (NXMAIL_SEND_OK);
case FAILURE:
return (NXMAIL_SEND_FAILURE);
default:
return (NXMAIL_SEND_ERROR);
}
}
/* This returns a OK, FAILURE, or ERROR depending on the result */
static int
smtp_handle_response(SMTPCommands state, int response)
{
switch (state) {
case SMTP_LOGON:
if (response != SMTP_READY)
return FAILURE;
return OK;
case SMTP_HELLO:
if (response != SMTP_OK)
return ERROR;
return OK;
case SMTP_MAIL:
switch (response) {
case SMTP_OK:
return (OK);
case SMTP_MAILBOX_FULL:
case SMTP_LOCAL_ERROR:
case SMTP_SYSTEM_FULL:
return (FAILURE);
default:
return (ERROR);
}
case SMTP_RECPT:
switch (response) {
case SMTP_OK:
case SMTP_FORWARDED:
return (OK);
case SMTP_SYNTAX_ERROR:
case SMTP_BAD_ARGUMENT:
case SMTP_BAD_SEQUENCE:
case SMTP_NO_SERVICE:
return (ERROR);
default:
return (FAILURE);
}
case SMTP_DATA:
if (response != SMTP_READY_FOR_DATA)
return (ERROR);
return (OK);
case SMTP_DATA_END:
if (response == SMTP_OK)
return (OK);
return (ERROR);
default:
return (FAILURE);
}
}
--- NEW FILE: net_util.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "net_util.h"
int nxmail_neterror = 0;
int
tcp_wait_for_socket(int fd, int len, int action)
{
int ret;
fd_set fdset;
struct timeval timeval;
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
timeval.tv_sec = len;
timeval.tv_usec = 0;
if (action == TCP_READ)
ret = select(fd + 1, &fdset, 0, 0, &timeval);
else
ret = select(fd + 1, 0, &fdset, 0, &timeval);
if (ret == -1)
perror("TCP_WAIT_FOR_SOCKET (SELECT)");
return (ret);
}
int
tcp_open_stream(char *address, int port)
{
int ret;
int fd;
int serror;
int slen = sizeof(serror);
struct sockaddr_in outsock;
struct hostent *host = gethostbyname(address);
struct in_addr *hostaddr;
if (!host)
return (-1);
hostaddr = (struct in_addr *) host->h_addr_list[0];
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("TCP_OPEN_STREAM (SOCKET)");
SET_NET_ERROR(errno);
return (-1);
}
/* Set it non blocking */
if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
perror("TCP_OPEN_sTREAM (FCNTL)");
SET_NET_ERROR(errno);
close(fd);
return (-1);
}
outsock.sin_family = AF_INET;
outsock.sin_port = htons(port);
outsock.sin_addr.s_addr = hostaddr->s_addr;
/* A small change here. A call to connect immediately */
/* returns a EINPROGRESS, and then we wait for further events */
/* to come in via poll or select */
ret =
connect(fd, (struct sockaddr *) &outsock, sizeof(struct sockaddr_in));
if (ret == 0)
return (fd);
if (errno != EINPROGRESS) {
perror("TCP_OPEN_STREAM (CONNECT)");
SET_NET_ERROR(errno);
close(fd);
return (-1);
}
ret = tcp_wait_for_socket(fd, 5, TCP_WRITE);
if (ret == -1) {
SET_NET_ERROR(errno);
close(fd);
return (-1);
}
if (ret == 0) {
printf("TCP_OPEN_STREAM - TIMEOUT ON CONNECT\n");
close(fd);
return (-1);
}
/* No error or timeout, check to see if there was an error */
getsockopt(fd, SOL_SOCKET, SO_ERROR, &serror, &slen);
if (serror != 0) {
printf("TCP_OPEN_STREAM: %d\n", serror);
SET_NET_ERROR(serror);
close(fd);
return (-1);
}
return (fd);
}
char *
tcp_get_hostname(int fd)
{
struct sockaddr_in saddr;
struct hostent *host;
unsigned long addr;
int slen = sizeof(struct sockaddr_in);
if (getsockname(fd, (struct sockaddr *) &saddr, &slen) == -1) {
perror("TCP_GET_HOSTNAME (GETSOCKNAME)");
SET_NET_ERROR(errno);
return (0);
}
addr = saddr.sin_addr.s_addr;
host = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
if (!host) {
return (0);
}
return (host->h_name);
}
/* Read up to len or until we are out of data, which */
/* ever comes first */
int
fdgets(int fd, char *buffer, int len)
{
int outsize = 0;
char *ptr = buffer;
while (1) {
int res = read(fd, ptr, 1);
if (res <= 0) {
if (res == -1 && errno != EAGAIN) {
perror("FDGETS (READ)");
return (-1);
}
*ptr = 0;
return (outsize);
}
if (*ptr == '\n') {
if (outsize + 1 < len)
*(ptr + 1) = 0;
return (outsize);
}
ptr++;
if (outsize++ == len)
return (len);
}
}
--- NEW FILE: rfc822.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef RFC822_H
#define RFC822_H
void rfc822_parse_date(char *date, nxmail_date_t * out);
void rfc822_parse_address(nxmail_address_t * out, char *addr);
int rfc822_parse_body(char *buffer, char *body);
void rfc822_parse_header(char *buffer, nxmail_header_t * header, int size);
int rfc822_build_message(nxmail_header_t *, char *, char *);
char *rfc822_getline(char *in, char *out, int size);
#endif
--- NEW FILE: net_util.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef UTIL_H
#define UTIL_H
#define TCP_WRITE 0
#define TCP_READ 1
extern int nxmail_neterror;
extern int errno;
#define SET_NET_ERROR(value) (nxmail_neterror = value)
#define GET_NET_ERROR (nxmail_neterror)
int tcp_open_stream(char *address, int port);
char *tcp_get_hostname(int fd);
int tcp_wait_for_socket(int fd, int len, int action);
int fdgets(int fd, char *buf, int len);
#endif
--- NEW FILE: mail_smtp.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef MAIL_SMTP_H
#define MAIL_SMTP_H
typedef enum
{
SMTP_LOGON = 0,
SMTP_HELLO,
SMTP_MAIL,
SMTP_RECPT,
SMTP_DATA,
SMTP_DATA_END,
SMTP_QUIT
}
SMTPCommands;
/* SMTP ERROR MESSAGES */
#define SMTP_NET_ERROR 1
#define SMTP_READY 220
#define SMTP_CLOSED 221
#define SMTP_OK 250
#define SMTP_FORWARDED 251
#define SMTP_READY_FOR_DATA 354
#define SMTP_NO_SERVICE 421
#define SMTP_MAILBOX_UNAVAIL 450
#define SMTP_LOCAL_ERROR 451
#define SMTP_SYSTEM_FULL 452
#define SMTP_SYNTAX_ERROR 500
#define SMTP_BAD_ARGUMENT 501
#define SMTP_NO_COMMAND 502
#define SMTP_BAD_SEQUENCE 503
#define SMTP_PARAM_NOT_AVAIL 504
#define SMTP_NO_MAILBOX 550
#define SMTP_USR_NOT_LOCAL 551
#define SMTP_MAILBOX_FULL 552
#define SMTP_BAD_MAILBOX_NAME 553
#define SMTP_FAILURE 554
int smtp_send_message(char *, int, nxmail_header_t *, char *, int);
#endif
--- NEW FILE: encoding.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef ENCODING_H
#define ENCODING_H
int encode_base64(unsigned char *in, unsigned char *out, int insize);
int decode_base64(unsigned char *in, unsigned char *out, int insize);
#endif
--- NEW FILE: rfc822.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nxmail.h"
#include "str_util.h"
/* RFC822 keyword callbacks */
void rfc822_ignore(char *, nxmail_header_t *);
void rfc822_date(char *, nxmail_header_t *);
void rfc822_from(char *, nxmail_header_t *);
void rfc822_to(char *, nxmail_header_t *);
void rfc822_subject(char *, nxmail_header_t *);
void rfc822_cc(char *, nxmail_header_t *);
void rfc822_replyto(char *, nxmail_header_t *);
void rfc822_build_address(nxmail_address_t * out, char *output);
struct
{
char keyword[20];
void (*callback) (char *, nxmail_header_t *);
}
rfc822_keywords[] =
{
/* RFC822 Keywords */
{
"return-path", rfc822_ignore}
, {
"received", rfc822_ignore}
, {
"date", rfc822_date}
, {
"resent-date", rfc822_date}
, {
"from", rfc822_from}
, {
"sender", rfc822_from}
, {
"resent-from", rfc822_from}
, {
"resent-sender", rfc822_from}
, {
"to", rfc822_to}
, {
"Resent-to", rfc822_to}
, {
"cc", rfc822_cc}
, {
"Resent-cc", rfc822_cc}
, {
"bcc", rfc822_cc}
, {
"resent-bcc", rfc822_cc}
, {
"reply-to", rfc822_replyto}
, {
"reset-reply-to", rfc822_replyto}
, {
"subject", rfc822_subject}
, {
"message-id", rfc822_ignore}
, {
"resent-message-id", rfc822_ignore}
, {
"in-reply-to", rfc822_ignore}
, {
"references", rfc822_ignore}
, {
"keywords", rfc822_ignore}
, {
"comments", rfc822_ignore}
, {
"encrypted", rfc822_ignore}
,
/* Extensions to RFC822 */
{
"auto-submitted", rfc822_ignore}
, {
"user-agent", rfc822_ignore}
, {
"status", rfc822_ignore}
, {
"<none>", 0}
};
void
rfc822_parse_header(char *buffer, nxmail_header_t * header, int totalsize)
{
char linebuf[1024];
char *curptr = buffer;
/* Parse the header as it was given to us */
while (curptr) {
char *nextptr;
char *keyword, *value;
int keycount = 0;
/* Grab the line and strip the endline */
nextptr = str_getline(curptr, linebuf, 1024);
/* If the size of the line is zero, then */
/* start processing the body */
if (!strlen(linebuf))
break;
curptr = nextptr;
/* Go through and parse the keywords */
if (!str_parsefield(linebuf, ':', &keyword, &value))
continue;
str_lcase(keyword, strlen(keyword));
keycount = 0;
while (rfc822_keywords[keycount].callback) {
if (!strncmp(keyword, rfc822_keywords[keycount].keyword,
strlen(rfc822_keywords[keycount].keyword))) {
rfc822_keywords[keycount].callback(value, header);
break;
}
keycount++;
}
}
/* Curptr is the now pointing to the start of the buffer */
/* so we can determine the offset of the message text */
header->offset = (int) (curptr - buffer);
header->msgsize = (int) (totalsize - header->offset);
}
static char *marray[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"
};
static char *
get_month(int value)
{
return (marray[value]);
}
static int
get_month_value(char *month)
{
int i;
for (i = 0; i < 12; i++)
if (!strcmp(month, marray[i]))
return (i);
return (0);
}
static char *warray[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *
get_weekday(int value)
{
return (warray[value]);
}
static int
get_weekday_value(char *wday)
{
int i;
for (i = 0; i < 7; i++)
if (!strcmp(wday, warray[i]))
return (i);
return (0);
}
void
rfc822_build_date(nxmail_date_t * in, char *out)
{
sprintf(out, "%3s, %2d %3s %4d %2d:%2d:%2d",
get_weekday(in->wday), in->day, get_month(in->month),
in->year, in->hour, in->min, in->sec);
}
/* Take a date of the format [www], dd mmm yy hh:mm:ss zone +hhh */
/* and put it into a structure suitable for use by the user */
void
rfc822_parse_date(char *date, nxmail_date_t * out)
{
char wdaystr[3], monthstr[3];
int day, year;
int hour, min, sec;
/* First, parse the date into the component pieces */
/* We are not going to handle time zones, yet */
sscanf(date, "%3s, %2d %3s %4d %2d:%2d:%2d", wdaystr, &day, monthstr,
&year, &hour, &min, &sec);
out->month = get_month_value(monthstr);
out->wday = get_weekday_value(wdaystr);
if (day >= 0 && day < 31)
out->day = day;
if (year >= 0 && year < 3000)
out->year = year;
if (hour >= 0 && hour <= 24)
out->hour = hour;
if (min >= 0 && min <= 60)
out->min = min;
if (min >= 0 && min <= 60)
out->sec = sec;
}
char *
rfc822_append_text(char *ptr, char *str)
{
strcat(ptr, str);
return (ptr + (strlen(str)));
}
char *
rfc822_append_field(char *ptr, char *fieldname, char *value)
{
char outstr[1024];
sprintf(outstr, "%s%s\n", fieldname, value);
return (rfc822_append_text(ptr, outstr));
}
char *
rfc822_append_addrlist(char *ptr, char *field, nxmail_address_t * list)
{
char *lptr = ptr;
char addrstr[100];
nxmail_address_t *alist = list;
lptr = rfc822_append_text(lptr, field);
while (alist) {
rfc822_build_address(alist, addrstr);
lptr = rfc822_append_text(lptr, addrstr);
if (alist->next)
lptr = rfc822_append_text(lptr, ", ");
alist = alist->next;
}
return (rfc822_append_text(lptr, "\n"));
}
int
rfc822_build_message(nxmail_header_t * header, char *body, char *output)
{
char addrstr[100];
char datestr[100];
char *bufptr = output;
/* date, from, subject, to, cc, bcc, reply to */
rfc822_build_date(&header->date, datestr);
bufptr = rfc822_append_field(bufptr, "Date: ", datestr);
rfc822_build_address(&header->from, addrstr);
bufptr = rfc822_append_field(bufptr, "From: ", addrstr);
bufptr = rfc822_append_field(bufptr, "Subject: ", header->subject);
bufptr = rfc822_append_addrlist(bufptr, "To: ", &header->to);
if (strlen(header->cc.host))
bufptr = rfc822_append_addrlist(bufptr, "cc: ", &header->cc);
bufptr = rfc822_append_text(bufptr, "\n");
bufptr = rfc822_append_text(bufptr, body);
return ((int) (bufptr - output));
}
void
rfc822_ignore(char *inptr, nxmail_header_t * header)
{
return;
}
void
rfc822_date(char *inptr, nxmail_header_t * header)
{
rfc822_parse_date(inptr, &header->date);
return;
}
void
rfc822_from(char *inptr, nxmail_header_t * header)
{
/* Get the from field */
rfc822_parse_address(&header->from, inptr);
}
void
rfc822_to(char *inptr, nxmail_header_t * header)
{
nxmail_address_t *addrlist = &header->to;
int count = nxmail_count_addrstr(inptr);
if (!count)
return;
count = nxmail_alloc_addrlist(addrlist, count);
nxmail_build_addrlist(inptr, addrlist, count);
}
void
rfc822_cc(char *inptr, nxmail_header_t * header)
{
nxmail_address_t *addrlist = &header->cc;
int count = nxmail_count_addrstr(inptr);
if (!count)
return;
count = nxmail_alloc_addrlist(addrlist, count);
nxmail_build_addrlist(inptr, addrlist, count);
}
void
rfc822_replyto(char *inptr, nxmail_header_t * header)
{
/* Get the to field */
strncpy(header->replyto, inptr, sizeof(header->replyto) - 1);
}
void
rfc822_subject(char *inptr, nxmail_header_t * header)
{
strncpy(header->subject, inptr, sizeof(header->subject) - 1);
}
void
rfc822_build_address(nxmail_address_t * out, char *output)
{
char addrstr[256];
if (strlen(out->host))
sprintf(addrstr, "%s@%s", out->mailbox, out->host);
else
sprintf(addrstr, "%s", out->mailbox);
if (strlen(out->name)) {
sprintf(output, "%s <%s>", out->name, addrstr);
} else
sprintf(output, "%s", addrstr);
}
/* These charaters cannot be in a address string */
static char addrchars[] = { '(', ')', '<', '>', ',',
';', '\\', '"', '[', ']', ' ',
};
static int
rfc822_verify_addr(char *addr, int len)
{
int i;
for (i = 0; i < len; i++) {
int c;
for (c = 0; c < 11; c++)
if (addr[i] == addrchars[c])
return (0);
}
return (1);
}
char *
rfc822_parse_name(nxmail_address_t * dest, char *address)
{
int size;
char *ptr, *nptr;
if (*address == '"')
ptr = address + 1;
else
ptr = address;
/* Go until we find another quote or a < */
for (nptr = ptr; *nptr; nptr++) {
if (*nptr == '"')
break;
if (*nptr == '<')
break;
/* If we find a at sign with no quotes or qualifiers, bet that */
/* we're barking up the wrong tree */
if (*nptr == '@' && *address != '"') /* uhoh, its an address. Bail! */
return (address);
/* This helps ensure that we don't get caught in a loop */
if ((int) (nptr - ptr) > sizeof(dest->name))
break;
}
/* Ok, we have some amount of name, ensure that we can fit it */
/* into the structure without overrunning the buffer */
size = (int) (nptr - ptr);
if (size >= sizeof(dest->name)) {
size = sizeof(dest->name) - 1;
}
if (size)
strncpy(dest->name, ptr, size);
return (nptr + 1);
}
char *
rfc822_parse_mailbox(nxmail_address_t * dest, char *address)
{
char *ptr, *nptr;
if (*address == '<')
ptr = address + 1;
else
ptr = address;
/* Go to the end */
for (nptr = ptr; *nptr && *nptr != '>' && *nptr != ' '; nptr++);
if (rfc822_verify_addr(ptr, (int) (nptr - ptr)) == 1) {
/* The address checks out with no bad chars */
/* now try to get the mailbox and host */
char *aptr = strchr(ptr, '@');
if (aptr) {
int size;
if ((int) (aptr - ptr) >= sizeof(dest->mailbox)) {
size = sizeof(dest->mailbox) - 1;
} else {
size = (int) (aptr - ptr);
}
strncpy(dest->mailbox, ptr, size);
dest->host[size + 1] = 0;
if ((int) (nptr - aptr - 1) >= sizeof(dest->host)) {
size = sizeof(dest->host) - 1;
} else
size = (int) (nptr - aptr - 1);
strncpy(dest->host, aptr + 1, size);
dest->host[size + 1] = 0;
} else {
int size;
if ((int) (nptr - ptr) >= sizeof(dest->mailbox))
size = sizeof(dest->mailbox) - 1;
else
size = (int) (nptr - ptr);
strncpy(dest->mailbox, ptr, size);
}
return (nptr + 1);
}
/* Otherwise, something didn't come out right */
return (address);
}
void
rfc822_parse_address(nxmail_address_t * dest, char *address)
{
char *ptr = address;
while (*ptr) {
char *nptr;
/* First, strip any whitespace */
while (*ptr) {
if (*ptr != ' ' && *ptr != '\t')
break;
ptr++;
}
if (!*ptr)
break;
if (*ptr == '"' || *ptr == ' ') {
ptr = rfc822_parse_name(dest, ptr);
continue;
}
if (*ptr == '<') {
ptr = rfc822_parse_mailbox(dest, ptr);
continue;
}
nptr = rfc822_parse_name(dest, ptr);
if (nptr != ptr) {
ptr = nptr;
continue;
}
ptr = rfc822_parse_mailbox(dest, ptr);
}
}
--- NEW FILE: nxmail.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef NXMAIL_H
#define NXMAIL_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#define NXMAIL_TYPE_POP3 0
#define NXMAIL_TYPE_LAST 1
#define NXMAIL_OK 0
#define NXMAIL_SEND_OK 0
#define NXMAIL_ERROR -1
#define NXMAIL_STREAM_OPEN -2
#define NXMAIL_NO_STREAM -3
#define NXMAIL_ADDR_ERROR -4
#define NXMAIL_NET_ERROR -5
#define NXMAIL_SEND_FAILURE -6
#define NXMAIL_SEND_ERROR -7
#define NXMAIL_NETWORK_ERROR -8
typedef struct
{
int fd;
int type;
}
nxmail_stream;
typedef struct
{
int (*mail_open) (char *, int, nxmail_stream *);
int (*mail_login) (nxmail_stream *, char *, char *);
int (*mail_status) (nxmail_stream *, int *, int *);
int (*mail_msginfo) (nxmail_stream *, int);
int (*mail_fetchheader) (nxmail_stream *, int, char **);
int (*mail_fetchbody) (nxmail_stream *, int, char **);
int (*mail_delete) (nxmail_stream *, int);
void (*mail_close) (nxmail_stream *);
}
nxmail_driver_t;
typedef struct nxmail_addr_t
{
char name[40];
char mailbox[40];
char host[40];
int result;
struct nxmail_addr_t *next;
}
nxmail_address_t;
typedef struct
{
int month;
int day;
int year;
int wday;
int hour;
int min;
int sec;
}
nxmail_date_t;
typedef struct
{
char type[50];
char name[50];
int charset;
int encoding;
char description[50];
}
nxmail_mime_header_t;
typedef struct
{
/* Message variables */
nxmail_date_t date;
nxmail_address_t to;
nxmail_address_t from;
nxmail_address_t cc;
char replyto[50];
char subject[100];
nxmail_mime_header_t mimeheader;
/* Housekeeping variables */
int offset;
int msgsize;
}
nxmail_header_t;
typedef struct nxmail_bdy_t
{
nxmail_mime_header_t mimeheader;
int size;
char *text;
struct nxmail_bdy_t *next;
}
nxmail_body_t;
#define NXMAIL_ENCODING_NONE 0
#define NXMAIL_ENCODING_BASE64 1
#define NXMAIL_CHARSET_USASCII 0
int nxmail_get_error(void);
nxmail_stream *nxmail_init_stream(void);
void nxmail_close_stream(nxmail_stream * stream);
int nxmail_open(nxmail_stream * stream, char *address, int port,
int type);
int nxmail_auth(nxmail_stream * stream, char *user, char *password);
int nxmail_status(nxmail_stream * stream, int *msgcount);
nxmail_header_t *nxmail_fetchheader(nxmail_stream * stream, int msgno);
nxmail_body_t *nxmail_fetchbody(nxmail_stream * stream, int msgno);
int nxmail_sendmsg(char *server, int port,
nxmail_header_t * header, char *body, int size);
void nxmail_parsedate(char *rfc822_date, nxmail_date_t * date);
int nxmail_delete(nxmail_stream * stream, int message);
void nxmail_close(nxmail_stream * stream);
/* Various parsers that may be useful to people */
void rfc822_parse_address(nxmail_address_t * dest, char *address);
/* Address list management */
void nxmail_build_addrstr(nxmail_address_t * out, char *output);
int nxmail_count_addrstr(char *addrstring);
int nxmail_build_addrlist(char *addrstring,
nxmail_address_t * addrlist, int count);
int nxmail_alloc_addrlist(nxmail_address_t * head, int count);
void nxmail_free_addrlist(nxmail_address_t * head);
void nxmail_parse_dateval(unsigned long, nxmail_date_t * date);
nxmail_body_t *nxmail_alloc_body_struct(int size);
void nxmail_free_body_struct(nxmail_body_t * head);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: Makefile ---
# apps/mail/nxmail/Makefile
LIB_STATIC=libnxmail.a
SRC=${shell ls *.c}
OBJS=${SRC:.c=.o}
include $(BASE_DIR)/Rules.make
--- NEW FILE: cache.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef CACHE_H
#define CACHE_H
#include "nxmail.h"
typedef struct
{
int key; /* The index that we search on */
int age; /* The age of the entry (in accesses) */
int size; /* The size of the raw buffer */
nxmail_header_t header; /* Parsed nxmail header */
char *raw; /* the raw message as it was recieved */
nxmail_body_t *body; /* parsed nxmail body */
}
cache_entry_t;
void cache_init(void);
void cache_close(void);
cache_entry_t *get_new_cache_entry(int key, int size);
void free_cache_entry(cache_entry_t *);
cache_entry_t *search_cache_entry(int);
#endif
--- NEW FILE: str_util.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef STR_UTILS_H
#define STR_UTILS_H
void str_lcase(char *value, int len);
char *str_getline(char *, char *, int);
char *str_skipwhite(char *ptr);
char *str_getfield(char *in, char delim, char **field);
int str_parsefield(char *in, char delim, char **keyword, char **value);
#endif
--- NEW FILE: mail_pop3.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
/*
* NXMAIL - MAIL_POP3.C
* Routines to access POP3 mailboxes
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include "nxmail.h"
#include "net_util.h"
#define POP3_PORT 110
static int
pop3_command(int fd, char *in, int len)
{
int outlen;
#ifdef DEBUG
printf("CLIENT OUT (%d): %s", len, in);
#endif
if (tcp_wait_for_socket(fd, 10, TCP_WRITE) <= 0)
return (-1);
outlen = write(fd, in, len);
if (outlen != len) {
if (outlen == -1)
perror("POP3_COMMAND (WRITE)");
SET_NET_ERROR(errno);
return (-1);
}
return (0);
}
static int
pop3_response(int fd, char *out, int len, int wait)
{
int ret;
int lindex;
if (tcp_wait_for_socket(fd, 10, TCP_READ) <= 0)
return (-1);
ret = fdgets(fd, out, len - 1);
if (ret <= 0) {
printf("Got back %d from ret!\n", ret);
return (-1);
}
/* Strip the CRLF and just turn it into a CR */
lindex = (strlen(out) - 1);
if (out[lindex] == '\n' && out[lindex - 1] == '\r') {
out[lindex - 1] = '\n';
out[lindex] = 0;
}
#ifdef DEBUG
printf("CLIENT IN: %s", out);
#endif
return (0);
}
#ifdef LOG
#define pop3_log(str) fprintf(stderr, "LOG %s", str)
#else
#define pop3_log(str)
#endif
static int
pop3_do_command(nxmail_stream * stream, char *command,
char *response, int reslen)
{
int cmdlen = strlen(command);
if (pop3_command(stream->fd, command, cmdlen) == -1)
return (NXMAIL_NETWORK_ERROR);
if (pop3_response(stream->fd, response, reslen, 1) == -1)
return (NXMAIL_NETWORK_ERROR);
#ifdef LOG
pop3_log(response);
#endif
return (NXMAIL_OK);
}
static int
pop3_is_ok(char *response)
{
if (response[0] == '+')
return (1);
else
return (0);
}
static int
pop3_get_data(nxmail_stream * stream, char *buffer, int maxlen)
{
char *pos = buffer;
int copied = 0;
char linebuf[1024];
while (1) {
char *lpos = 0;
int lsize = 0;
if (pop3_response(stream->fd, linebuf, 1024, 0) != NXMAIL_OK)
break;
if (!strlen(linebuf))
break;
if (!strcmp(linebuf, ".\n"))
break;
lpos = linebuf;
lsize = strlen(linebuf);
if (linebuf[0] == '.') {
lpos++;
lsize--;
}
if (copied + lsize > maxlen) {
strncpy(pos, lpos, maxlen - copied);
break;
}
strncpy(pos, lpos, lsize);
pos += lsize;
copied += lsize;
}
return (copied);
}
int
pop3_open(char *address, int port, nxmail_stream * stream)
{
char response[200];
int res;
int fd = tcp_open_stream(address, port);
if (fd == -1)
return (NXMAIL_NETWORK_ERROR);
stream->fd = fd;
/* Now wait for the server to respond */
res = pop3_response(stream->fd, response, 200, 1);
if (res == -1) {
close(fd);
stream->fd = 0;
return (NXMAIL_NETWORK_ERROR);
}
#ifdef DEBUG
pop3_log(response);
#endif
return (NXMAIL_OK);
}
int
pop3_login(nxmail_stream * stream, char *user, char *password)
{
char command[100];
char response[100];
/* Send the user string */
#ifdef DEBUG
printf("LOG: Sending USER command\n");
#endif
sprintf(command, "USER %s\n", user);
pop3_do_command(stream, command, response, 100);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
#ifdef DEBUG
printf("LOG: Sending PASS command\n");
#endif
sprintf(command, "PASS %s\n", password);
pop3_do_command(stream, command, response, 100);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
return (NXMAIL_OK);
}
void
pop3_close(nxmail_stream * stream)
{
char response[10];
if (stream->fd != 0) {
pop3_do_command(stream, "QUIT\n", response, 10);
close(stream->fd);
stream->fd = 0;
}
}
int
pop3_stat(nxmail_stream * stream, int *msgcount, int *msgsize)
{
char response[100];
pop3_do_command(stream, "STAT\n", response, 100);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
sscanf(response, "+OK %d %d", msgcount, msgsize);
return (NXMAIL_OK);
}
int
pop3_msginfo(nxmail_stream * stream, int msg)
{
char command[100];
char response[100];
int tmp, msgsize;
sprintf(command, "LIST %d\n", msg);
pop3_do_command(stream, command, response, 100);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
sscanf(response, "+OK %d %d", &tmp, &msgsize);
return (msgsize);
}
/* This just gets the header, nice for those quick grabs */
/* Returns the read size of the buffer */
int
pop3_getheader(nxmail_stream * stream, int msg, char **buffer)
{
char command[100];
char response[100];
int hsize;
hsize = pop3_msginfo(stream, msg);
sprintf(command, "TOP %d 0\n", msg);
if (pop3_command(stream->fd, command, strlen(command)) == -1)
return (NXMAIL_NETWORK_ERROR);
if (pop3_response(stream->fd, response, 100, 1) == -1)
return (NXMAIL_NETWORK_ERROR);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
/* sscanf(response, "+OK %d", &hsize); */
*buffer = (char *) malloc(hsize);
if (!*buffer)
return (NXMAIL_ERROR);
return (pop3_get_data(stream, *buffer, hsize));
}
int
pop3_getbody(nxmail_stream * stream, int msg, char **buffer)
{
char command[100];
char response[100];
int hsize;
hsize = pop3_msginfo(stream, msg);
/* Get the message */
sprintf(command, "RETR %d\n", msg);
if (pop3_command(stream->fd, command, strlen(command)) == -1)
return (NXMAIL_NETWORK_ERROR);
if (pop3_response(stream->fd, response, 100, 1) == -1)
return (NXMAIL_NETWORK_ERROR);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
/* sscanf(response, "+OK %d", &hsize); */
/* Local buffer ensures that we have a big enough area */
/* to copy in a message with no breaks in it */
*buffer = (char *) malloc(hsize);
if (!*buffer)
return (NXMAIL_ERROR);
return (pop3_get_data(stream, *buffer, hsize));
}
int
pop3_delete(nxmail_stream * stream, int msg)
{
char command[100];
char response[100];
sprintf(command, "DELE %d\n", msg);
pop3_do_command(stream, command, response, 100);
if (!pop3_is_ok(response))
return (NXMAIL_ERROR);
return (NXMAIL_OK);
}
/* This is the structure that the main API accesses to do POP3 functions */
nxmail_driver_t nxmail_pop3_driver = {
pop3_open,
pop3_login,
pop3_stat,
pop3_msginfo,
pop3_getheader,
pop3_getbody,
pop3_delete,
pop3_close
};
--- NEW FILE: mime.h ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef MIME_H
#define MIME_H
#include <string.h>
void mime_parse_message(char *, int, nxmail_header_t *, nxmail_body_t **);
#endif
--- NEW FILE: nxmail.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nxmail.h"
#include "rfc822.h"
#include "mime.h"
#include "cache.h"
#include "mail_smtp.h"
#include "net_util.h"
extern nxmail_driver_t nxmail_pop3_driver;
static nxmail_driver_t *drivers[] = { &nxmail_pop3_driver };
static nxmail_stream nxmail_openstream;
int
nxmail_get_error(void)
{
return (GET_NET_ERROR);
}
/* This will initalize the stream and get the cache ready to go */
nxmail_stream *
nxmail_init_stream(void)
{
cache_init();
bzero(&nxmail_openstream, sizeof(nxmail_openstream));
return (&nxmail_openstream);
}
void
nxmail_close_stream(nxmail_stream * stream)
{
nxmail_close(stream);
cache_close();
bzero(&nxmail_openstream, sizeof(nxmail_openstream));
}
int
nxmail_open(nxmail_stream * stream, char *address, int port, int type)
{
int ret;
if (type > NXMAIL_TYPE_LAST)
return (0);
ret = drivers[type]->mail_open(address, port, stream);
if (ret == NXMAIL_NETWORK_ERROR)
return (NXMAIL_ERROR);
stream->type = type;
return (ret);
}
int
nxmail_delete(nxmail_stream * stream, int msgno)
{
if (!stream)
return (NXMAIL_NO_STREAM);
if (stream->fd == 0)
return (NXMAIL_NO_STREAM);
return (drivers[stream->type]->mail_delete(stream, msgno));
}
int
nxmail_auth(nxmail_stream * stream, char *user, char *password)
{
if (!stream)
return (NXMAIL_NO_STREAM);
if (stream->fd == 0)
return (NXMAIL_NO_STREAM);
return (drivers[stream->type]->mail_login(stream, user, password));
}
int
nxmail_status(nxmail_stream * stream, int *msgcount)
{
int msize, ret;
if (!stream)
return (NXMAIL_NO_STREAM);
if (stream->fd == 0)
return (NXMAIL_NO_STREAM);
ret = drivers[stream->type]->mail_status(stream, msgcount, &msize);
return (ret);
}
static cache_entry_t *
nxmail_retheader(nxmail_stream * stream, int msgno)
{
cache_entry_t *centry;
int size;
char *buffer;
/* Get the header only */
size = drivers[stream->type]->mail_fetchheader(stream, msgno, &buffer);
/* Now allocate a cache entry and put it in */
if ((centry = get_new_cache_entry(msgno, size)) != NULL) {
/* Copy over what we have into the raw portion */
memcpy(centry->raw, buffer, size);
/* Parse the header */
rfc822_parse_header(centry->raw, ¢ry->header, size);
}
/* end of if */
free(buffer);
return (centry);
}
void
nxmail_parse_full(cache_entry_t * centry)
{
mime_parse_message(centry->raw, centry->size, ¢ry->header,
¢ry->body);
}
/* Retrieve the message, and parse the header */
static cache_entry_t *
nxmail_retbody(nxmail_stream * stream, int msgno)
{
cache_entry_t *centry = search_cache_entry(msgno);
char *buffer;
int size;
if (!stream)
return (0);
if (stream->fd == 0)
return (0);
size = drivers[stream->type]->mail_fetchbody(stream, msgno, &buffer);
/* If the cache already exists, then reuse it */
if (centry) {
/* Free the raw space and replace it */
if (centry->raw)
free(centry->raw);
centry->raw = (char *) malloc(size);
centry->size = size;
} else {
centry = get_new_cache_entry(msgno, size);
}
if (!centry)
return (0);
memcpy(centry->raw, buffer, size);
/* Reparse the header */
rfc822_parse_header(centry->raw, ¢ry->header, size);
nxmail_parse_full(centry);
free(buffer);
return (centry);
}
/* Given cache entry, parse out the full message */
/* We don't normally cache headers, but if it exists, then use it */
nxmail_header_t *
nxmail_fetchheader(nxmail_stream * stream, int msgno)
{
cache_entry_t *entry = search_cache_entry(msgno);
/* Check the cache to see if this message already exists */
if (!entry)
entry = nxmail_retheader(stream, msgno);
if (!entry)
return (0);
return (&entry->header);
}
nxmail_body_t *
nxmail_fetchbody(nxmail_stream * stream, int msgno)
{
cache_entry_t *entry = search_cache_entry(msgno);
if (!entry || !entry->body)
entry = nxmail_retbody(stream, msgno);
if (!entry)
return (0);
return (entry->body);
}
void
nxmail_parsedate(char *rfc822_date, nxmail_date_t * date)
{
rfc822_parse_date(rfc822_date, date);
}
void
nxmail_close(nxmail_stream * stream)
{
if (!stream)
return;
drivers[stream->type]->mail_close(stream);
}
int
nxmail_sendmsg(char *server, int port,
nxmail_header_t * header, char *body, int size)
{
int ret;
int outsize;
char *output;
/* I'm not happy about this, but for now, this will work */
/* Allocate an extra 1K for the header */
output = (char *) calloc(size + 1024, 1);
if (!output)
return (NXMAIL_ERROR);
outsize = rfc822_build_message(header, body, output);
ret = smtp_send_message(server, port, header, output, outsize);
free(output);
return (ret);
}
int
nxmail_count_addrstr(char *addrstring)
{
char *startptr = addrstring;
int count = 0;
if (*startptr)
count = 1;
else
return (0);
while (1) {
for (; *startptr != ',' && *startptr; startptr++);
if (!*startptr++)
return (count);
count++;
}
}
int
nxmail_build_addrlist(char *addrstring, nxmail_address_t * addrlist,
int count)
{
nxmail_address_t *addr = addrlist;
char *startptr = addrstring;
char *endptr;
int i;
for (i = 0; i < count; i++) {
char str[100];
bzero(str, 100);
sscanf(startptr, "%[^,],", str);
if (!strlen(str))
return (i);
/* bzero(addr, sizeof(nxmail_address_t)); */
rfc822_parse_address(addr, str);
endptr = (startptr + strlen(str) + 1);
if (!*endptr)
return (i + 1);
for (; *endptr == ' ' && *endptr; endptr++);
if (!*endptr)
return (i + 1);
if (addr->next)
addr = addr->next;
else
return (i + 1);
startptr = endptr;
}
return (count);
}
int
nxmail_alloc_addrlist(nxmail_address_t * head, int count)
{
int i;
/* The first entry (the head) is always static, so only */
/* allocate memory if there is more than 1 address */
if (count == 1)
return (1);
for (i = 1; i < count; i++) {
head->next = (nxmail_address_t *) calloc(sizeof(nxmail_address_t), 1);
if (!head->next)
return (i);
head = head->next;
}
return (count);
}
void
nxmail_free_addrlist(nxmail_address_t * head)
{
nxmail_address_t *ptr = head->next;
nxmail_address_t *nptr;
while (ptr) {
nptr = ptr->next;
free(ptr);
ptr = nptr;
}
}
void
nxmail_parse_dateval(unsigned long seconds, nxmail_date_t * date)
{
struct tm *tm = localtime(&seconds);
date->wday = tm->tm_wday;
date->day = tm->tm_mday;
date->month = tm->tm_mon;
date->year = (tm->tm_year + 1900);
date->hour = tm->tm_hour;
date->min = tm->tm_min;
date->sec = tm->tm_sec;
}
nxmail_body_t *
nxmail_alloc_body_struct(int size)
{
nxmail_body_t *ptr = (nxmail_body_t *) calloc(sizeof(nxmail_body_t), 1);
if (!ptr)
return (0);
ptr->size = size;
ptr->next = 0;
return (ptr);
}
void
nxmail_free_body_struct(nxmail_body_t * head)
{
nxmail_body_t *ptr = head;
while (ptr) {
nxmail_body_t *nptr = ptr->next;
free(ptr);
ptr = nptr;
}
}
--- NEW FILE: str_util.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <string.h>
static inline int
isspace(char test)
{
return ((test == ' ' || test == '\t'));
}
/* Turn the given string into lower case */
void
str_lcase(char *value, int len)
{
int i;
for (i = 0; i < len; i++)
if (value[i] >= 65 && value[i] <= 90)
value[i] = value[i] + 32;
}
char *
str_skipwhite(char *ptr)
{
while (isspace(*ptr) && *ptr)
ptr++;
return (ptr);
}
/* WARNING: THIS MANGLES THE STRING */
char *
str_getfield(char *in, char delim, char **field)
{
char *ptr = in;
ptr = str_skipwhite(ptr);
if (!*ptr) {
*field = 0;
return (0);
}
*field = ptr;
/* Now advance until the delim */
while (*ptr != delim && *ptr)
ptr++;
if (*ptr) {
*ptr = 0;
if (*(ptr + 1))
return (ptr + 1);
}
return (0);
}
/* Given a buffer, parse off the keyword and value */
/* WARNING: THIS MANGLES THE STRING */
int
str_parsefield(char *in, char delim, char **keyword, char **value)
{
char *ptr = in;
ptr = str_skipwhite(ptr);
if (!*ptr)
return (0); /* Nothing found */
*keyword = ptr;
/* Now advance until the delim */
while (*ptr != delim && ptr)
ptr++;
if (!*ptr)
return (0);
*ptr = 0;
ptr = str_skipwhite(ptr + 1);
if (!*ptr)
return (0);
*value = ptr;
return (1);
}
/* This copies the string, but it does not mangle it! */
char *
str_getline(char *in, char *out, int outsize)
{
char *inpos = in;
char *outpos = out;
int copied = 0;
/* Zero out the whole buffer */
bzero(out, outsize);
while (*inpos) {
int linesize = 0;
char *curpos = inpos;
/* Find the end of the current line */
while (*curpos != '\n' && *curpos)
curpos++;
/* Calculate the size of the line */
linesize = (int) (curpos - inpos);
/* If the total size of the string is greater than the input, then copy as much as we can */
if (copied + linesize >= outsize) {
strncpy(outpos, inpos, outsize - copied);
return (curpos + 1); /* And return */
}
/* Otherwise, attach the string */
strncpy(outpos, inpos, linesize);
curpos++;
if (!*curpos)
return (0); /* Nothing more to see here */
/* If it is not white space, then this is a new line */
if (!isspace(*curpos))
return (curpos);
/* If there was whitespace, then this is a continued line, so add it on */
/* Turn tabs into spaces */
for (; *curpos && *curpos == '\t'; curpos++)
*curpos = ' ';
inpos = curpos;
outpos += linesize;
copied += linesize;
}
return (0);
}
--- NEW FILE: cache.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
/*
* This manages a simple cache that holds the last
* few messages that were accessed
*/
#define CACHE_SIZE 5
#include <stdlib.h>
#include <string.h>
#include "cache.h"
static cache_entry_t cache_entry[5];
int
get_oldest_entry()
{
int useentry = -1;
int oldest = -1;
int age = 0;
int i;
for (i = 0; i < CACHE_SIZE; i++) {
/* If the age is too high, then it must be corrupted */
if (cache_entry[i].age > 1000) {
bzero(&cache_entry[i], sizeof(cache_entry));
cache_entry[i].age = -1;
}
if (cache_entry[i].age == -1) {
if (useentry == -1)
useentry = i;
} else {
cache_entry[i].age++;
if (cache_entry[i].age > age) {
age = cache_entry[i].age;
oldest = i;
}
}
}
if (useentry != -1)
return (useentry);
return (oldest);
}
cache_entry_t *
search_cache_entry(int key)
{
int i;
for (i = 0; i < CACHE_SIZE; i++) {
if (cache_entry[i].key == key)
return (&cache_entry[i]);
}
return (0);
}
void
free_cache_entry(cache_entry_t * entry)
{
if (entry->raw)
free(entry->raw);
nxmail_free_addrlist(&entry->header.to);
nxmail_free_addrlist(&entry->header.cc);
nxmail_free_body_struct(entry->body);
bzero(entry, sizeof(cache_entry_t));
entry->age = -1;
}
/* The size is the size of the raw message */
cache_entry_t *
get_new_cache_entry(int key, int size)
{
/* Grab the oldest entry */
int entry = get_oldest_entry();
/* If it was being used, then free it */
if (cache_entry[entry].age != -1)
free_cache_entry(&cache_entry[entry]);
/* Now, allocate some space for the raw message */
cache_entry[entry].raw = (char *) calloc(size + 1, 1);
if (!cache_entry[entry].raw)
return (0);
cache_entry[entry].age = 0;
cache_entry[entry].size = size;
cache_entry[entry].key = key;
cache_entry[entry].body = 0;
return (&cache_entry[entry]);
}
void
cache_init(void)
{
int i;
for (i = 0; i < CACHE_SIZE; i++) {
bzero(&cache_entry[i], sizeof(cache_entry_t));
cache_entry[i].age = -1;
}
}
void
cache_close(void)
{
int i;
for (i = 0; i < CACHE_SIZE; i++)
free_cache_entry(&cache_entry[i]);
}
--- NEW FILE: mime.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdlib.h>
#include <string.h>
#include "nxmail.h"
#include "rfc822.h"
#include "mime.h"
#include "str_util.h"
/* This is a local structure that holds all of the mime information */
/* that the client may not care about. This cuts down on each */
/* body section carrying around a huge mime header structure that */
/* is basically useless */
typedef struct
{
char type[50];
char bound[100];
char name[50];
char description[50];
int encoding;
int charset;
}
local_mimeheader_t;
/* These are all of the possible 1.1 MIME fields. Most we can ignore, but those we care about */
static char *
mime_find_next_section(char *buffer, char *boundary)
{
char linebuf[1024];
char *curptr = buffer;
while (1) {
char *nextptr;
if (!curptr)
return (0); /* Nothing there, bail */
/* Grab the line and strip the endline */
nextptr = str_getline(curptr, linebuf, 1024);
/* Jump in two dashes */
if (linebuf[0] == '-' && linebuf[1] == '-') {
if (!strncmp(linebuf + 2, boundary, strlen(boundary))) {
/* It is a boundary. Is it the last one? */
if (linebuf[2 + strlen(boundary)] == '-')
return (0);
else
return (curptr);
}
}
curptr = nextptr;
}
}
void
mime_ignore(char *inptr, local_mimeheader_t * header)
{
return;
}
void
mime_description(char *inptr, local_mimeheader_t * header)
{
strncpy(header->description, inptr, 50);
}
void
mime_contentEncoding(char *inptr, local_mimeheader_t * header)
{
/* Determine the various encoding schemes here */
/* Right now we only handle BASE64 */
str_lcase(inptr, strlen(inptr));
if (!strncmp(inptr, "base64", strlen("base64")))
header->encoding = NXMAIL_ENCODING_BASE64;
else
header->encoding = NXMAIL_ENCODING_NONE;
return;
}
void
mime_charset(char *inptr, local_mimeheader_t * header)
{
}
void
mime_boundary(char *inptr, local_mimeheader_t * header)
{
/* Watch out for the quotes! */
char *ptr = inptr + 1;
/* Look for the other quote, igoring any escaped quotes */
while (*ptr) {
if (*ptr == '"' && *(ptr - 1) != '\\')
break;
ptr++;
}
if (!*ptr)
return;
strncpy(header->bound, inptr + 1, (int) (ptr - inptr) - 1);
}
void
mime_name(char *inptr, local_mimeheader_t * header)
{
strncpy(header->name, inptr, 50);
}
struct
{
char keyword[10];
void (*callback) (char *, local_mimeheader_t * header);
}
content_keyword[] =
{
{
"charset", mime_charset}
, {
"name", mime_name}
, {
"boundary", mime_boundary}
, {
"<none>", 0}
};
/* Stupid content type has a million entries all it own, so we need */
/* to do parsing within parsing */
void
mime_contentType(char *inptr, local_mimeheader_t * header)
{
char *field;
char *curptr;
/* Get the first entry, which is the content type */
curptr = str_getfield(inptr, ';', &field);
if (field)
strcpy(header->type, field);
str_lcase(header->type, strlen(header->type));
/* Now, parse the other items */
while (curptr) {
char *keyword, *value;
curptr = str_getfield(curptr, ';', &field);
if (str_parsefield(field, '=', &keyword, &value)) {
int count = 0;
str_lcase(keyword, strlen(keyword));
/* Go through the content keywords */
while (content_keyword[count].callback) {
if (!strncmp(keyword, content_keyword[count].keyword,
strlen(content_keyword[count].keyword))) {
content_keyword[count].callback(value, header);
break;
}
if (content_keyword[count].callback == 0)
break;
count++;
}
}
}
return;
}
struct
{
char keyword[30];
void (*callback) (char *, local_mimeheader_t * header);
}
mime_keywords[] =
{
{
"--", mime_ignore}
, {
"accept", mime_ignore}
, {
"accept-charset", mime_ignore}
, {
"accept-encoding", mime_ignore}
, {
"accept-language", mime_ignore}
, {
"accept-ranges", mime_ignore}
, {
"authorization", mime_ignore}
, {
"cache-control", mime_ignore}
, {
"connection", mime_ignore}
, {
"content-encoding", mime_contentEncoding}
, {
"content-length", mime_ignore}
, {
"content-range", mime_ignore}
, {
"content-transfer-encoding", mime_contentEncoding}
, {
"content-type", mime_contentType}
, {
"content-description", mime_description}
, {
"digest-MessageDigest", mime_ignore}
, {
"keep-alive", mime_ignore}
, {
"link", mime_ignore}
, {
"location", mime_ignore}
, {
"max-forwards", mime_ignore}
, {
"mime-version", mime_ignore}
, {
"pragma", mime_ignore}
, {
"protocol", mime_ignore}
, {
"protocol-info", mime_ignore}
, {
"protocol-request", mime_ignore}
, {
"proxy-authenticate", mime_ignore}
, {
"proxy-authorization", mime_ignore}
, {
"public", mime_ignore}
, {
"range", mime_ignore}
, {
"referer", mime_ignore}
, {
"retry-after", mime_ignore}
, {
"server", mime_ignore}
, {
"trailer", mime_ignore}
, {
"transfer-encoding", mime_ignore}
, {
"upgrade", mime_ignore}
, {
"user-agent", mime_ignore}
, {
"vary", mime_ignore}
, {
"via", mime_ignore}
, {
"warning", mime_ignore}
, {
"www-authenticate", mime_ignore}
, {
"authentication-info", mime_ignore}
, {
"proxy-authentication-info", mime_ignore}
, {
"<none>", 0}
};
char *
mime_parse_header(char *input, local_mimeheader_t * header)
{
char linebuf[1024];
char *keyword, *value;
char *pos = input;
while (pos) {
int count = 0;
if (!pos)
return (0); /* Nothing there, bail out early */
/* Get the line from the input buffer */
pos = str_getline(pos, linebuf, 1024);
if (strlen(linebuf) == 0)
break;
/* Parse it */
if (str_parsefield(linebuf, ':', &keyword, &value)) {
str_lcase(keyword, strlen(keyword));
while (mime_keywords[count].callback) {
if (!strncmp(keyword, mime_keywords[count].keyword,
strlen(mime_keywords[count].keyword))) {
mime_keywords[count].callback(value, header);
break;
}
count++;
}
}
}
return (pos);
}
nxmail_body_t *
mime_parse_section(char *input, int sectionsize, local_mimeheader_t * header)
{
local_mimeheader_t localheader;
nxmail_body_t *body;
char *bodyptr;
bzero(&localheader, sizeof(local_mimeheader_t));
/* Create a body structure */
body = nxmail_alloc_body_struct(sectionsize);
if (!body)
return (0);
/* Now, check out the section header */
bodyptr = mime_parse_header(input, &localheader);
if (!bodyptr) {
free(body);
return (0);
}
/* Store the mime information */
strcpy(body->mimeheader.type, localheader.type);
strcpy(body->mimeheader.description, localheader.description);
strcpy(body->mimeheader.name, localheader.name);
body->mimeheader.encoding = localheader.encoding;
body->mimeheader.charset = localheader.charset;
body->text = bodyptr;
body->size = (input + sectionsize) - bodyptr;
return (body);
}
/* This function parses the given message into a series of body sections for each mime type */
void
mime_parse_message(char *message, int msgsize, nxmail_header_t * header,
nxmail_body_t ** body)
{
char *curptr = message;
local_mimeheader_t localheader;
bzero(&localheader, sizeof(local_mimeheader_t));
/* Step 1: Go through the main header again, looking for mime related keywords */
curptr = mime_parse_header(curptr, &localheader);
/* The curptr should be pointing at the start of the message, but we're going to cheat */
/* and grab the offset from the nxmail_header_t, just to be safe */
curptr = message + header->offset;
/* Easiest case. No mime encoding at all. Call it a text/plain and bail */
if (!strlen(localheader.type)) {
int size;
nxmail_body_t *bodyptr;
sprintf(header->mimeheader.type, "text/plain");
header->mimeheader.encoding = NXMAIL_ENCODING_NONE;
header->mimeheader.charset = NXMAIL_CHARSET_USASCII;
size = (int) (header->msgsize);
bodyptr = *body = nxmail_alloc_body_struct(size);
bodyptr->size = size;
bodyptr->text = curptr;
return;
}
/* MIME encoding was specified. If the mimetype is not multipart/, then */
/* assume its all one big happy message */
if (strncmp(localheader.type, "multipart", strlen("multipart"))) {
int size;
nxmail_body_t *bodyptr;
strcpy(header->mimeheader.type, localheader.type);
header->mimeheader.encoding = localheader.encoding;
header->mimeheader.charset = localheader.charset;
size = (int) (header->msgsize);
bodyptr = *body = nxmail_alloc_body_struct(size);
bodyptr->size = size;
bodyptr->text = curptr;
return;
}
/* So its a multipart message. Find the first section */
curptr = mime_find_next_section(curptr, localheader.bound);
/* No message. Thats not right.... */
while (1) {
char linebuf[1024];
char *nextptr;
nxmail_body_t *section = 0;
int size = 0;
if (!curptr)
return;
/* First order of business, get rid of the boundary line */
curptr = str_getline(curptr, linebuf, 1024);
if (!curptr)
return;
/* Now find the next section */
nextptr = mime_find_next_section(curptr, localheader.bound);
if (!nextptr)
size = (int) ((message + msgsize) - curptr);
else
size = (int) (nextptr - curptr);
/* Now parse the section */
if (!*body) {
*body = mime_parse_section(curptr, size, &localheader);
section = *body;
} else {
section->next = mime_parse_section(curptr, size, &localheader);
if (section->next)
section = section->next;
}
/* Go back around for the next section */
curptr = nextptr;
}
}
More information about the dslinux-commit
mailing list