pop3-client.c revision 37703e8d00a3a486aafba6a276fef35b38eab948
/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
#include "pop3-common.h"
#include "array.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
#include "ostream.h"
#include "crc32.h"
#include "str.h"
#include "llist.h"
#include "hostpid.h"
#include "file-dotlock.h"
#include "var-expand.h"
#include "master-service.h"
#include "mail-storage.h"
#include "mail-storage-service.h"
#include "pop3-commands.h"
#include "mail-search-build.h"
#include "mail-namespace.h"
#include <stdlib.h>
#include <unistd.h>
/* max. length of input command line (spec says 512) */
#define MAX_INBUF_SIZE 2048
/* Disconnect client when it sends too many bad commands in a row */
#define CLIENT_MAX_BAD_COMMANDS 20
/* Disconnect client after idling this many milliseconds */
/* If client starts idling for this many milliseconds, commit the current
transaction. This allows the mailbox to become unlocked. */
#define POP3_LOCK_FNAME "dovecot-pop3-session.lock"
extern struct pop3_client_vfuncs pop3_client_vfuncs;
struct pop3_module_register pop3_module_register = { 0 };
struct client *pop3_clients;
unsigned int pop3_client_count;
static enum mail_sort_type pop3_sort_program[] = {
};
static const struct dotlock_settings session_dotlock_set = {
.timeout = 10,
.lock_suffix = "",
};
{
/* Can't commit while commands are running */
return;
}
}
{
"Disconnected for inactivity in reading our output");
} else {
}
}
static int
{
int ret;
/* first try to get the virtual size */
if (ret == 0)
return 0;
return -1;
/* virtual size not available with a fast lookup.
fallback to trying the physical size */
if (ret == 0)
return 0;
return -1;
/* no way to quickly get the size. fallback to doing a slow virtual
size lookup */
}
static void
unsigned int msgnum)
{
return;
/* add any messages between this and the previous one that had
a POP3 order defined */
}
{
struct mailbox_status status;
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
struct mail_search_arg *sarg;
struct mail_search_context *ctx;
unsigned int msgnum;
int ret = 1;
*failed_uid_r = 0;
} else {
}
client->last_seen_pop3_msn = 0;
client->total_size = 0;
msgnum = 0;
break;
}
msgnum++;
}
if (mailbox_search_deinit(&ctx) < 0)
ret = -1;
if (ret <= 0) {
/* commit the transaction instead of rollbacking to make sure
we don't lose data (virtual sizes) added to cache file */
(void)mailbox_transaction_commit(&t);
return ret;
}
}
if (array_is_created(&msgnum_to_seq_map)) {
}
return 1;
}
{
const char *deleted_keywords[2];
return 0;
&client->deleted_kw) < 0) {
"pop3_deleted_flags: Invalid keyword '%s': %s",
return -1;
}
return 0;
}
{
int i, ret = -1;
for (i = 0;; i++) {
MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
ret = -1;
break;
}
if (ret > 0)
return 0;
if (i == 2)
break;
/* well, sync and try again. maybe it works the second time. */
failed_uid = 0;
}
if (ret < 0) {
} else {
/* failed twice in same message */
"Getting size of message UID=%u failed",
} else {
*error_r = "Can't sync mailbox: "
"Messages keep getting expunged";
}
}
return -1;
}
{
switch (var_get_key(++format)) {
case 'v':
mask |= UIDL_UIDVALIDITY;
break;
case 'u':
break;
case 'm':
break;
case 'f':
mask |= UIDL_FILE_NAME;
break;
case 'g':
break;
}
}
}
return mask;
}
{
}
}
{
const struct mail_storage_settings *mail_set =
struct dotlock_settings dotlock_set;
int ret;
"can't create a POP3 session lock file");
return -1;
}
if (ret < 0)
else if (ret > 0) {
}
return ret;
}
struct mail_storage_service_user *service_user,
{
struct mail_storage *storage;
const char *ident;
enum mailbox_flags flags;
const char *errmsg;
int ret;
/* always use nonblocking I/O */
client->v = pop3_client_vfuncs;
"-ERR [IN-USE] Mailbox is locked by another POP3 session.");
return -1;
}
if (!set->pop3_no_flag_updates)
i_error("Couldn't open INBOX: %s",
return -1;
}
return -1;
}
if (client->uidl_keymask == 0)
i_fatal("Invalid pop3_uidl_format");
/* logging uidl_change. we need hashes of the UIDLs */
/* UIDL duplicates aren't allowed, so we'll need to
keep track of them */
}
if (ident != NULL) {
}
if (hook_client_created != NULL)
return 0;
}
{
unsigned int old_msg_count, new_msg_count;
/* UIDL command not given */
return "";
}
/* 1..new-1 were probably left to mailbox by previous POP3 session */
for (i = 0, old_hash = 0; i < old_msg_count; i++)
/* assume all except deleted messages were sent to POP3 client */
} else {
(1 << (i % CHAR_BIT)))
continue;
}
}
else {
return t_strdup_printf("%u/%08x -> %u/%08x",
}
}
{
static struct var_expand_table static_tab[] = {
};
struct var_expand_table *tab;
else
}
{
t_strdup_printf("Connection closed: %m");
}
{
}
{
if (client->seen_change_count > 0)
(void)client_update_mails(client);
if (!client->disconnected) {
}
/* deinitialize command */
}
/* client didn't QUIT, but we still want to save any changes
done in this transaction. especially the cached virtual
message sizes. */
}
if (client->anvil_sent) {
"\n", NULL));
}
}
{
}
{
if (client->disconnected)
return;
}
{
return;
T_BEGIN {
} T_END;
if (ret >= 0) {
if (!POP3_CLIENT_OUTPUT_FULL(client))
/* no more input until client has read
our output */
/* If someone happens to flush output, we want to get
our IO handler back in flush callback */
}
}
}
{
const char *errstr;
enum mail_error error;
"state, please relogin.");
return;
}
switch (error) {
case MAIL_ERROR_TEMP:
case MAIL_ERROR_NOSPACE:
case MAIL_ERROR_INUSE:
break;
default:
break;
}
}
{
int ret;
*args++ = '\0';
T_BEGIN {
} T_END;
if (ret >= 0) {
client->bad_counter = 0;
TRUE);
break;
}
}
}
return FALSE;
}
return TRUE;
}
{
/* we're still processing a command. wait until it's
finished. */
return;
}
case -1:
/* disconnected */
return;
case -2:
/* line too long, kill it */
return;
}
(void)client_handle_input(client);
}
{
return 1;
}
/* enable input again */
client);
}
if (!client_handle_input(client)) {
/* client got destroyed */
return 1;
}
}
}
/* command not finished yet */
return 0;
/* data still in output buffer, get back here to add IO */
return 0;
} else {
return 1;
}
}
void clients_destroy_all(void)
{
while (pop3_clients != NULL) {
}
}
}
struct pop3_client_vfuncs pop3_client_vfuncs = {
};