#define EVP3C_syslog(LEVEL, FORMAT, ...) \
DBGLOG(LEVEL) syslog(LEVEL, \
- "IO[%ld]CC[%d][%ld]POP3: " FORMAT, \
- IO->ID, CCID, N, __VA_ARGS__)
+ "%s[%ld]CC[%d][%ld]POP3: " FORMAT, \
+ IOSTR, IO->ID, CCID, N, __VA_ARGS__)
#define EVP3CM_syslog(LEVEL, FORMAT) \
DBGLOG(LEVEL) syslog(LEVEL, \
- "IO[%ld]CC[%d][%ld]POP3: " FORMAT, \
- IO->ID, CCID, N)
+ "%s[%ld]CC[%d][%ld]POP3: " FORMAT, \
+ IOSTR, IO->ID, CCID, N)
#define EVP3CQ_syslog(LEVEL, FORMAT, ...) \
DBGLOG(LEVEL) syslog(LEVEL, \
- "P3Q:" FORMAT, \
- __VA_ARGS__)
+ "%s P3Q:" FORMAT, \
+ IOSTR, __VA_ARGS__)
#define EVP3CQM_syslog(LEVEL, FORMAT) \
DBGLOG(LEVEL) syslog(LEVEL, \
- "P3Q" FORMAT \
- )
+ "%s P3Q" FORMAT, \
+ IOSTR)
#define EVP3CCS_syslog(LEVEL, FORMAT, ...) \
- DBGLOG(LEVEL) syslog(LEVEL, "IO[%ld][%ld]POP3: " FORMAT, \
- IO->ID, N, __VA_ARGS__)
+ DBGLOG(LEVEL) syslog(LEVEL, "%s[%ld][%ld]POP3: " FORMAT, \
+ IOSTR, IO->ID, N, __VA_ARGS__)
#define EVP3CCSM_syslog(LEVEL, FORMAT) \
- DBGLOG(LEVEL) syslog(LEVEL, "IO[%ld][%ld]POP3: " FORMAT, \
- IO->ID, N)
+ DBGLOG(LEVEL) syslog(LEVEL, "%s[%ld][%ld]POP3: " FORMAT, \
+ IOSTR, IO->ID, N)
#define POP3C_DBG_SEND() \
EVP3C_syslog(LOG_DEBUG, \
- "IO[%ld]CC[%d][%ld]POP3: > %s\n", \
- IO->ID, CCID, N, \
+ "%s[%ld]CC[%d][%ld]POP3: > %s\n", \
+ IOSTR, IO->ID, CCID, N, \
ChrPtr(RecvMsg->IO.SendBuf.Buf))
#define POP3C_DBG_READ() \
EVP3C_syslog(LOG_DEBUG, \
- "IO[%ld]CC[%d][%ld]POP3: < %s\n", \
- IO->ID, CCID, N, \
+ "%s[%ld]CC[%d][%ld]POP3: < %s\n", \
+ IOSTR, IO->ID, CCID, N, \
ChrPtr(RecvMsg->IO.IOBuf))
free(Item);
}
+
+
+typedef enum _POP3State {
+ eCreated,
+ eGreeting,
+ eUser,
+ ePassword,
+ eListing,
+ eUseTable,
+ eGetMsgID,
+ eGetMsg,
+ eStoreMsg,
+ eDelete,
+ eQuit
+} POP3State;
+
+ConstStr POP3States[] = {
+ {HKEY("Aggregator created")},
+ {HKEY("Reading Greeting")},
+ {HKEY("Sending User")},
+ {HKEY("Sending Password")},
+ {HKEY("Listing")},
+ {HKEY("Fetching Usetable")},
+ {HKEY("Get MSG ID")},
+ {HKEY("Get Message")},
+ {HKEY("Store Msg")},
+ {HKEY("Delete Upstream")},
+ {HKEY("Quit")}
+};
+
+static void SetPOP3State(AsyncIO *IO, POP3State State)
+{
+ CitContext* CCC = IO->CitContext;
+ if (CCC != NULL)
+ memcpy(CCC->cs_clientname, POP3States[State].Key, POP3States[State].len + 1);
+}
+
+
struct pop3aggr {
AsyncIO IO;
eNextState POP3C_ReadGreeting(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+ SetPOP3State(IO, eGreeting);
POP3C_DBG_READ();
/* Read the server greeting */
if (!POP3C_OK) return eTerminateConnection;
eNextState POP3C_SendUser(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+ SetPOP3State(IO, eUser);
/* Identify ourselves. NOTE: we have to append a CR to each command.
* The LF will automatically be appended by sock_puts(). Believe it
* or not, leaving out the CR will cause problems if the server happens
eNextState POP3C_SendPassword(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+ SetPOP3State(IO, ePassword);
/* Password */
StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
"PASS %s\r\n", ChrPtr(RecvMsg->pop3pass));
eNextState POP3C_SendListCommand(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+ SetPOP3State(IO, eListing);
+
/* Get the list of messages */
StrBufPlain(RecvMsg->IO.SendBuf.Buf, HKEY("LIST\r\n"));
POP3C_DBG_SEND();
return eSendReply;
}
+
+ /*
+ * work around buggy pop3 servers which send
+ * empty lines in their listings.
+ */
+ if ((StrLength(RecvMsg->IO.IOBuf) == 0) ||
+ !isdigit(ChrPtr(RecvMsg->IO.IOBuf)[0]))
+ {
+ return eReadMore;
+ }
+
OneMsg = (FetchItem*) malloc(sizeof(FetchItem));
memset(OneMsg, 0, sizeof(FetchItem));
OneMsg->MSGID = atol(ChrPtr(RecvMsg->IO.IOBuf));
long HKLen;
const char *HKey;
void *vData;
- struct cdbdata *cdbut;
pop3aggr *RecvMsg = (pop3aggr *) IO->Data;
+ SetPOP3State(IO, eUseTable);
+
if((RecvMsg->Pos != NULL) &&
GetNextHashPos(RecvMsg->MsgNumbers,
RecvMsg->Pos,
&HKey,
&vData))
{
- struct UseTable ut;
if (server_shutting_down)
return eAbort;
- RecvMsg->CurrMsg = (FetchItem*) vData;
- EVP3CCS_syslog(LOG_DEBUG,
- "CHECKING: whether %s has already been seen: ",
- ChrPtr(RecvMsg->CurrMsg->MsgUID));
-
- /* Find out if we've already seen this item */
- safestrncpy(ut.ut_msgid,
- ChrPtr(RecvMsg->CurrMsg->MsgUID),
- sizeof(ut.ut_msgid));
- ut.ut_timestamp = time(NULL);/// TODO: libev timestamp!
-
- cdbut = cdb_fetch(CDB_USETABLE, SKEY(RecvMsg->CurrMsg->MsgUID));
- if (cdbut != NULL) {
+ if (CheckIfAlreadySeen("POP3 Item Seen",
+ RecvMsg->CurrMsg->MsgUID,
+ IO->Now,
+ IO->Now, //// todo
+ eCheckUpdate,
+ IO->ID, CCID)
+ != 0)
+ {
/* Item has already been seen */
- EVP3CCSM_syslog(LOG_DEBUG, "YES\n");
- cdb_free(cdbut);
-
- /* rewrite the record anyway, to update the timestamp */
- cdb_store(CDB_USETABLE,
- SKEY(RecvMsg->CurrMsg->MsgUID),
- &ut, sizeof(struct UseTable) );
- RecvMsg->CurrMsg->NeedFetch = 0; ////TODO0;
+ RecvMsg->CurrMsg->NeedFetch = 0;
}
else
{
/* ok, now we know them all,
* continue with reading the actual messages. */
DeleteHashPos(&RecvMsg->Pos);
- StopDBWatchers(IO);
- return QueueEventContext(IO, POP3_C_ReAttachToFetchMessages);
+ return DBQueueEventContext(IO, POP3_C_ReAttachToFetchMessages);
}
}
const char *HKey;
void *vData;
+ SetPOP3State(IO, eGetMsgID);
#if 0
int rc;
rc = TestValidateHash(RecvMsg->MsgNumbers);
DeleteHashPos(&RecvMsg->Pos);
/// done receiving uidls.. start looking them up now.
RecvMsg->Pos = GetNewHashPos(RecvMsg->MsgNumbers, 0);
- return QueueDBOperation(&RecvMsg->IO,
- POP3_FetchNetworkUsetableEntry);
+ return EventQueueDBOperation(&RecvMsg->IO,
+ POP3_FetchNetworkUsetableEntry);
}
return eReadMore; /* TODO */
}
const char *HKey;
void *vData;
+ SetPOP3State(IO, eGetMsg);
+
RecvMsg->CurrMsg = NULL;
while ((RecvMsg->Pos != NULL) &&
GetNextHashPos(RecvMsg->MsgNumbers,
eNextState POP3C_StoreMsgRead(AsyncIO *IO)
{
pop3aggr *RecvMsg = (pop3aggr *) IO->Data;
- struct UseTable ut;
+
+ SetPOP3State(IO, eStoreMsg);
EVP3CCS_syslog(LOG_DEBUG,
"MARKING: %s as seen: ",
ChrPtr(RecvMsg->CurrMsg->MsgUID));
-
- safestrncpy(ut.ut_msgid,
- ChrPtr(RecvMsg->CurrMsg->MsgUID),
- sizeof(ut.ut_msgid));
- ut.ut_timestamp = time(NULL); /* TODO: use libev time */
- cdb_store(CDB_USETABLE,
- ChrPtr(RecvMsg->CurrMsg->MsgUID),
- StrLength(RecvMsg->CurrMsg->MsgUID),
- &ut,
- sizeof(struct UseTable) );
- StopDBWatchers(IO);
- return QueueEventContext(&RecvMsg->IO, POP3_C_ReAttachToFetchMessages);
+ CheckIfAlreadySeen("POP3 Item Seen",
+ RecvMsg->CurrMsg->MsgUID,
+ IO->Now,
+ IO->Now, //// todo
+ eWrite,
+ IO->ID, CCID);
+
+ return DBQueueEventContext(&RecvMsg->IO, POP3_C_ReAttachToFetchMessages);
}
eNextState POP3C_SaveMsg(AsyncIO *IO)
{
* so we don't fetch this message again
*/
}
- CtdlFreeMessage(RecvMsg->CurrMsg->Msg);
+ CM_Free(RecvMsg->CurrMsg->Msg);
RecvMsg->count ++;
return NextDBOperation(&RecvMsg->IO, POP3C_StoreMsgRead);
EVP3CM_syslog(LOG_DEBUG, "Converting message...");
RecvMsg->CurrMsg->Msg =
convert_internet_message_buf(&RecvMsg->IO.ReadMsg->MsgBuf);
- StopClientWatchers(IO, 0);
- return QueueDBOperation(&RecvMsg->IO, POP3C_SaveMsg);
+ return EventQueueDBOperation(&RecvMsg->IO, POP3C_SaveMsg);
}
eNextState POP3C_SendDelete(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+
+ SetPOP3State(IO, eDelete);
+
if (!RecvMsg->keep) {
StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
"DELE %ld\r\n", RecvMsg->CurrMsg->MSGID);
eNextState POP3C_SendQuit(pop3aggr *RecvMsg)
{
AsyncIO *IO = &RecvMsg->IO;
+ SetPOP3State(IO, eQuit);
+
/* Log out */
StrBufPlain(RecvMsg->IO.SendBuf.Buf,
HKEY("QUIT\r\n3)"));
DeletePOP3Aggregator);
pthread_mutex_unlock(&POP3QueueMutex);
+ pLine = pLine->next;
}
}