home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
-
- YAM - Yet Another Mailer
- Copyright (C) 2000 Marcel Beck <mbeck@yam.ch>
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- YAM Official Support Site : http://www.yam.ch
- YAM OpenSource project : http://sourceforge.net/projects/yamos/
-
- ***************************************************************************/
-
- #include "YAM.h"
-
- /***************************************************************************
- Module: Transfer
- ***************************************************************************/
-
- /*** General connecting/disconnecting & transfer ***/
-
- /// TR_IsOnline
- // Checks if there's an online connection
- BOOL TR_IsOnline(void)
- {
- BOOL isonline = FALSE;
- struct Library *MiamiBase, *GenesisBase, *SoBase;
-
- if (C->IsOnlineCheck)
- {
- if (MiamiBase = OpenLibrary(MIAMINAME, 10))
- {
- isonline = MiamiIsOnline(*C->IOCInterface ? C->IOCInterface : NULL); CloseLibrary(MiamiBase);
- return isonline;
- }
- else if (GenesisBase = OpenLibrary("genesis.library", 1))
- {
- isonline = IsOnline(*C->IOCInterface ? (long)C->IOCInterface : NULL); CloseLibrary(GenesisBase);
- return isonline;
- }
- }
- if (SoBase = OpenLibrary("bsdsocket.library", 2L))
- {
- isonline = TRUE; CloseLibrary(SoBase);
- }
- return isonline;
- }
- ///
- /// TR_CloseTCPIP
- // Closes bsdsocket library
- void TR_CloseTCPIP(void)
- {
- if (SocketBase) CloseLibrary(SocketBase);
- SocketBase = NULL;
- }
- ///
- /// TR_OpenTCPIP
- // Opens bsdsocket.library
- BOOL TR_OpenTCPIP(void)
- {
- if (!TR_IsOnline()) return FALSE;
- if (!SocketBase) SocketBase = OpenLibrary("bsdsocket.library", 2L);
- return (BOOL)(SocketBase != NULL);
- }
- ///
- /// TR_Disconnect
- // Terminates a connection
- void TR_Disconnect(void)
- {
- if (G->TR_Socket != SMTP_NO_SOCKET)
- {
- Shutdown(G->TR_Socket, 2);
- CloseSocket(G->TR_Socket);
- G->TR_Socket = SMTP_NO_SOCKET;
- }
- }
- ///
- /// TR_Connect
- // Connects to a internet service
- int TR_Connect(char *host, int port)
- {
- struct hostent *hostaddr;
-
- if (!(hostaddr = GetHostByName((STRPTR)host))) return -1;
- G->TR_INetSocketAddr.sin_len = sizeof(G->TR_INetSocketAddr);
- G->TR_INetSocketAddr.sin_family = 2;
- G->TR_INetSocketAddr.sin_port = port;
- G->TR_INetSocketAddr.sin_addr.s_addr = 0;
- memcpy(&G->TR_INetSocketAddr.sin_addr, hostaddr->h_addr, hostaddr->h_length);
- G->TR_Socket = Socket(hostaddr->h_addrtype, 1, 0);
- if (G->TR_Socket == -1) { TR_Disconnect(); return -2; }
- if (Connect(G->TR_Socket, (struct sockaddr *)&G->TR_INetSocketAddr, sizeof(G->TR_INetSocketAddr)) == -1) { TR_Disconnect(); return -3; }
- return 0;
- }
- ///
- /// TR_RecvDat
- // Receives data from a TCP/IP connection
- int TR_RecvDat(char *recvdata) /* success? */
- {
- int len;
-
- DoMethod(G->App,MUIM_Application_InputBuffered);
- if (G->TR_Socket == SMTP_NO_SOCKET) return 0;
- len = Recv(G->TR_Socket, (STRPTR)recvdata, SIZE_LINE-1, 0);
- recvdata[len] = '\0';
- if (G->TR_Debug) printf("SERVER: %s", recvdata);
- return len;
- }
- ///
- /// TR_SendDat
- // Sends data through a TCP/IP connection
- BOOL TR_SendDat(char *senddata) /* success? */
- {
- DoMethod(G->App,MUIM_Application_InputBuffered);
- if (G->TR_Socket == SMTP_NO_SOCKET) return FALSE;
- if (!senddata) return TRUE;
- if (G->TR_Debug) printf("CLIENT: %s", senddata);
- if (Send(G->TR_Socket, (STRPTR)senddata, strlen(senddata), 0) != -1) return TRUE;
- return FALSE;
- }
- ///
- /// TR_SetWinTitle
- // Sets the title of the transfer window
- void TR_SetWinTitle(BOOL from, char *host)
- {
- sprintf(G->TR->WTitle, GetStr(from ? MSG_TR_MailTransferFrom : MSG_TR_MailTransferTo), host);
- set(G->TR->GUI.WI, MUIA_Window_Title, G->TR->WTitle);
- }
- ///
-
- /*** HTTP routines ***/
- /// TR_DownloadURL
- // Downloads a file from the web using HTTP
- BOOL TR_DownloadURL(char *url0, char *url1, char *url2, char *filename)
- {
-
- BOOL success = FALSE, done = FALSE, noproxy = !*C->ProxyServer;
- int l = 0, len, hport;
- char buf[SIZE_LINE], url[SIZE_URL], host[SIZE_HOST], *port, *path, line[SIZE_DEFAULT], *bufptr;
- FILE *out;
-
- G->Error = FALSE;
- if (!strnicmp(url0,"http://",7)) strcpy(url, &url0[7]); else strcpy(url, url0);
- if (url1)
- {
- if (url[strlen(url)-1] != '/') strcat(url, "/");
- strcat(url, url1);
- }
- if (url2)
- {
- if (url[strlen(url)-1] != '/') strcat(url, "/");
- strcat(url, url2);
- }
- if (path = strchr(url,'/')) *path++ = 0; else path = "";
- strcpy(host, noproxy ? url : C->ProxyServer);
- if (bufptr = strchr(host, ':')) { *bufptr++ = 0; hport = atoi(bufptr); }
- else hport = noproxy ? 80 : 8080;
- if (!TR_Connect(host, hport))
- {
- /*
- if (noproxy) sprintf(buf, "GET /%s HTTP/1.0\r\nHost: http://%s\r\n", path, host);
- else if (port = strchr(url, ':'))
- {
- *port++ = 0;
- sprintf(buf, "GET http://%s:%s/%s HTTP/1.0\r\nHost: http://%s\r\n", url, port, path, url);
- }
- else sprintf(buf, "GET http://%s/%s HTTP/1.0\r\nHost: http://%s\r\n", url, path, url);
- sprintf(&buf[strlen(buf)], "From: %s\r\nUser-Agent: YAM %s\r\n\r\n", BuildAddrName(C->EmailAddress, C->RealName), __VERSION__);
- */
- if (noproxy) sprintf(buf, "GET /%s HTTP/1.0\r\nHost: %s\r\n", path, host);
- else if (port = strchr(url, ':'))
- {
- *port++ = 0;
- sprintf(buf, "GET http://%s:%s/%s HTTP/1.0\r\nHost: %s\r\n", url, port, path, url);
- }
- else sprintf(buf, "GET http://%s/%s HTTP/1.0\r\nHost: %s\r\n", url, path, url);
- sprintf(&buf[strlen(buf)], "From: %s\r\nUser-Agent: YAM %s\r\n\r\n", BuildAddrName(C->EmailAddress, C->RealName), __VERSION__);
- if (TR_SendDat(buf))
- {
- len = TR_RecvDat(buf);
- if (atoi(&buf[9]) == 200)
- {
- if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- while (!G->Error)
- {
- for (; *bufptr; bufptr++)
- {
- if (*bufptr != '\r') if (l < SIZE_DEFAULT-1) line[l++] = *bufptr;
- if (*bufptr != '\n') continue;
- line[l] = 0; l = 0;
- if (line[0] == '\n') { done = TRUE; break; }
- }
- if (done) break;
- if ((len = TR_RecvDat(buf)) <= 0) break;
- bufptr = buf;
- }
- if (out = fopen(filename, "w"))
- {
- ++bufptr;
- fwrite(bufptr, len-(bufptr-buf), 1, out);
- while ((len = TR_RecvDat(buf)) > 0) fwrite(buf, len, 1, out);
- fclose(out);
- success = TRUE;
- }
- else ER_NewError(GetStr(MSG_ER_CantCreateFile), filename, NULL);
- }
- else ER_NewError(GetStr(MSG_ER_DocNotFound), path, NULL);
- }
- else ER_NewError(GetStr(MSG_ER_SendHTTP), NULL, NULL);
- TR_Disconnect();
- }
- else ER_NewError(GetStr(MSG_ER_ConnectHTTP), host, NULL);
- return success;
- }
- ///
-
- /*** POP3 routines ***/
- /// TR_SendPopCmd
- // Sends a command to the POP3 server
- BOOL TR_SendPopCmd(char *buf, char *cmdtext, char *parmtext, int flags)
- {
- char cmdbuf[SIZE_COMMAND];
- int len, ln;
-
- if (G->TR_Socket == SMTP_NO_SOCKET) return FALSE;
- if (!parmtext || !*parmtext) sprintf(cmdbuf, "%s\r\n", cmdtext);
- else sprintf(cmdbuf, "%s %s\r\n", cmdtext, parmtext);
- if (!TR_SendDat(cmdbuf)) return FALSE;
- if (!(len = TR_RecvDat(buf))) return FALSE;
- if (flags & POPCMD_WAITEOL)
- while (buf[len-1] != '\n') if (ln = TR_RecvDat(&buf[len])) len += ln; else return FALSE;
- if (!strncmp(buf, "-ERR", 4))
- {
- if (!(flags & POPCMD_NOERROR)) ER_NewError(GetStr(MSG_ER_BadResponse), cmdtext, buf);
- return FALSE;
- }
- return TRUE;
- }
- ///
- /// TR_ConnectPOP
- // Connects to a POP3 mail server
- int TR_ConnectPOP(int guilevel)
- {
- char passwd[SIZE_PASSWORD], host[SIZE_HOST], buf[SIZE_LINE], *p;
- int err, pop = G->TR->POP_Nr, msgs, port = 110;
-
- strcpy(passwd, C->P3[pop]->Password);
- strcpy(host, C->P3[pop]->Server);
- if (C->TransferWindow == 2 || (C->TransferWindow == 1 && (guilevel == POP_START || guilevel == POP_USER))) set(G->TR->GUI.WI, MUIA_Window_Open, TRUE);
- set(G->TR->GUI.TX_STATUS , MUIA_Text_Contents,GetStr(MSG_TR_Connecting));
- if (p = strchr(host, ':')) { *p = 0; port = atoi(++p); }
- TR_SetWinTitle(TRUE, host);
- if (err = TR_Connect(host, port))
- {
- if (guilevel == POP_USER) switch (err)
- {
- case -1: ER_NewError(GetStr(MSG_ER_UnknownPOP), C->P3[pop]->Server, NULL); break;
- default: ER_NewError(GetStr(MSG_ER_CantConnect), C->P3[pop]->Server, NULL);
- }
- return -1;
- }
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_WaitWelcome));
- if (!TR_RecvDat(buf)) return -1;
- if (!*passwd)
- {
- sprintf(buf, GetStr(MSG_TR_PopLoginReq), C->P3[pop]->User, host);
- if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_TR_PopLogin), buf, GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, G->TR->GUI.WI)) return -1;
- }
- if (C->P3[pop]->UseAPOP)
- {
- MD5_CTX context;
- UBYTE digest[16], *welcomemsg = StrBufCpy(NULL, buf);
- int i, j;
-
- while (!strstr(buf, "\n"))
- {
- if (!TR_RecvDat(buf)) return -1;
- welcomemsg = StrBufCat(welcomemsg, buf);
- }
- *buf = 0;
- if (p = strchr(welcomemsg, '<'))
- {
- strcpy(buf, p);
- if (p = strchr(buf, '>')) p[1] = 0;
- }
- else ER_NewError(GetStr(MSG_ER_NoAPOP), NULL, NULL);
- strcat(buf, passwd);
- FreeStrBuf(welcomemsg);
- MD5Init(&context);
- MD5Update(&context, buf, strlen(buf));
- MD5Final(digest, &context);
- sprintf(buf, "%s ", C->P3[pop]->User);
- for (j=strlen(buf), i=0; i<16; j+=2, i++) sprintf(&buf[j], "%02x", digest[i]);
- buf[j] = 0;
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_SendAPOPLogin));
- if (!TR_SendPopCmd(buf, "APOP", buf, POPCMD_WAITEOL)) return -1;
- }
- else
- {
- while (!strstr(buf, "\n")) if (!TR_RecvDat(buf)) return -1;
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_SendUserID));
- if (!TR_SendPopCmd(buf, "USER", C->P3[pop]->User, POPCMD_WAITEOL)) return -1;
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_SendPassword));
- if (!TR_SendPopCmd(buf, "PASS", passwd, POPCMD_WAITEOL)) return -1;
- }
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_GetStats));
- if (!TR_SendPopCmd(buf, "STAT", NULL, POPCMD_WAITEOL)) return -1;
- sscanf(&buf[4], "%ld", &msgs);
- if (msgs) AppendLogVerbose(31, GetStr(MSG_LOG_ConnectPOP), C->P3[pop]->User, host, (void *)msgs, "");
- return msgs;
- }
- ///
- /// TR_DisplayMailList
- // Displays a list of messages ready for download
- void TR_DisplayMailList(BOOL largeonly)
- {
- struct Mail *mail;
- APTR lv = G->TR->GUI.LV_MAILS;
- int pos = 0;
- set(lv, MUIA_NList_Quiet, TRUE);
- for (mail = G->TR->List; mail; mail = mail->Next)
- if (mail->Size >= C->WarnSize<<10 || !largeonly)
- {
- mail->Position = pos++;
- DoMethod(lv, MUIM_NList_InsertSingle, mail, MUIV_NList_Insert_Bottom);
- }
- set(lv, MUIA_NList_Quiet, FALSE);
- }
- ///
- /// TR_AddMessageHeader
- // Parses downloaded message header
- void TR_AddMessageHeader(int *count, int size, char *tfname)
- {
- struct Mail *mail;
- struct ExtendedMail *email;
-
- if (email = MA_ExamineMail((struct Folder *)-1, tfname, NULL, FALSE))
- {
- mail = calloc(1,sizeof(struct Mail));
- *mail = email->Mail;
- mail->Folder = NULL;
- mail->Status = 1;
- mail->Index = ++(*count);
- mail->Size = size;
- MA_FreeEMailStruct(email);
- MyAddTail(&(G->TR->List), mail);
- }
- }
- ///
- /// TR_GetMessageList_IMPORT
- // Collects messages from a UUCP mailbox file
- void TR_GetMessageList_IMPORT(FILE *fh)
- {
- BOOL body = FALSE;
- int c = 0, size = 0;
- char buffer[SIZE_LINE], *ptr, *tfname = "yamIMP.tmp", fname[SIZE_PATHFILE];
- FILE *f = NULL;
-
- strmfp(fname, C->TempDir, tfname);
- G->TR->List = NULL;
- fseek(fh, 0, SEEK_SET);
- while (fgets(buffer, SIZE_LINE, fh))
- {
- if (f || body) size += strlen(buffer);
- if (ptr = strpbrk(buffer, "\r\n")) *ptr = 0;
- if (!f && !strncmp(buffer, "From ", 5))
- {
- if (body) { TR_AddMessageHeader(&c, size, tfname); DeleteFile(fname); }
- if (!(f = fopen(fname, "w"))) break;
- size = 0; body = FALSE;
- }
- if (f)
- {
- fputs(buffer, f); fputc('\n', f);
- if (!*buffer)
- {
- fclose(f); f = NULL;
- body = TRUE;
- }
- }
- }
- if (body) { TR_AddMessageHeader(&c, size, tfname); DeleteFile(fname); }
- TR_DisplayMailList(FALSE);
- }
- ///
- /// TR_GetMessageList_GET
- // Collects messages waiting on a POP3 server
- BOOL TR_GetMessageList_GET(int maxmsgs)
- {
- char buf[SIZE_LINE];
-
- if (TR_SendPopCmd(buf, "LIST", NULL, 0))
- {
- int mode, l = 0, index, size;
- char line[SIZE_DEFAULT], *bufptr;
- BOOL done = FALSE;
- struct Mail *new;
-
- G->TR->List = NULL;
- if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- else if (TR_RecvDat(buf) > 0) if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- if (!bufptr) return FALSE;
- while (!G->Error)
- {
- for (; *bufptr; bufptr++)
- {
- if (*bufptr != '\r') if (l < SIZE_DEFAULT-1) line[l++] = *bufptr;
- if (*bufptr != '\n') continue;
- line[l] = 0; l = 0;
- if (line[0] == '.' && line[1] == '\n') { done = TRUE; break; }
- sscanf(line, "%ld %ld", &index, &size);
- if (index) if (new = calloc(1,sizeof(struct Mail)))
- {
- static int mode2status[16] = { 1,1,3,3,1,1,3,3,0,1,0,3,0,1,0,3 };
- new->Index = index; new->Size = size; new->Folder = NULL;
- mode = (C->DownloadLarge ? 1 : 0) +
- (C->P3[G->TR->POP_Nr]->DeleteOnServer ? 2 : 0) +
- (G->TR->GUIlevel == POP_USER ? 4 : 0) +
- ((C->WarnSize && new->Size >= (C->WarnSize<<10)) ? 8 : 0);
- new->Status = mode2status[mode];
- MyAddTail(&(G->TR->List), new);
- }
- }
- if (done) break;
- if (TR_RecvDat(buf) <= 0) break;
- bufptr = buf;
- }
- return TRUE;
- }
- else return FALSE;
- }
- ///
- /// TR_AppendUIDL
- // Appends a UIDL to the .uidl file
- void TR_AppendUIDL(char *uidl)
- {
- FILE *fh;
- if (fh = fopen(CreateFilename(".uidl"), "a"))
- {
- fprintf(fh, "%s\n", uidl);
- fclose(fh);
- }
- }
- ///
- /// TR_FindUIDL
- // Searches UIDL list for a given UIDL
- BOOL TR_FindUIDL(char *uidl)
- {
- int l = strlen(uidl);
- char *p = G->TR->UIDLloc;
- if (p) while (*p)
- {
- if (!strncmp(p, uidl, l)) return TRUE;
- while (*p) if (*p++ == '\n') break;
- }
- return FALSE;
- }
- ///
- /// TR_GetUIDLonDisk
- // Loads local UIDL list from disk
- char *TR_GetUIDLonDisk(void)
- {
- FILE *fh;
- char *text = NULL, *file = CreateFilename(".uidl");
- int size;
-
- if ((size = FileSize(file)) > 0)
- if (text = calloc(size+1,1))
- if (fh = fopen(file, "r"))
- {
- fread(text, 1, size, fh);
- fclose(fh);
- }
- return text;
- }
- ///
- /// TR_GetUIDLonServer
- // Gets remote UIDL list from the POP3 server
- BOOL TR_GetUIDLonServer(void)
- {
- char buf[SIZE_LINE];
-
- if (TR_SendPopCmd(buf, "UIDL", NULL, POPCMD_NOERROR))
- {
- int num, l = 0;
- struct Mail *mail;
- char uidl[SIZE_DEFAULT+SIZE_HOST], line[SIZE_DEFAULT], *bufptr;
- BOOL done = FALSE;
-
- if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- while (!G->Error)
- {
- for (; *bufptr; bufptr++)
- {
- if (*bufptr != '\r') if (l < SIZE_DEFAULT-1) line[l++] = *bufptr;
- if (*bufptr != '\n') continue;
- line[l] = 0; l = 0;
- if (line[0] == '.' && line[1] == '\n') { done = TRUE; break; }
- sscanf(line, "%ld %s", &num, uidl);
- strcat(uidl, "@"); strcat(uidl, C->P3[G->TR->POP_Nr]->Server);
- for (mail = G->TR->List; mail; mail = mail->Next)
- if (mail->Index == num) { mail->UIDL = AllocCopy(uidl, strlen(uidl)+1); break; }
- }
- if (done) break;
- if (TR_RecvDat(buf) <= 0) break;
- bufptr = buf;
- }
- return TRUE;
- }
- else return FALSE;
- }
- ///
- /// TR_ApplyRemoteFilters
- // Applies remote filters to a message
- void TR_ApplyRemoteFilters(struct Mail *mail)
- {
- int i;
-
- for (i = 0; i < G->TR->Scnt; i++) if (FI_DoComplexSearch(G->TR->Search[i], G->TR->Search[i]->Rule->Combine, G->TR->Search[i+MAXRU], mail))
- {
- struct Rule *rule = G->TR->Search[i]->Rule;
- if (rule->Actions & 8) if (*rule->ExecuteCmd) ExecuteCommand(rule->ExecuteCmd, FALSE, NULL);
- if (rule->Actions & 16) if (*rule->PlaySound) PlaySound(rule->PlaySound);
- if (rule->Actions & 64) mail->Status |= 2; else mail->Status &= ~2;
- if (rule->Actions & 128) mail->Status &= ~1; else mail->Status |= 1;
- return;
- }
- }
- ///
- /// TR_GetMessageDetails
- // Gets header from a message stored on the POP3 server
- void TR_GetMessageDetails(struct Mail *mail, int lline)
- {
- if (!*mail->From.Address)
- {
- char buf[SIZE_LINE], cmdbuf[SIZE_SMALL], *tfname = "yamTOP.tmp";
- sprintf(cmdbuf, "%ld 1", mail->Index);
- if (TR_SendPopCmd(buf, "TOP", cmdbuf, POPCMD_NOERROR))
- {
- char fname[SIZE_PATHFILE];
- FILE *f;
- strmfp(fname, C->TempDir, tfname);
- if (f = fopen(fname, "w"))
- {
- struct ExtendedMail *email;
- int l = 0;
- char line[SIZE_LINE], *bufptr;
- BOOL done = FALSE;
-
- if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- while (!G->Error && !G->TR->Abort)
- {
- for (; *bufptr; bufptr++)
- {
- if (*bufptr != '\r') line[l++] = *bufptr;
- if (l == SIZE_LINE-1)
- {
- line[l] = 0; l = 0;
- if (fputs(line, f) == EOF) { ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), fname, NULL); break; }
- }
- if (*bufptr != '\n') continue;
- line[l] = 0; l = 0;
- if (line[0] == '.') if (line[1] == '\n') { done = TRUE; break; }
- if (fputs(line, f) == EOF) { ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), fname, NULL); break; }
- }
- if (done) break;
- if (TR_RecvDat(buf) <= 0) break;
- bufptr = buf;
- }
- fclose(f);
- if (email = MA_ExamineMail(NULL, tfname, NULL, TRUE))
- {
- mail->From = email->Mail.From;
- mail->To = email->Mail.To;
- mail->ReplyTo = email->Mail.ReplyTo;
- strcpy(mail->Subject, email->Mail.Subject);
- strcpy(mail->MailFile, email->Mail.MailFile);
- mail->Date = email->Mail.Date;
- if (lline == -1)
- {
- char uidl[SIZE_DEFAULT+SIZE_HOST];
- sprintf(uidl, "%s@%s", Trim(email->MsgID), C->P3[G->TR->POP_Nr]->Server);
- mail->UIDL = AllocCopy(uidl, strlen(uidl)+1);
- }
- if (lline == -2) TR_ApplyRemoteFilters(mail);
- DeleteFile(fname);
- MA_FreeEMailStruct(email);
- }
- }
- else ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), fname, NULL);
- fclose(f);
- }
- }
- if (lline >= 0) DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_Redraw, lline);
- }
- ///
- /// TR_GetUIDL
- // Filters out duplicate messages
- void TR_GetUIDL(void)
- {
- struct Mail *mail;
- G->TR->supportUIDL = TR_GetUIDLonServer();
- G->TR->UIDLloc = TR_GetUIDLonDisk();
- for (mail = G->TR->List; mail; mail = mail->Next)
- {
- if (!G->TR->supportUIDL) TR_GetMessageDetails(mail, -1);
- if (TR_FindUIDL(mail->UIDL)) { G->TR->Stats.DupSkipped++; mail->Status &= 2; }
- }
- }
- ///
- /// TR_DisconnectPOP
- // Terminates a POP3 session
- void TR_DisconnectPOP(void)
- {
- char buf[SIZE_LINE];
-
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_Disconnecting));
- if (!G->TR->Abort) TR_SendPopCmd(buf, "QUIT", NULL, POPCMD_WAITEOL);
- TR_Disconnect();
- }
- ///
- /// TR_GetMailFromNextPOP
- // Downloads and filters mail from a POP3 account
- void TR_GetMailFromNextPOP(BOOL isfirst, int singlepop, int guilevel)
- {
- extern SAVEDS void TR_ProcessGETFunc(void);
- struct Mail *mail;
- static int laststats;
- int msgs, pop = singlepop;
-
- if (isfirst) /* Init first connection */
- {
- G->LastDL.Error = TRUE;
- if (!TR_OpenTCPIP()) { if (guilevel == POP_USER) ER_NewError(GetStr(MSG_ER_NoTCP), NULL, NULL); return; }
- if (!CO_IsValid()) { TR_CloseTCPIP(); return; }
- if (!(G->TR = TR_New(TR_GET))) { TR_CloseTCPIP(); return; }
- G->TR->Checking = TRUE; DisplayStatistics((struct Folder *)-1);
- G->TR->GUIlevel = guilevel;
- G->TR->Scnt = MA_AllocRules(G->TR->Search, APPLY_REMOTE);
- if (singlepop >= 0) G->TR->SinglePOP = TRUE;
- else G->TR->POP_Nr = -1;
- laststats = 0;
- }
- else /* Finish previous connection */
- {
- struct POP3 *p = C->P3[G->TR->POP_Nr];
- TR_DisconnectPOP();
- TR_Cleanup();
- AppendLogNormal(30, GetStr(MSG_LOG_Retrieving), (void *)(G->TR->Stats.Downloaded-laststats), p->User, p->Server, "");
- if (G->TR->SinglePOP) pop = MAXP3;
- laststats = G->TR->Stats.Downloaded;
- }
- if (!G->TR->SinglePOP) for (pop = ++G->TR->POP_Nr; pop < MAXP3; pop++)
- if (C->P3[pop]) if (C->P3[pop]->Enabled) break;
- if (pop == MAXP3) /* Finish last connection */
- {
- TR_CloseTCPIP();
- set(G->TR->GUI.WI, MUIA_Window_Open, FALSE);
- MA_FreeRules(G->TR->Search, G->TR->Scnt);
- MA_StartMacro(MACRO_POSTGET, itoa(G->TR->Stats.Downloaded));
- DoMethod(G->App, MUIM_CallHook, &MA_ApplyRulesHook, APPLY_AUTO, 0, FALSE);
- G->TR->Checking = FALSE; DisplayStatistics((struct Folder *)-1);
- TR_NewMailAlert();
- MA_ChangeTransfer(TRUE);
- DisposeModulePush(&G->TR);
- if (G->TR_Exchange)
- {
- G->TR_Exchange = FALSE;
- DoMethod(G->App, MUIM_Application_PushMethod, G->App, 3, MUIM_CallHook, &MA_SendHook, SEND_ALL);
- }
- return;
- }
- G->TR->POP_Nr = pop;
- G->TR_Allow = G->TR->Abort = G->Error = FALSE;
- if ((msgs = TR_ConnectPOP(G->TR->GUIlevel)) != -1)
- {
- if (msgs)
- {
- if (TR_GetMessageList_GET(msgs))
- {
- BOOL preselect = FALSE;
- G->TR->Stats.OnServer += msgs;
- if (G->TR->Scnt)
- {
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_ApplyFilters));
- for (mail = G->TR->List; mail; mail = mail->Next)
- TR_GetMessageDetails(mail, -2);
- }
- if (C->AvoidDuplicates) TR_GetUIDL();
- if (G->TR->GUIlevel == POP_USER)
- {
- if (C->PreSelection >= 2) preselect = TRUE;
- if (C->WarnSize && C->PreSelection)
- for (mail = G->TR->List; mail; mail = mail->Next)
- if (mail->Size >= C->WarnSize<<10) { preselect = TRUE; break; }
- }
- if (preselect)
- {
- set(G->TR->GUI.WI, MUIA_Window_Open, TRUE);
- if (C->PreSelection == 1)
- {
- TR_DisplayMailList(TRUE);
- set(G->TR->GUI.GR_LIST, MUIA_ShowMe, TRUE);
- set(G->TR->GUI.WI, MUIA_Window_Activate, TRUE);
- DoMethod(G->TR->GUI.WI, MUIM_Window_ScreenToFront);
- }
- else TR_DisplayMailList(FALSE);
- set(G->TR->GUI.GR_PAGE, MUIA_Group_ActivePage, 0);
- G->TR->GMD_Mail = G->TR->List;
- G->TR->GMD_Line = 0;
- TR_CompleteMsgList();
- return;
- }
- else
- {
- TR_ProcessGETFunc();
- }
- return;
- }
- }
- }
- else G->TR->Stats.Error = TRUE;
- TR_GetMailFromNextPOP(FALSE, 0, 0);
- }
- ///
-
- /*** SMTP routines ***/
- /// TR_SendSMTPCmd
- // Sends a command to the SMTP server
- BOOL TR_SendSMTPCmd(char *cmdtext, char *parmtext)
- {
- int len;
- static char buffer[SIZE_LINE];
- char cont;
-
- if (G->TR_Socket == SMTP_NO_SOCKET) return FALSE;
- if (cmdtext)
- {
- sprintf(buffer, "%s\r\n", cmdtext);
- if (parmtext) if (*parmtext) sprintf(buffer, "%s %s\r\n", cmdtext, parmtext);
- }
- else *buffer = 0;
- if (!TR_SendDat(buffer)) return FALSE;
- if (!(len = TR_RecvDat(buffer))) return FALSE;
- switch (atoi(buffer))
- {
- case 211: case 214: case 220: case 221:
- case 250: case 251: case 354: break;
- default: ER_NewError(GetStr(MSG_ER_BadResponse), cmdtext, buffer); return FALSE;
- }
- cont = buffer[3];
- while (buffer[len-1] != '\n') if (!(len = TR_RecvDat(buffer))) return FALSE;
- if (cont == '-') while (buffer[len-1] != '\n') if (!(len = TR_RecvDat(buffer))) break;
- return TRUE;
- }
- ///
- /// TR_ConnectSMTP
- // Connects to a SMTP mail server
- BOOL TR_ConnectSMTP(void)
- {
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_WaitWelcome));
- if (!TR_SendSMTPCmd(NULL, NULL)) return FALSE;
- set(G->TR->GUI.TX_STATUS,MUIA_Text_Contents, GetStr(MSG_TR_SendHello));
- if (!TR_SendSMTPCmd("HELO", C->SMTP_Domain)) return FALSE;
- return TRUE;
- }
- ///
- /// TR_DisconnectSMTP
- // Terminates a SMTP session
- void TR_DisconnectSMTP(void)
- {
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_Disconnecting));
- if (!G->TR->Abort) TR_SendSMTPCmd("QUIT", NULL);
- TR_Disconnect();
- }
- ///
- /// TR_ChangeStatusFunc
- // Changes status of selected messages
- SAVEDS ASM void TR_ChangeStatusFunc(REG(a1) int *arg)
- {
- int id = MUIV_NList_NextSelected_Start;
- struct Mail *mail;
- for (;;)
- {
- DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_NextSelected, &id);
- if (id == MUIV_NList_NextSelected_End) break;
- DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_GetEntry, id, &mail);
- mail->Status = *arg;
- DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_Redraw, id);
- }
- }
- MakeHook(TR_ChangeStatusHook, TR_ChangeStatusFunc);
- ///
- /// TR_GetSeconds
- // Gets current date and time in seconds
- long TR_GetSeconds(void)
- {
- struct DateStamp ds;
- DateStamp(&ds);
- return ((86400*ds.ds_Days) + (60*ds.ds_Minute) + (ds.ds_Tick/50));
- }
- ///
- /// TR_TransStat_Init
- // Initializes transfer statistics
- void TR_TransStat_Init(struct TransStat *ts)
- {
- struct Mail *mail;
-
- ts->Msgs_Tot = ts->Size_Tot = 0;
- if (G->TR->GUI.GR_LIST)
- {
- set(G->TR->GUI.GR_PAGE, MUIA_Group_ActivePage, 1);
- DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Off, NULL);
- }
- for (mail = G->TR->List; mail; mail = mail->Next)
- {
- ts->Msgs_Tot++;
- if (mail->Status & 1) ts->Size_Tot += mail->Size;
- }
- }
- ///
- /// TR_TransStat_Start
- // Resets statistics display
- void TR_TransStat_Start(struct TransStat *ts)
- {
- ts->Msgs_Done = ts->Size_Done = 0;
- sprintf(G->TR->CountLabel, GetStr(MSG_TR_MessageGauge), "%ld", ts->Msgs_Tot);
- set(G->TR->GUI.GA_COUNT, MUIA_Gauge_InfoText, G->TR->CountLabel);
- set(G->TR->GUI.GA_COUNT, MUIA_Gauge_Max, ts->Msgs_Tot);
- ts->Clock_Start = TR_GetSeconds();
- }
- ///
- /// TR_TransStat_NextMsg
- // Updates statistics display for next message
- void TR_TransStat_NextMsg(struct TransStat *ts, int index, int listpos, int size, char *status)
- {
- ts->Size_Curr = 0;
- ts->Clock_Last = 0;
- ts->Delay = 0;
- if (!GetMUI(G->TR->GUI.WI, MUIA_Window_Open)) return;
- else if (size < 2500) ts->Delay = 256;
- else if (size < 25000) ts->Delay = 512;
- else if (size < 250000) ts->Delay = 1024;
- else if (size < 2500000) ts->Delay = 2048;
- else ts->Delay = 4096;
- if (G->TR->GUI.GR_LIST && listpos >= 0) set(G->TR->GUI.LV_MAILS, MUIA_NList_Active, listpos);
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, status);
- set(G->TR->GUI.GA_COUNT, MUIA_Gauge_Current, index);
- sprintf(G->TR->BytesLabel, GetStr(MSG_TR_SizeGauge), size);
- set(G->TR->GUI.GA_BYTES, MUIA_Gauge_InfoText, G->TR->BytesLabel);
- set(G->TR->GUI.GA_BYTES, MUIA_Gauge_Max, size);
- }
- ///
- /// TR_TransStat_Update
- // Updates statistics display for next block of data
- void TR_TransStat_Update(struct TransStat *ts, int size_incr)
- {
- long clock;
- int speed = 0, remclock = 0;
- static long size_done = 0;
-
- if (!ts->Size_Done) size_done = 0;
- ts->Size_Curr += size_incr;
- ts->Size_Done += size_incr;
- if (!ts->Delay) return;
- if (ts->Size_Done-size_done > ts->Delay)
- {
- set(G->TR->GUI.GA_BYTES, MUIA_Gauge_Current, ts->Size_Curr);
- DoMethod(G->App, MUIM_Application_InputBuffered);
- size_done = ts->Size_Done;
- }
- if ((clock = (TR_GetSeconds()-ts->Clock_Start)) == ts->Clock_Last) return;
- ts->Clock_Last = clock;
- if (clock) speed = ts->Size_Done/clock;
- if (speed) remclock = MAX(ts->Size_Tot/speed-clock,0);
- sprintf(G->TR->StatsLabel, GetStr(MSG_TR_TransferStats),
- ts->Size_Done>>10, ts->Size_Tot>>10, speed, remclock/60, remclock%60);
- set(G->TR->GUI.TX_STATS, MUIA_Text_Contents, G->TR->StatsLabel);
- }
- ///
- /// TR_Cleanup
- // Free temporary message and UIDL lists
- void TR_Cleanup(void)
- {
- struct Mail *work, *next;
-
- if (G->TR->GUI.LV_MAILS) DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_Clear);
- for (work = G->TR->List; work; work = next)
- {
- next = work->Next;
- if (work->UIDL) free(work->UIDL);
- free(work);
- }
- if (G->TR->UIDLloc) free(G->TR->UIDLloc);
- G->TR->UIDLloc = NULL;
- G->TR->List = NULL;
- }
- ///
- /// TR_AbortnClose
- // Aborts a transfer
- void TR_AbortnClose(void)
- {
- set(G->TR->GUI.WI, MUIA_Window_Open, FALSE);
- TR_Cleanup();
- MA_ChangeTransfer(TRUE);
- DisposeModulePush(&G->TR);
- }
- ///
- /// TR_ApplySentFilters
- // Applies filters to a sent message
- BOOL TR_ApplySentFilters(struct Mail *mail)
- {
- int i;
- for (i = 0; i < G->TR->Scnt; i++)
- if (FI_DoComplexSearch(G->TR->Search[i], G->TR->Search[i]->Rule->Combine, G->TR->Search[i+MAXRU], mail))
- if (!MA_ExecuteRuleAction(G->TR->Search[i]->Rule, mail)) return FALSE;
- return TRUE;
- }
- ///
-
- /*** EXPORT ***/
- /// TR_ProcessEXPORT
- // Saves a list of messages to a UUCP mailbox file
- BOOL TR_ProcessEXPORT(char *fname, struct Mail **mlist, BOOL append)
- {
- BOOL success = FALSE;
- struct TransStat ts;
- int i, c;
- char buf[SIZE_LINE], fullfile[SIZE_PATHFILE];
- FILE *fh, *mfh;
- struct Mail *mail, *new;
-
- G->TR->List = NULL;
- for (c = i = 0; i < (int)*mlist; i++)
- {
- if (new = calloc(1,sizeof(struct Mail)))
- {
- *new = *mlist[i+2];
- new->Index = ++c; new->Status = 1;
- MyAddTail(&(G->TR->List), new);
- }
- }
- if (c)
- {
- TR_SetWinTitle(FALSE, FilePart(fname));
- TR_TransStat_Init(&ts);
- TR_TransStat_Start(&ts);
- if (fh = fopen(fname, append ? "a" : "w"))
- {
- success = TRUE;
- for (mail = G->TR->List; mail && !G->TR->Abort; mail = mail->Next)
- {
- ts.Msgs_Done++;
- TR_TransStat_NextMsg(&ts, mail->Index, -1, mail->Size, GetStr(MSG_TR_Exporting));
- if (StartUnpack(GetMailFile(NULL, NULL, mail), fullfile, mail->Folder))
- {
- if (mfh = fopen(fullfile, "r"))
- {
- fprintf(fh, "From %s %s", mail->From.Address, DateStamp2String(&mail->Date, DSS_UNIXDATE));
- while (fgets(buf, SIZE_LINE, mfh) && !G->TR->Abort)
- {
- if (!strncmp(buf, "From ", 5)) fputc('>', fh);
- fputs(buf, fh);
- TR_TransStat_Update(&ts, strlen(buf));
- }
- if (*buf) if (buf[strlen(buf)-1] != '\n') fputc('\n', fh);
- fclose(mfh);
- }
- FinishUnpack(fullfile);
- }
- }
- }
- fclose(fh);
- AppendLog(51, GetStr(MSG_LOG_Exporting), (void *)ts.Msgs_Done, G->TR->List->Folder->Name, fname, "");
- }
- TR_AbortnClose();
- return success;
- }
- ///
-
- /*** SEND ***/
- /// TR_SendMessage
- // Sends a single message
- int TR_SendMessage(struct TransStat *ts, struct Mail *mail)
- {
- int result = 0;
- struct Folder *outfolder = FO_GetFolderByType(FT_OUTGOING, NULL);
- char *mf;
- FILE *f;
-
- if (f = fopen(mf = GetMailFile(NULL, outfolder, mail), "r"))
- {
- char buf[SIZE_LINE];
- sprintf(buf, "FROM:<%s>", C->EmailAddress);
- if (TR_SendSMTPCmd("MAIL", buf))
- {
- int j;
- BOOL rcptok = TRUE;
- struct ExtendedMail *email = MA_ExamineMail(outfolder, mail->MailFile, NULL, TRUE);
- sprintf(buf, "TO:<%s>", mail->To.Address);
- if (!TR_SendSMTPCmd("RCPT", buf)) rcptok = FALSE;
- for (j = 0; j < email->NoSTo && rcptok; j++)
- {
- sprintf(buf, "TO:<%s>", email->STo[j].Address);
- if (!TR_SendSMTPCmd("RCPT", buf)) rcptok = FALSE;
- }
- for (j = 0; j < email->NoCC && rcptok; j++)
- {
- sprintf(buf, "TO:<%s>", email->CC[j].Address);
- if (!TR_SendSMTPCmd("RCPT", buf)) rcptok = FALSE;
- }
- for (j = 0; j < email->NoBCC && rcptok; j++)
- {
- sprintf(buf, "TO:<%s>", email->BCC[j].Address);
- if (!TR_SendSMTPCmd("RCPT", buf)) rcptok = FALSE;
- }
- if (rcptok)
- {
- if (TR_SendSMTPCmd("DATA", NULL))
- {
- BOOL infield = FALSE, inbody = FALSE;
- while (fgets(buf, SIZE_LINE-1, f) && !G->TR->Abort && !G->Error)
- {
- char *p, sendbuf[SIZE_LINE+2];
- int sb = strlen(buf);
- if (p = strpbrk(buf, "\r\n")) *p = 0;
- if (!*buf && !inbody)
- {
- inbody = TRUE; infield = FALSE;
- }
- if (!ISpace(*buf) && !inbody) infield = !strnicmp(buf, "bcc", 3) || !strnicmp(buf, "x-yam-", 6);
- if (!infield)
- {
- *sendbuf = 0;
- if (*buf == '.') strcat(sendbuf, "."); /* RFC 821 */
- strcat(sendbuf, buf);
- strcat(sendbuf, "\r\n");
- if (!TR_SendDat(sendbuf)) ER_NewError(GetStr(MSG_ER_ConnectionBroken), NULL, NULL);
- }
- TR_TransStat_Update(ts, sb);
- }
- if (_OSERR) ER_NewError(GetStr(MSG_ER_ErrorReadMailfile), mf, NULL);
- else if (!G->TR->Abort && !G->Error)
- {
- result = email->DelSend ? 2 : 1;
- AppendLogVerbose(41, GetStr(MSG_LOG_SendingVerbose), AddrName(mail->To), mail->Subject, (void *)mail->Size, "");
- }
- TR_SendSMTPCmd("\r\n.", NULL);
- }
- }
- else ER_NewError(GetStr(MSG_ER_InvalidAddress), buf, NULL);
- MA_FreeEMailStruct(email);
- }
- fclose(f);
- }
- else ER_NewError(GetStr(MSG_ER_CantOpenFile), mf, NULL);
- return result;
- }
- ///
- /// TR_ProcessSEND
- // Sends a list of messages
- BOOL TR_ProcessSEND(struct Mail **mlist)
- {
- struct TransStat ts;
- int c, i, port = 25, err;
- struct Mail *mail, *new;
- struct Folder *outfolder = FO_GetFolderByType(FT_OUTGOING, NULL);
- struct Folder *sentfolder = FO_GetFolderByType(FT_SENT, NULL);
- BOOL success = FALSE;
- char *p;
-
- G->TR->List = NULL;
- G->TR_Allow = G->TR->Abort = G->Error = FALSE;
- for (c = i = 0; i < (int)*mlist; i++)
- {
- mail = mlist[i+2];
- if (mail->Status == STATUS_WFS || mail->Status == STATUS_ERR) if (new = malloc(sizeof(struct Mail)))
- {
- *new = *mail;
- new->Index = ++c;
- new->Status = 1;
- new->Reference = mail;
- new->Next = NULL;
- MyAddTail(&(G->TR->List), new);
- }
- }
- if (c)
- {
- char host[SIZE_HOST];
- G->TR->Scnt = MA_AllocRules(G->TR->Search, APPLY_SENT);
- TR_TransStat_Init(&ts);
- TR_TransStat_Start(&ts);
- strcpy(host, C->SMTP_Server);
- if (p = strchr(host, ':')) { *p = 0; port = atoi(++p); }
- TR_SetWinTitle(FALSE, host);
- if (!(err = TR_Connect(host, port)))
- {
- if (TR_ConnectSMTP())
- {
- success = TRUE;
- AppendLogVerbose(41, GetStr(MSG_LOG_ConnectSMTP), host, "", "", "");
- for (mail = G->TR->List; mail; mail = mail->Next)
- {
- if (G->TR->Abort || G->Error) break;
- ts.Msgs_Done++;
- TR_TransStat_NextMsg(&ts, mail->Index, -1, mail->Size, GetStr(MSG_TR_Sending));
- switch (TR_SendMessage(&ts, mail))
- {
- case 0: MA_SetMailStatus(mail->Reference, STATUS_ERR);
- TR_SendSMTPCmd("RSET", NULL);
- break;
- case 1: MA_SetMailStatus(mail->Reference, STATUS_SNT);
- if (TR_ApplySentFilters(mail->Reference)) MA_MoveCopy(mail->Reference, outfolder, sentfolder, FALSE);
- break;
- case 2: MA_SetMailStatus(mail->Reference, STATUS_SNT);
- if (TR_ApplySentFilters(mail->Reference)) MA_DeleteSingle(mail->Reference, FALSE);
- }
- }
- TR_DisconnectSMTP();
- AppendLogNormal(40, GetStr(MSG_LOG_Sending), (void *)c, host, "", "");
- }
- }
- else switch (err)
- {
- case -1: ER_NewError(GetStr(MSG_ER_UnknownSMTP), C->SMTP_Server, NULL); break;
- default: ER_NewError(GetStr(MSG_ER_CantConnect), C->SMTP_Server, NULL);
- }
- MA_FreeRules(G->TR->Search, G->TR->Scnt);
- }
- TR_AbortnClose();
- return success;
- }
- ///
-
- /*** IMPORT ***/
- /// TR_AbortIMPORTFunc
- // Aborts import process
- SAVEDS void TR_AbortIMPORTFunc(void)
- {
- TR_AbortnClose();
- }
- MakeHook(TR_AbortIMPORTHook, TR_AbortIMPORTFunc);
- ///
- /// TR_ProcessIMPORTFunc
- // Imports messages from a UUCP mailbox file
- SAVEDS void TR_ProcessIMPORTFunc(void)
- {
- struct TransStat ts;
- FILE *fh, *f = NULL;
-
- TR_TransStat_Init(&ts);
- if (ts.Msgs_Tot)
- {
- TR_TransStat_Start(&ts);
- if (fh = fopen(G->TR->ImportFile, "r"))
- {
- struct ExtendedMail *email;
- struct Mail *mail = G->TR->List;
- static char mfile[SIZE_MFILE];
- BOOL header = FALSE, body = FALSE;
- struct Folder *folder = G->TR->ImportBox;
- int btype = folder->Type;
- char buffer[SIZE_LINE], *stat;
-
- if (btype == FT_OUTGOING) stat = Status[STATUS_WFS];
- else if (btype == FT_SENT || btype == FT_CUSTOMSENT) stat = Status[STATUS_SNT];
- else stat = " ";
- while (fgets(buffer, SIZE_LINE, fh) && !G->TR->Abort)
- {
- if (!header && !strncmp(buffer, "From ", 5))
- {
- if (body)
- {
- if (f)
- {
- fclose(f); f = NULL;
- if (email = MA_ExamineMail(folder, mfile, stat, FALSE))
- {
- AddMailToList((struct Mail *)email, folder);
- MA_FreeEMailStruct(email);
- }
- }
- mail = mail->Next;
- }
- header = TRUE; body = FALSE;
- if (mail->Status & 1)
- {
- ts.Msgs_Done++;
- TR_TransStat_NextMsg(&ts, mail->Index, mail->Position, mail->Size, GetStr(MSG_TR_Importing));
- f = fopen(MA_NewMailFile(folder, mfile, 0), "w");
- }
- }
- else if (f && (header || body))
- {
- fputs(buffer, f);
- TR_TransStat_Update(&ts, strlen(buffer));
- }
- if (header && !buffer[1]) { body = TRUE; header = FALSE; }
- }
- if (body && f)
- {
- fclose(f);
- if (email = MA_ExamineMail(folder, mfile, stat, FALSE))
- {
- AddMailToList((struct Mail *)email, folder);
- MA_FreeEMailStruct(email);
- }
- }
- fclose(fh);
- DisplayMailList(folder, G->MA->GUI.NL_MAILS);
- AppendLog(50, GetStr(MSG_LOG_Importing), (void *)ts.Msgs_Done, G->TR->ImportFile, folder->Name, "");
- DisplayStatistics(folder);
- }
- }
- TR_AbortnClose();
- }
- MakeHook(TR_ProcessIMPORTHook, TR_ProcessIMPORTFunc);
- ///
-
- /*** GET ***/
- /// TR_AbortGETFunc
- // Aborts a POP3 download
- SAVEDS void TR_AbortGETFunc(void)
- {
- MA_FreeRules(G->TR->Search, G->TR->Scnt);
- TR_AbortnClose();
- TR_CloseTCPIP();
- G->TR->Checking = FALSE; DisplayStatistics((struct Folder *)-1);
- }
- MakeHook(TR_AbortGETHook, TR_AbortGETFunc);
- ///
- /// TR_LoadMessage
- // Retrieves a message from the POP3 server
- BOOL TR_LoadMessage(struct TransStat *ts, int number)
- {
- static char mfile[SIZE_MFILE];
- struct Folder *infolder = FO_GetFolderByType(FT_INCOMING, NULL);
- char msgnum[SIZE_SMALL], buf[SIZE_LINE], msgfile[SIZE_PATHFILE];
- FILE *f;
-
- stccpy(msgfile, MA_NewMailFile(infolder, mfile, 0), SIZE_PATHFILE);
- if (f = fopen(msgfile, "w"))
- {
- sprintf(msgnum, "%ld", number);
- if (TR_SendPopCmd(buf, "RETR", msgnum, 0))
- {
- int l = 0;
- char line[SIZE_LINE], *bufptr;
- BOOL done = FALSE;
-
- if (bufptr = strstr(buf, "\r\n")) bufptr += 2;
- while (!G->Error && !G->TR->Abort)
- {
- for (; *bufptr; bufptr++)
- {
- if (*bufptr != '\r') line[l++] = *bufptr;
- if (l == SIZE_LINE-1)
- {
- TR_TransStat_Update(ts, l);
- line[l] = 0; l = 0;
- if (fputs(line, f) == EOF) { ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), mfile, NULL); break; }
- }
- if (*bufptr != '\n') continue;
- TR_TransStat_Update(ts, l+1);
- line[l] = 0; l = 0;
- if (line[0] == '.')
- if (line[1] == '\n') { done = TRUE; break; }
- else l = 1; /* RFC 1725 */
- if (fputs(&line[l], f) == EOF) { ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), mfile, NULL); break; }
- l = 0;
- }
- if (done) break;
- if (TR_RecvDat(buf) <= 0) break;
- bufptr = buf;
- }
- }
- else ER_NewError(GetStr(MSG_ER_ErrorWriteMailfile), (char *)"", NULL);
- fclose(f);
- if (!G->TR->Abort && !G->Error)
- {
- struct ExtendedMail *mail;
- if (mail = MA_ExamineMail(infolder, mfile, " ", FALSE))
- {
- struct Mail *new = AddMailToList((struct Mail *)mail, infolder);
- if (FO_GetCurrentFolder() == infolder) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_InsertSingle, new, MUIV_NList_Insert_Sorted);
- AppendLogVerbose(32, GetStr(MSG_LOG_RetrievingVerbose), AddrName(new->From), new->Subject, (void *)new->Size, "");
- MA_StartMacro(MACRO_NEWMSG, mfile);
- MA_FreeEMailStruct(mail);
- }
- return TRUE;
- }
- DeleteFile(msgfile);
- }
- return FALSE;
- }
- ///
- /// TR_DeleteMessage
- // Deletes a message on the POP3 server
- void TR_DeleteMessage(int number)
- {
- char msgnum[SIZE_SMALL], buf[SIZE_LINE];
-
- sprintf(msgnum, "%ld", number);
- set(G->TR->GUI.TX_STATUS, MUIA_Text_Contents, GetStr(MSG_TR_DeletingServerMail));
- if (TR_SendPopCmd(buf, "DELE", msgnum, POPCMD_WAITEOL)) G->TR->Stats.Deleted++;
- }
- ///
- /// TR_NewMailAlert
- // Notifies user when new mail is available
- void TR_NewMailAlert(void)
- {
- struct DownloadResult *stats = &G->TR->Stats;
-
- memcpy(&G->LastDL, stats, sizeof(struct DownloadResult));
- if (!stats->Downloaded) return;
- if ((C->NotifyType & NOTI_REQ) && G->TR->GUIlevel != POP_REXX)
- {
- int iconified;
- static char buffer[SIZE_LARGE];
- struct RuleResult *rr = &G->RRs;
- get(G->App, MUIA_Application_Iconified, &iconified);
- if (iconified) { PopUp(); Delay(50L); }
- sprintf(buffer, GetStr(MSG_TR_NewMailReq),
- stats->Downloaded, stats->OnServer-stats->Deleted, stats->DupSkipped);
- sprintf(&buffer[strlen(buffer)], GetStr(MSG_TR_FilterStats),
- rr->Checked, rr->Bounced, rr->Forwarded, rr->Replied, rr->Executed, rr->Moved, rr->Deleted);
- InfoWindow(GetStr(MSG_TR_NewMail), buffer, GetStr(MSG_Okay), G->MA->GUI.WI);
- }
- if (C->NotifyType & NOTI_CMD) ExecuteCommand(C->NotifyCommand, FALSE, NULL);
- if (C->NotifyType & NOTI_SOUND) PlaySound(C->NotifySound);
- }
- ///
- /// TR_ProcessGETFunc
- // Downloads messages from a POP3 server
- SAVEDS void TR_ProcessGETFunc(void)
- {
- struct TransStat ts;
- struct Mail *mail;
-
- TR_TransStat_Init(&ts);
- if (ts.Msgs_Tot)
- {
- if (C->TransferWindow == 2) set(G->TR->GUI.WI, MUIA_Window_Open, TRUE);
- TR_TransStat_Start(&ts);
- for (mail = G->TR->List; mail && !G->TR->Abort && !G->Error; mail = mail->Next)
- {
- TR_TransStat_NextMsg(&ts, mail->Index, mail->Position, mail->Size, GetStr(MSG_TR_Downloading));
- if (mail->Status & 1)
- {
- if (TR_LoadMessage(&ts, mail->Index))
- {
- G->TR->Stats.Downloaded++;
- if (C->AvoidDuplicates) TR_AppendUIDL(mail->UIDL);
- if (mail->Status & 2) TR_DeleteMessage(mail->Index);
- }
- }
- else if (mail->Status & 2)
- {
- TR_DeleteMessage(mail->Index);
- }
- }
- DisplayStatistics(FO_GetFolderByType(FT_INCOMING, NULL));
- }
- TR_GetMailFromNextPOP(FALSE, 0, 0);
- }
- MakeHook(TR_ProcessGETHook, TR_ProcessGETFunc);
- ///
- /// TR_GetMessageInfoFunc
- // Requests message header of a message selected by the user
- SAVEDS void TR_GetMessageInfoFunc(void)
- {
- int line;
- struct Mail *mail;
- get(G->TR->GUI.LV_MAILS, MUIA_NList_Active, &line);
- DoMethod(G->TR->GUI.LV_MAILS, MUIM_NList_GetEntry, line, &mail);
- TR_GetMessageDetails(mail, line);
- }
- MakeHook(TR_GetMessageInfoHook, TR_GetMessageInfoFunc);
- ///
- /// TR_CompleteMsgList
- // Gets details for messages on server
- void TR_CompleteMsgList()
- {
- struct TR_ClassData *tr = G->TR;
- struct Mail *mail = tr->GMD_Mail;
-
- if (C->PreSelection < 3) while (mail && !tr->Abort)
- {
- if (tr->Pause) return;
- if (tr->Start) { TR_ProcessGETFunc(); return; }
- if (C->PreSelection != 1 || mail->Size >= C->WarnSize*1024) TR_GetMessageDetails(mail, tr->GMD_Line++);
- mail = mail->Next;
- }
- set(G->TR->GUI.BT_PAUSE, MUIA_Disabled, TRUE);
- DoMethod(tr->GUI.BT_START, MUIM_KillNotify, MUIA_Pressed);
- DoMethod(tr->GUI.BT_START, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &TR_ProcessGETHook);
- DoMethod(tr->GUI.BT_QUIT , MUIM_KillNotify, MUIA_Pressed);
- DoMethod(tr->GUI.BT_QUIT , MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &TR_AbortGETHook);
- if (tr->Abort) TR_AbortGETFunc();
- }
- ///
- /// TR_PauseFunc
- // Pauses or resumes message download
- SAVEDS ASM void TR_PauseFunc(REG(a1) int *arg)
- {
- BOOL pause = *arg;
-
- set(G->TR->GUI.BT_RESUME, MUIA_Disabled, !pause);
- set(G->TR->GUI.BT_PAUSE, MUIA_Disabled, pause);
- if (pause) return;
- G->TR->Pause = FALSE;
- TR_CompleteMsgList();
- }
- MakeHook(TR_PauseHook, TR_PauseFunc);
- ///
-
- /*** GUI ***/
- /// TR_LV_DspFunc
- // Message listview display hook
- SAVEDS ASM long TR_LV_DspFunc(REG(a0) struct Hook *hook, REG(a2) char **array, REG(a1) struct Mail *entry)
- {
- if (entry)
- {
- static char dispfro[SIZE_DEFAULT], dispsta[SIZE_DEFAULT], dispsiz[SIZE_SMALL], dispdate[32];
- struct Person *pe = &entry->From;
- sprintf(array[0] = dispsta, "%3ld ", entry->Index);
- if (entry->Status & 1) strcat(dispsta, "\033o[10]");
- if (entry->Status & 2) strcat(dispsta, "\033o[9]");
- if (entry->Size >= C->WarnSize<<10) strcat(dispsiz, MUIX_PH);
- array[1] = dispsiz; *dispsiz = 0;
- FormatSize(entry->Size, dispsiz);
- stccpy(array[2] = dispfro, AddrName((*pe)), SIZE_DEFAULT);
- array[3] = entry->Subject;
- array[4] = dispdate; *dispdate = 0;
- if (entry->Date.ds_Days) stccpy(dispdate, DateStamp2String(&entry->Date, C->SwatchBeat ? DSS_DATEBEAT : DSS_DATETIME), 32);
- }
- else
- {
- array[0] = GetStr(MSG_MA_TitleStatus);
- array[1] = GetStr(MSG_Size);
- array[2] = GetStr(MSG_From);
- array[3] = GetStr(MSG_Subject);
- array[4] = GetStr(MSG_Date);
-
- }
- return 0;
- }
- MakeHook(TR_LV_DspFuncHook,TR_LV_DspFunc);
- ///
- /// TR_New
- // Creates transfer window
- struct TR_ClassData *TR_New(int TRmode)
- {
- struct TR_ClassData *data;
-
- if (data = calloc(1,sizeof(struct TR_ClassData)))
- {
- APTR bt_all = NULL, bt_none = NULL, bt_loadonly = NULL, bt_loaddel = NULL, bt_delonly = NULL, bt_leave = NULL;
- APTR gr_sel, gr_proc, gr_win;
- BOOL fullwin = (TRmode == TR_GET || TRmode == TR_IMPORT);
-
-
- gr_proc = ColGroup(2), GroupFrameT(GetStr(MSG_TR_Status)),
- Child, data->GUI.TX_STATS = TextObject,
- MUIA_Text_Contents, GetStr(MSG_TR_TransferStats0),
- MUIA_Background,MUII_TextBack,
- MUIA_Frame ,MUIV_Frame_Text,
- MUIA_Text_PreParse, MUIX_C,
- End,
- Child, VGroup,
- Child, data->GUI.GA_COUNT = GaugeObject,
- GaugeFrame,
- MUIA_Gauge_Horiz ,TRUE,
- MUIA_Gauge_InfoText,GetStr(MSG_TR_MessageGauge0),
- End,
- Child, data->GUI.GA_BYTES = GaugeObject,
- GaugeFrame,
- MUIA_Gauge_Horiz ,TRUE,
- MUIA_Gauge_InfoText,GetStr(MSG_TR_BytesGauge0),
- End,
- End,
- Child, data->GUI.TX_STATUS = TextObject,
- MUIA_Background,MUII_TextBack,
- MUIA_Frame ,MUIV_Frame_Text,
- End,
- Child, data->GUI.BT_ABORT = MakeButton(GetStr(MSG_TR_Abort)),
- End;
- if (fullwin)
- {
- data->GUI.GR_LIST = VGroup, GroupFrameT(TRmode==TR_IMPORT ? GetStr(MSG_TR_MsgInFile) : GetStr(MSG_TR_MsgOnServer)),
- MUIA_ShowMe, TRmode==TR_IMPORT || C->PreSelection>=2,
- Child, NListviewObject,
- MUIA_CycleChain,1,
- MUIA_NListview_NList, data->GUI.LV_MAILS = NListObject,
- MUIA_NList_MultiSelect, MUIV_NList_MultiSelect_Default,
- MUIA_NList_Format , "W=-1 BAR,W=-1 MACW=9 P=\33r BAR,MICW=20 BAR,MICW=16 BAR,MICW=9 MACW=15",
- MUIA_NList_DisplayHook , &TR_LV_DspFuncHook,
- MUIA_NList_AutoVisible , TRUE,
- MUIA_NList_Title , TRUE,
- MUIA_NList_TitleSeparator, TRUE,
- MUIA_NList_DoubleClick , TRUE,
- MUIA_NList_MinColSortable, 0,
- MUIA_Font, C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
- MUIA_ContextMenu , NULL,
- MUIA_NList_Exports, MUIV_NList_Exports_Cols,
- MUIA_NList_Imports, MUIV_NList_Imports_Cols,
- MUIA_ObjectID, MAKE_ID('N','L','0','4'),
- End,
- End,
- End;
- gr_sel = VGroup, GroupFrameT(GetStr(MSG_TR_Control)),
- Child, ColGroup(5),
- Child, bt_all = MakeButton(GetStr(MSG_TR_All)),
- Child, bt_loaddel = MakeButton(GetStr(MSG_TR_DownloadDelete)),
- Child, bt_leave = MakeButton(GetStr(MSG_TR_Leave)),
- Child, HSpace(0),
- Child, data->GUI.BT_PAUSE = MakeButton(GetStr(MSG_TR_Pause)),
- Child, bt_none = MakeButton(GetStr(MSG_TR_Clear)),
- Child, bt_loadonly = MakeButton(GetStr(MSG_TR_DownloadOnly)),
- Child, bt_delonly = MakeButton(GetStr(MSG_TR_DeleteOnly)),
- Child, HSpace(0),
- Child, data->GUI.BT_RESUME = MakeButton(GetStr(MSG_TR_Resume)),
- End,
- Child, ColGroup(2),
- Child, data->GUI.BT_START = MakeButton(GetStr(MSG_TR_Start)),
- Child, data->GUI.BT_QUIT = MakeButton(GetStr(MSG_TR_Abort)),
- End,
- End;
- gr_win = VGroup,
- Child, data->GUI.GR_LIST,
- Child, data->GUI.GR_PAGE = PageGroup,
- Child, gr_sel,
- Child, gr_proc,
- End,
- End;
- }
- else gr_win = gr_proc;
- data->GUI.WI = WindowObject,
- MUIA_Window_ID, MAKE_ID('T','R','A','0'+TRmode-TR_IMPORT),
- MUIA_Window_CloseGadget, FALSE,
- MUIA_Window_Activate, (TRmode == TR_IMPORT || TRmode == TR_EXPORT),
- MUIA_HelpNode, "TR_W",
- WindowContents, gr_win,
- End;
- if (data->GUI.WI)
- {
- DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
- SetHelp(data->GUI.TX_STATUS,MSG_HELP_TR_TX_STATUS);
- SetHelp(data->GUI.BT_ABORT ,MSG_HELP_TR_BT_ABORT);
- if (fullwin)
- {
- set(data->GUI.BT_RESUME, MUIA_Disabled, TRUE);
- if (TRmode == TR_IMPORT)
- {
- set(data->GUI.BT_PAUSE, MUIA_Disabled, TRUE);
- set(bt_delonly , MUIA_Disabled, TRUE);
- set(bt_loaddel , MUIA_Disabled, TRUE);
- DoMethod(data->GUI.BT_START, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &TR_ProcessIMPORTHook);
- DoMethod(data->GUI.BT_QUIT , MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 2, MUIM_CallHook, &TR_AbortIMPORTHook);
- }
- else
- {
- set(data->GUI.GR_PAGE, MUIA_Group_ActivePage, 1);
- DoMethod(data->GUI.BT_RESUME,MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_PauseHook,0);
- DoMethod(data->GUI.BT_PAUSE ,MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_PauseHook,1);
- DoMethod(data->GUI.BT_PAUSE, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_WriteLong, TRUE, &(data->Pause));
- DoMethod(data->GUI.LV_MAILS ,MUIM_Notify, MUIA_NList_DoubleClick,TRUE, MUIV_Notify_Application, 2, MUIM_CallHook, &TR_GetMessageInfoHook);
- DoMethod(bt_delonly, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_ChangeStatusHook,2);
- DoMethod(bt_loaddel, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_ChangeStatusHook,3);
- DoMethod(data->GUI.BT_START, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_WriteLong, TRUE, &(data->Start));
- DoMethod(data->GUI.BT_QUIT , MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_WriteLong, TRUE, &(data->Abort));
- }
- DoMethod(bt_loadonly, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_ChangeStatusHook,1);
- DoMethod(bt_leave, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_CallHook, &TR_ChangeStatusHook,0);
- DoMethod(bt_all, MUIM_Notify, MUIA_Pressed, FALSE, data->GUI.LV_MAILS, 4, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_On, NULL);
- DoMethod(bt_none, MUIM_Notify, MUIA_Pressed, FALSE, data->GUI.LV_MAILS, 4, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Off, NULL);
- DoMethod(data->GUI.LV_MAILS, MUIM_NList_UseImage, G->MA->GUI.BC_STAT[9], 9, 0);
- DoMethod(data->GUI.LV_MAILS, MUIM_NList_UseImage, G->MA->GUI.BC_STAT[10], 10, 0);
- }
- DoMethod(data->GUI.BT_ABORT, MUIM_Notify, MUIA_Pressed, FALSE, MUIV_Notify_Application, 3, MUIM_WriteLong, TRUE, &(data->Abort));
- MA_ChangeTransfer(FALSE);
- return data;
- }
- free(data);
- }
- return NULL;
- }
- ///
-