/*
* 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
/**
* cache_id - Make a message-cache-compatible id
* @param id POP message id
* @retval ptr Sanitised string
*
* The POP message id may contain '/' and other awkward characters.
*
* @note This function returns a pointer to a static buffer.
*/
static const char *cache_id(const char *id)
{
static char clean[SHORT_STRING];
strfcpy (clean, id, sizeof(clean));
mutt_sanitize_filename (clean, 0);
return clean;
}
/* 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;
LOFF_T length;
char buf[LONG_STRING];
BUFFER *tempfile;
tempfile = mutt_buffer_pool_get ();
mutt_buffer_mktemp (tempfile);
if (!(f = safe_fopen (mutt_b2s (tempfile), "w+")))
{
mutt_perror (mutt_b2s (tempfile));
ret = -3;
goto cleanup;
}
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 " OFF_T_FMT, &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), "%s",
_("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 (mutt_b2s (tempfile));
cleanup:
mutt_buffer_pool_release (&tempfile);
return ret;
}
/* parse UIDL */
static int fetch_uidl (char *line, void *data)
{
int i