- time_t interval;
- ePOP3_C_States State;
- HashList *MsgNumbers;
- HashPos *Pos;
- FetchItem *CurrMsg;
-} pop3aggr;
-
-void DeletePOP3Aggregator(void *vptr)
-{
- pop3aggr *ptr = vptr;
- DeleteHashPos(&ptr->Pos);
- DeleteHash(&ptr->MsgNumbers);
- FreeStrBuf(&ptr->rooms);
- FreeStrBuf(&ptr->pop3user);
- FreeStrBuf(&ptr->pop3pass);
- FreeStrBuf(&ptr->RoomName);
-}
-
-
-typedef eNextState(*Pop3ClientHandler)(pop3aggr* RecvMsg);
-
-eNextState POP3_C_Shutdown(AsyncIO *IO);
-eNextState POP3_C_Timeout(AsyncIO *IO);
-eNextState POP3_C_ConnFail(AsyncIO *IO);
-eNextState POP3_C_DispatchReadDone(AsyncIO *IO);
-eNextState POP3_C_DispatchWriteDone(AsyncIO *IO);
-eNextState POP3_C_Terminate(AsyncIO *IO);
-eReadState POP3_C_ReadServerStatus(AsyncIO *IO);
-
-eNextState FinalizePOP3AggrRun(AsyncIO *IO)
-{
-
- return eAbort;
-}
-
-eNextState FailAggregationRun(AsyncIO *IO)
-{
- return eAbort;
-}
-
-#define POP3C_DBG_SEND() CtdlLogPrintf(CTDL_DEBUG, "POP3 client[%ld]: > %s\n", RecvMsg->n, ChrPtr(RecvMsg->IO.SendBuf.Buf))
-#define POP3C_DBG_READ() CtdlLogPrintf(CTDL_DEBUG, "POP3 client[%ld]: < %s\n", RecvMsg->n, ChrPtr(RecvMsg->IO.IOBuf))
-#define POP3C_OK (strncasecmp(ChrPtr(RecvMsg->IO.IOBuf), "+OK", 3) == 0)
-
-eNextState POP3C_ReadGreeting(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- /* Read the server greeting */
- if (!POP3C_OK) return eTerminateConnection;
- else return eSendReply;
-}
-
-
-eNextState POP3C_SendUser(pop3aggr *RecvMsg)
-{
- /* 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 to be Exchange, which is so b0rken it
- * actually barfs on LF-terminated newlines.
- */
- StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
- "USER %s\r\n", ChrPtr(RecvMsg->pop3user));
- POP3C_DBG_SEND();
- return eReadMessage;
-}
-
-eNextState POP3C_GetUserState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- if (!POP3C_OK) return eTerminateConnection;
- else return eSendReply;
-}
-
-eNextState POP3C_SendPassword(pop3aggr *RecvMsg)
-{
- /* Password */
- StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
- "PASS %s\r\n", ChrPtr(RecvMsg->pop3pass));
- CtdlLogPrintf(CTDL_DEBUG, "<PASS <password>\n");
-// POP3C_DBG_SEND();
- return eReadMessage;
-}
-
-eNextState POP3C_GetPassState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- if (!POP3C_OK) return eTerminateConnection;
- else return eSendReply;
-}
-
-eNextState POP3C_SendListCommand(pop3aggr *RecvMsg)
-{
- /* Get the list of messages */
- StrBufPlain(RecvMsg->IO.SendBuf.Buf, HKEY("LIST\r\n"));
- POP3C_DBG_SEND();
- return eReadMessage;
-}
-
-eNextState POP3C_GetListCommandState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- if (!POP3C_OK) return eTerminateConnection;
- RecvMsg->MsgNumbers = NewHash(1, NULL);
- return eReadMore;
-}
-
-
-eNextState POP3C_GetListOneLine(pop3aggr *RecvMsg)
-{
- FetchItem *OneMsg = NULL;
- POP3C_DBG_READ();
-
- if ((StrLength(RecvMsg->IO.IOBuf) == 1) &&
- (ChrPtr(RecvMsg->IO.IOBuf)[0] == '.'))
- {
- if (GetCount(RecvMsg->MsgNumbers) == 0)
- {
- //// RecvMsg->Sate = ReadQuitState;
- }
- else
- {
- RecvMsg->Pos = GetNewHashPos(RecvMsg->MsgNumbers, 0);
- }
- return eSendReply;
-
- }
- OneMsg = (FetchItem*) malloc(sizeof(FetchItem));
- memset(OneMsg, 0, sizeof(FetchItem));
- OneMsg->MSGID = atoi(ChrPtr(RecvMsg->IO.IOBuf));
- Put(RecvMsg->MsgNumbers, LKEY(OneMsg->MSGID), OneMsg, HfreeFetchItem);
-
- //RecvMsg->State --; /* read next Line */
- return eReadMore;
-}
-
-eNextState POP3C_GetOneMessagID(pop3aggr *RecvMsg)
-{
- long HKLen;
- const char *HKey;
- void *vData;
-
- if(GetNextHashPos(RecvMsg->MsgNumbers, RecvMsg->Pos, &HKLen, &HKey, &vData))
- {
- RecvMsg->CurrMsg = (FetchItem*) vData;
- /* Find out the UIDL of the message, to determine whether we've already downloaded it */
- StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
- "UIDL %ld\r\n", RecvMsg->CurrMsg->MSGID);
- POP3C_DBG_SEND();
- }
- else
- {
- DeleteHashPos(&RecvMsg->Pos);
- /// done receiving uidls.. start looking them up now.
- RecvMsg->Pos = GetNewHashPos(RecvMsg->MsgNumbers, 0);
-
- }
- return eReadMore; /* TODO */
-}
-
-#if 0
-eNextState FetchNetworkUsetableEntry(AsyncIO *IO)
-{
- struct cdbdata *cdbut;
- networker_save_message *Ctx = (networker_save_message *) IO->Data;
-
- if(GetNextHashPos(RecvMsg->MsgNumbers, RecvMsg->Pos, &HKLen, &HKey, &vData))
- {
-
- /* Find out if we've already seen this item */
- strcpy(Ctx->ut.ut_msgid, ChrPtr(Ctx->MsgGUID)); /// TODO
- Ctx->ut.ut_timestamp = time(NULL);
-
- cdbut = cdb_fetch(CDB_USETABLE, SKEY(Ctx->MsgGUID));
- if (cdbut != NULL) {
- /* Item has already been seen */
- CtdlLogPrintf(CTDL_DEBUG, "%s has already been seen\n", ChrPtr(Ctx->MsgGUID));
- cdb_free(cdbut);
-
- /* rewrite the record anyway, to update the timestamp */
- cdb_store(CDB_USETABLE,
- SKEY(Ctx->MsgGUID),
- &Ctx->ut, sizeof(struct UseTable) );
- return eAbort;
- }
- else
- {
- NextDBOperation(IO, RSSSaveMessage);
- return eSendMore;
- }
- }
- return eReadMessage;
-}
-#endif
-
-
-eNextState POP3C_GetOneMessageIDState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- if (!POP3C_OK) return eTerminateConnection;
- RecvMsg->CurrMsg->MsgUIDL = NewStrBufPlain(NULL, StrLength(RecvMsg->IO.IOBuf));
- RecvMsg->CurrMsg->MsgUID = NewStrBufPlain(NULL, StrLength(RecvMsg->IO.IOBuf) * 2);
-
- StrBufExtract_token(RecvMsg->CurrMsg->MsgUIDL, RecvMsg->IO.IOBuf, 2, ' ');
- StrBufPrintf(RecvMsg->CurrMsg->MsgUID,
- "pop3/%s/%s@%s",
- ChrPtr(RecvMsg->RoomName),
- ChrPtr(RecvMsg->CurrMsg->MsgUIDL),
- RecvMsg->Pop3Host.Host);
- return eReadMessage;
-}
-
-eNextState POP3C_GetOneMessageIDFromUseTable(pop3aggr *RecvMsg)
-{
-
- struct cdbdata *cdbut;
- struct UseTable ut;
-
- cdbut = cdb_fetch(CDB_USETABLE, SKEY(RecvMsg->CurrMsg->MsgUID));
- if (cdbut != NULL) {
- /* message has already been seen */
- CtdlLogPrintf(CTDL_DEBUG, "%s has already been seen\n", ChrPtr(RecvMsg->CurrMsg->MsgUID));
- cdb_free(cdbut);
-
- /* rewrite the record anyway, to update the timestamp */
- strcpy(ut.ut_msgid, ChrPtr(RecvMsg->CurrMsg->MsgUID));
- ut.ut_timestamp = time(NULL);
- cdb_store(CDB_USETABLE, SKEY(RecvMsg->CurrMsg->MsgUID), &ut, sizeof(struct UseTable) );
- }
-
- return eReadMessage;
-}
-
-eNextState POP3C_SendGetOneMsg(pop3aggr *RecvMsg)
-{
- /* Message has not been seen. Tell the server to fetch the message... */
- StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
- "RETR %ld\r\n", RecvMsg->CurrMsg->MSGID);
- POP3C_DBG_SEND();
- return eReadMessage;
-}
-
-
-eNextState POP3C_ReadMessageBodyFollowing(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- if (!POP3C_OK) return eTerminateConnection;
- else return eSendReply;
-}
-
-
-
-eNextState POP3C_ReadMessageBody(pop3aggr *RecvMsg)
-{
-#if 0
-//TODO
- /* If we get to this point, the message is on its way. Read it. */
- body = CtdlReadMessageBody(HKEY("."), config.c_maxmsglen, NULL, 1, &sock);
- if (body == NULL) goto bail;
-
- CtdlLogPrintf(CTDL_DEBUG, "Converting message...\n");
- msg = convert_internet_message(body);
- body = NULL; /* yes, this should be dereferenced, NOT freed */
-
- /* Do Something With It (tm) */
- msgnum = CtdlSubmitMsg(msg, NULL, roomname, 0);
- if (msgnum > 0L) {
- /* Message has been committed to the store */
- /* write the uidl to the use table so we don't fetch this message again */
- }
- CtdlFreeMessage(msg);
-#endif
- return eReadMessage;
-}
-
-eNextState POP3C_StoreMsgRead(pop3aggr *RecvMsg)
-{
-#if 0
- strcpy(ut.ut_msgid, utmsgid);
- ut.ut_timestamp = time(NULL);
- cdb_store(CDB_USETABLE, utmsgid, strlen(utmsgid),
- &ut, sizeof(struct UseTable) );
-#endif
- return eReadMessage;/// TODO
-}
-eNextState POP3C_SendDelete(pop3aggr *RecvMsg)
-{
- if (!RecvMsg->keep) {
- StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
- "DELE %ld\r\n", RecvMsg->CurrMsg->MSGID);
- POP3C_DBG_SEND();
- }
- return eReadMessage;
-}
-eNextState POP3C_ReadDeleteState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- return eReadMessage;
-}
-
-eNextState POP3C_SendQuit(pop3aggr *RecvMsg)
-{
- /* Log out */
- StrBufPlain(RecvMsg->IO.SendBuf.Buf,
- HKEY("QUIT\r\n3)"));
- POP3C_DBG_SEND();
- return eReadMessage;
-}
-
-
-eNextState POP3C_ReadQuitState(pop3aggr *RecvMsg)
-{
- POP3C_DBG_READ();
- return eAbort;
-}
-
-const long POP3_C_ConnTimeout = 1000;
-const long DefaultPOP3Port = 110;
-
-Pop3ClientHandler POP3C_ReadHandlers[] = {
- POP3C_ReadGreeting,
- POP3C_GetUserState,
- POP3C_GetPassState,
- POP3C_GetListCommandState,
- POP3C_GetOneMessageIDState,
- POP3C_ReadMessageBodyFollowing,
- POP3C_ReadMessageBody,
- POP3C_ReadQuitState,