/*
* Copyright (C) 2000-2002 Vsevolod Volkov <vvv@mutt.org.ua>
* Copyright (C) 2006-2007,2009 Rocco Rutte <pdmef@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "mutt.h"
#include "mutt_curses.h"
#include "mx.h"
#include "pop.h"
#include "mutt_crypt.h"
#include "bcache.h"
#if USE_HCACHE
#include "hcache.h"
#endif
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef USE_HCACHE
#define HC_FNAME "mutt" /* filename for hcache as POP lacks paths */
#define HC_FEXT "hcache" /* extension for hcache as POP lacks paths */
#endif
/* write line to file */
static int fetch_message (char *line, void *file)
{
FILE *f = (FILE *) file;
fputs (line, f);
if (fputc ('\n', f) == EOF)
return -1;
return 0;
}
/*
* Read header
* returns:
* 0 on success
* -1 - connection lost,
* -2 - invalid command or execution error,
* -3 - error writing to tempfile
*/
static int pop_read_header (POP_DATA *pop_data, HEADER *h)
{
FILE *f;
int ret, index;
long length;
char buf[LONG_STRING];
char tempfile[_POSIX_PATH_MAX];
mutt_mktemp (tempfile, sizeof (tempfile));
if (!(f = safe_fopen (tempfile, "w+")))
{
mutt_perror (tempfile);
return -3;
}
snprintf (buf, sizeof (buf), "LIST %d\r\n", h->refno);
ret = pop_query (pop_data, buf, sizeof (buf));
if (ret == 0)
{
sscanf (buf, "+OK %d %ld", &index, &length);
snprintf (buf, sizeof (buf), "TOP %d 0\r\n", h->refno);
ret = pop_fetch_data (pop_data, buf, NULL, fetch_message, f);
if (pop_data->cmd_top == 2)
{
if (ret == 0)
{
pop_data->cmd_top = 1;
dprint (1, (debugfile, "pop_read_header: set TOP capability\n"));
}
if (ret == -2)
{
pop_data->cmd_top = 0;
dprint (1, (debugfile, "pop_read_header: unset TOP capability\n"));
snprintf (pop_data->err_msg, sizeof (pop_data->err_msg),
_("Command TOP is not supported by server."));
}
}
}
switch (ret)
{
case 0:
{
rewind (f);
h->env = mutt_read_rfc822_header (f, h, 0, 0);
h->content->length = length - h->content->offset + 1;
rewind (f);
while (!feof (f))
{
h->content->length--;
fgets (buf, sizeof (buf), f);
}
break;
}
case -2:
{
mutt_error ("%s", pop_data->err_msg);
break;
}
case -3:
{
mutt_error _("Can't write header to temporary file!");
break;
}
}
safe_fclose (&f);
unlink (tempfile);
return ret;
}
/* parse UIDL */
static int fetch_uidl (char *line, void *data)
{
int i, index;
CONTEXT *ctx = (CONTEXT *)data;
POP_DATA *pop_data = (POP_DATA *)ctx->data;
char *endp;
errno = 0;
index = strtol(line, &endp, 10);
if (errno)
return -1;
while (*endp == ' ')
endp++;
memmove(line, endp, strlen(endp) + 1);
for (i = 0; i < ctx->msgcount; i++)
if (!mutt_strcmp (line, ctx->hdrs[i]->data))
break;
if (i == ctx->msgcount)
{
dprint (1, (debugfile, "pop_fetch_headers: new header %d %s\n", index, line));
if (i >= ctx->hdrmax)
mx_alloc_memory(ctx);
ctx->msgcount++;
ctx->hdrs[i] = mutt_new_header ();
ctx->hdrs[i]-&g