void retr_msg(int msgnum) { char *p, *q, temp[PATH_MAX], *base; int Header; unsigned int crc = -1; snprintf(temp, 81, "RETR %d\r\n", msgnum); if (pop3_cmd(temp) == 0) { Msg_New(); Header = TRUE; snprintf(temp, PATH_MAX, "%s/%s/mailbox", CFG.bbs_usersdir, exitinfo.Name); base = xstrcpy(temp); Open_Msgbase(base, 'w'); Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Private = TRUE; while (TRUE) { p = pop3_receive(); if ((p[0] == '.') && (strlen(p) == 1)) { break; } else { if (Header) { /* * Check the primary message header lines. */ if (strncmp(p, "To: ", 4) == 0) { if (strlen(p) > 104) p[104] = '\0'; snprintf(Msg.To, 101, "%s", p+4); } if (strncmp(p, "From: ", 6) == 0) { if (strlen(p) > 106) p[106] = '\0'; snprintf(Msg.From, 101, "%s", p+6); } if (strncmp(p, "Subject: ", 9) == 0) { if (strlen(p) > 109) p[109] = '\0'; snprintf(Msg.Subject, 101, "%s", p+9); mbse_CleanSubject(Msg.Subject); } if (strncmp(p, "Date: ", 6) == 0) Msg.Written = parsedate(p+6, NULL) - (gmt_offset((time_t)0) * 60); if (strncmp(p, "Message-Id: ", 12) == 0) { q = xstrcpy(p+12); Msg.MsgIdCRC = upd_crc32(q, crc, strlen(q)); free(q); } Msg.ReplyCRC = 0xffffffff; if (strlen(p) == 0) { Header = FALSE; } else { snprintf(temp, PATH_MAX, "\001%s", p); MsgText_Add2(temp); } } else { MsgText_Add2(p); } } } Msg_AddMsg(); Msg_UnLock(); Close_Msgbase(base); free(base); snprintf(temp, 81, "DELE %d\r\n", msgnum); pop3_cmd(temp); } else { WriteError("POP3: Can't retrieve message %d", msgnum); } }
/* * Kill messages according to age and max messages. */ void KillArea(char *Path, char *Name, int DaysOld, int MaxMsgs, int Areanr) { unsigned int Number, TotalMsgs = 0, *Active, Counter = 0; int i, DelCount = 0, DelAge = 0, Done; time_t Today, MsgDate; IsDoing("Killing %ld", Areanr); Today = time(NULL) / 86400L; if (Msg_Open(Path)) { if (!do_quiet) { mbse_colour(LIGHTRED, BLACK); printf(" (Killing)"); mbse_colour(LIGHTMAGENTA, BLACK); fflush(stdout); } if (Msg_Lock(30L)) { TotalMsgs = Msg_Number(); if (TotalMsgs) { if ((Active = (unsigned int *)malloc((size_t)((TotalMsgs + 100L) * sizeof(unsigned int)))) != NULL) { i = 0; Number = Msg_Lowest(); do { Active[i++] = Number; } while (Msg_Next(&Number) == TRUE); } } else Active = NULL; Number = Msg_Lowest(); do { if (CFG.slow_util && do_quiet) msleep(1); if ((!do_quiet) && ((Counter % 10L) == 0)) { printf("%6u / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", Counter, TotalMsgs); fflush(stdout); } if ((Counter % 10L) == 0) DoNop(); Counter++; msg_tot++; if (Msg_ReadHeader(Number) == TRUE) { Done = FALSE; if (DaysOld) { /* * GoldED doesn't fill the Msg.Arrived field, use the * written date instead. */ if (Msg.Arrived == 0L) MsgDate = Msg.Written / 86400L; else MsgDate = Msg.Arrived / 86400L; if ((Today - MsgDate) > DaysOld) { Msg_Delete(Number); Done = TRUE; DelAge++; msg_del++; if (Active != NULL) { for (i = 0; i < TotalMsgs; i++) { if (Active[i] == Number) Active[i] = 0L; } } } } if (Done == FALSE && (MaxMsgs) && Msg_Number() > MaxMsgs) { Msg_Delete(Number); DelCount++; msg_del++; if (Active != NULL) { for (i = 0; i < TotalMsgs; i++) { if (Active[i] == Number) Active[i] = 0L; } } } } } while (Msg_Next(&Number) == TRUE); if (Active != NULL) free(Active); Msg_UnLock(); } else { Syslog('+', "Can't lock msgbase %s", Path); } if (!do_quiet) { printf(" \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } Msg_Close(); Syslog('-', "%6d %6d %6d %6d %6d %s", TotalMsgs, DaysOld, DelAge, MaxMsgs, DelCount, Name); if (!do_quiet) { printf("\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } } else Syslog('+', "Failed to open %s", Path); }
int Read_a_Email(unsigned int Num) { char *p = NULL, *fn, *charset = NULL, *charsin = NULL; lastread LR; unsigned int mycrc; LastNum = Num; iLineCount = 7; WhosDoingWhat(READ_POST, NULL); /* * The area data is already set, so we can do the next things */ if (EmailBase.Total == 0) { Enter(1); /* There are no messages in this area */ pout(WHITE, BLACK, (char *) Language(205)); Enter(2); sleep(3); return FALSE; } if (!Msg_Open(sMailpath)) { WriteError("Error open JAM base %s", sMailpath); return FALSE; } if (!Msg_ReadHeader(Num)) { Enter(1); pout(WHITE, BLACK, (char *)Language(77)); Enter(2); Msg_Close(); sleep(3); return FALSE; } /* * Fill Quote file in case the user wants to reply. Note that line * wrapping is set lower then normal message read, to create room * for the Quote> strings at the start of each line. */ fn = calloc(PATH_MAX, sizeof(char)); snprintf(fn, PATH_MAX, "%s/%s/.quote", CFG.bbs_usersdir, exitinfo.Name); if ((qf = fopen(fn, "w")) != NULL) { if (Msg_Read(Num, 75)) { if ((p = (char *)MsgText_First()) != NULL) do { if (p[0] == '\001') { /* * Check CHRS kludge */ if (strncmp(p, "\001CHRS: ", 7) == 0) { charset = xstrcpy(p + 7); } /* * While doing this, store the original Message-id in case * a reply will be made. */ if (strncasecmp(p, "\001Message-id: ", 13) == 0) { snprintf(Msg.Msgid, sizeof(Msg.Msgid), "%s", p+13); Syslog('m', "Stored Msgid \"%s\"", Msg.Msgid); } if (Kludges) { p[0] = 'a'; fprintf(qf, "^%s\n", p); } } else fprintf(qf, "%s\n", p); } while ((p = (char *)MsgText_Next()) != NULL); } fclose(qf); } else { WriteError("$Can't open %s", p); } free(fn); if (charset == NULL) { charsin = xstrcpy((char *)"CP437"); } else { charsin = xstrcpy(get_ic_ftn(find_ftn_charset(charset))); } /* * Setup character translation */ chartran_init(charsin, get_ic_ftn(exitinfo.Charset), 'b'); ShowEmailHdr(); /* * Show message text */ colour(CFG.TextColourF, CFG.TextColourB); if (Msg_Read(Num, 79)) { if ((p = (char *)MsgText_First()) != NULL) { do { if (p[0] == '\001') { if (Kludges) { colour(LIGHTGRAY, BLACK); if (p[0] == '\001') p[0] = 'a'; PUTSTR(chartran(p)); Enter(1); if (CheckLine(CFG.TextColourF, CFG.TextColourB, TRUE)) break; } } else { colour(CFG.TextColourF, CFG.TextColourB); if (strchr(p, '>') != NULL) if ((strlen(p) - strlen(strchr(p, '>'))) < 10) colour(CFG.HiliteF, CFG.HiliteB); PUTSTR(chartran(p)); Enter(1); if (CheckLine(CFG.TextColourF, CFG.TextColourB, TRUE)) break; } } while ((p = (char *)MsgText_Next()) != NULL); } } if (charset) free(charset); if (charsin) free(charsin); chartran_close(); /* * Set the Received status on this message. */ if (!Msg.Received) { Syslog('m', "Marking message received"); Msg.Received = TRUE; Msg.Read = time(NULL) - (gmt_offset((time_t)0) * 60); if (Msg_Lock(30L)) { Msg_WriteHeader(Num); Msg_UnLock(); } } /* * Update lastread pointer. */ p = xstrcpy(exitinfo.sUserName); mycrc = StringCRC32(tl(p)); free(p); if (Msg_Lock(30L)) { LR.UserID = grecno; LR.UserCRC = mycrc; if (Msg_GetLastRead(&LR) == TRUE) { LR.LastReadMsg = Num; if (Num > LR.HighReadMsg) LR.HighReadMsg = Num; if (LR.HighReadMsg > EmailBase.Highest) LR.HighReadMsg = EmailBase.Highest; LR.UserCRC = mycrc; if (!Msg_SetLastRead(LR)) WriteError("Error update lastread"); } else { /* * Append new lastread pointer */ LR.UserCRC = mycrc; LR.UserID = grecno; LR.LastReadMsg = Num; LR.HighReadMsg = Num; if (!Msg_NewLastRead(LR)) WriteError("Can't append lastread"); } Msg_UnLock(); } Msg_Close(); return TRUE; }
/* * Save the message to disk. */ int Save_Email(int IsReply) { int i; char *p, *temp; unsigned int crc = -1; int id; FILE *fp; if (Line < 2) return TRUE; if (!Open_Msgbase(sMailpath, 'w')) { return FALSE; } Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Written = Msg.Arrived; Msg.Local = TRUE; Msg.Netmail = TRUE; temp = calloc(PATH_MAX, sizeof(char)); /* * Add header lines */ snprintf(temp, PATH_MAX, "\001Date: %s", rfcdate(Msg.Written)); MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001From: %s", Msg.From); MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001Subject: %s", Msg.Subject); MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001Sender: %s", Msg.From); MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001To: %s", Msg.To); MsgText_Add2(temp); MsgText_Add2((char *)"\001MIME-Version: 1.0"); if (exitinfo.Charset != FTNC_NONE) { snprintf(temp, PATH_MAX, "\001Content-Type: text/plain; charset=%s", getrfcchrs(exitinfo.Charset)); } else { snprintf(temp, PATH_MAX, "\001Content-Type: text/plain; charset=iso8859-1"); } MsgText_Add2(temp); MsgText_Add2((char *)"\001Content-Transfer-Encoding: 8bit"); snprintf(temp, PATH_MAX, "\001X-Mailreader: MBSE BBS %s", VERSION); MsgText_Add2(temp); p = calloc(81, sizeof(char)); id = sequencer(); snprintf(p, 81, "<%08x@%s>", id, CFG.sysdomain); snprintf(temp, PATH_MAX, "\001Message-id: %s", p); MsgText_Add2(temp); Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp)); free(p); if (IsReply) { snprintf(temp, PATH_MAX, "\001In-reply-to: %s", Msg.Replyid); MsgText_Add2(temp); crc = -1; Msg.ReplyCRC = upd_crc32(temp, crc, strlen(temp)); } else Msg.ReplyCRC = 0xffffffff; /* * Add message text */ for (i = 1; i < Line; i++) { MsgText_Add2(Message[i]); } /* * Add signature. */ snprintf(temp, PATH_MAX, "%s/%s/.signature", CFG.bbs_usersdir, exitinfo.Name); if ((fp = fopen(temp, "r"))) { Syslog('m', " Add .signature"); MsgText_Add2((char *)""); while (fgets(temp, 80, fp)) { Striplf(temp); MsgText_Add2(temp); } fclose(fp); MsgText_Add2((char *)""); } MsgText_Add2(TearLine()); /* * Save if to disk */ Msg_AddMsg(); Msg_UnLock(); ReadExitinfo(); exitinfo.iPosted++; mib_posted++; WriteExitinfo(); do_mailout = TRUE; LC_Wrote = TRUE; Syslog('+', "Email (%ld) to \"%s\", \"%s\", in mailbox", Msg.Id, Msg.To, Msg.Subject); Enter(1); /* Saving message to disk */ snprintf(temp, 81, "%s(%d)", (char *) Language(202), Msg.Id); pout(CFG.HiliteF, CFG.HiliteB, temp); Enter(2); sleep(2); /* * Add quick mailscan info */ snprintf(temp, PATH_MAX, "%s/tmp/netmail.jam", getenv("MBSE_ROOT")); if ((fp = fopen(temp, "a")) != NULL) { fprintf(fp, "%s/%s/mailbox %u\n", CFG.bbs_usersdir, exitinfo.Name, Msg.Id); fclose(fp); } free(temp); Close_Msgbase(sMailpath); return TRUE; }
/* * Link messages in one area. * Returns -1 if error, else the number of linked messages. */ int Msg_Link(char *Path, int do_quiet, int slow_util) { int i, m, msg_link = 0; unsigned int Number, Prev, Next, Crc, Total; char Temp[128], *p; MSGLINK *Link; if (! Msg_Open(Path)) { return -1; } if (!do_quiet) { msg_colour(LIGHTRED, BLACK); printf(" (linking)"); msg_colour(LIGHTMAGENTA, BLACK); fflush(stdout); } if ((Total = Msg_Number()) != 0L) { if (Msg_Lock(30L)) { if ((Link = (MSGLINK *)malloc((Total + 1) * sizeof(MSGLINK))) != NULL) { memset(Link, 0, (Total + 1) * sizeof(MSGLINK)); Number = Msg_Lowest(); i = 0; do { Msg_ReadHeader(Number); strcpy(Temp, Msg.Subject); p = strupr(Temp); if (!strncmp(p, "RE:", 3)) { p += 3; if (*p == ' ') p++; } Link[i].Subject = StringCRC32(p); Link[i].Number = Number; i++; if (((i % 10) == 0) && (!do_quiet)) { printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total); fflush(stdout); } } while(Msg_Next(&Number) == TRUE); if (!do_quiet) { printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total); fflush(stdout); } Number = Msg_Lowest(); i = 0; do { Msg_ReadHeader(Number); Prev = Next = 0; Crc = Link[i].Subject; for (m = 0; m < Total; m++) { if (m == i) continue; if (Link[m].Subject == Crc) { if (m < i) Prev = Link[m].Number; else if (m > i) { Next = Link[m].Number; break; } } } if (((i % 10) == 0) && (!do_quiet)) { printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total); fflush(stdout); } if (Msg.Original != Prev || Msg.Reply != Next) { Msg.Original = Prev; Msg.Reply = Next; Msg_WriteHeader(Number); msg_link++; } i++; } while(Msg_Next(&Number) == TRUE); if (!do_quiet) { printf("%6d / %6u\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i, Total); fflush(stdout); } free(Link); } if (!do_quiet) { printf(" \b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } Msg_UnLock(); } else { Syslog('+', "Can't lock %s", Path); return -1; } } Msg_Close(); if (!do_quiet) { printf("\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b"); fflush(stdout); } return msg_link; }
int Post(char *To, int Area, char *Subj, char *File, char *Flavor) { int i, rc = FALSE, has_tear = FALSE, has_origin = FALSE; char *aka, *temp, *sAreas; FILE *fp, *tp; unsigned int crc = -1; time_t tt; struct tm *t; ftnd_CleanSubject(Subj); if (!do_quiet) { ftnd_colour(CYAN, BLACK); printf("Post \"%s\" to \"%s\" in area %d\n", File, To, Area); } IsDoing("Posting"); Syslog('+', "Post \"%s\" area %d to \"%s\" flavor %s", File, Area, To, Flavor); Syslog('+', "Subject: \"%s\"", Subj); if ((tp = fopen(File, "r")) == NULL) { WriteError("$Can't open %s", File); if (!do_quiet) printf("Can't open \"%s\"\n", File); return -1; } sAreas = calloc(PATH_MAX, sizeof(char)); snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("FTND_ROOT")); if ((fp = fopen(sAreas, "r")) == NULL) { WriteError("$Can't open %s", sAreas); free(sAreas); fclose(tp); return -1; } fread(&msgshdr, sizeof(msgshdr), 1, fp); if (fseek(fp, (msgshdr.recsize + msgshdr.syssize) * (Area - 1), SEEK_CUR) == 0) { if (fread(&msgs, msgshdr.recsize, 1, fp) == 1) { rc = TRUE; } else { WriteError("$Can't read area %ld", Area); } } else { WriteError("$Can't seek area %ld", Area); } free(sAreas); if (rc == FALSE) { fclose(fp); fclose(tp); return -1; } if (!msgs.Active) { WriteError("Area %s not active", msgs.Name); fclose(fp); fclose(tp); return -1; } /* * Check the proper syntax in the To parameter, in netmail areas * it must have a destination address, in all other areas just a * full name. */ if (msgs.Type == NETMAIL) { if ((strchr(To, '@') == NULL) || (strstr(To, (char *)".n") == NULL) || (strstr(To, (char *)".z") == NULL)) { WriteError("No address in \"%s\" and area is netmail", To); if (!do_quiet) printf("No address in \"%s\" and area is netmail\n", To); fclose(fp); fclose(tp); return -1; } } else { if ((strchr(To, '@')) || (strstr(To, (char *)".n")) || (strstr(To, (char *)".z"))) { WriteError("Address present in \"%s\" and area is not netmail", To); if (!do_quiet) printf("Address present in \"%s\" and area is not netmail\n", To); fclose(fp); fclose(tp); return -1; } } if (!Msg_Open(msgs.Base)) { WriteError("Can't open %s", msgs.Base); fclose(fp); fclose(tp); return -1; } if (!Msg_Lock(30L)) { WriteError("Can't lock %s", msgs.Base); Msg_Close(); fclose(fp); fclose(tp); return -1; } tt = time(NULL); t = localtime(&tt); Diw = t->tm_wday; Miy = t->tm_mon; memset(&Msg, 0, sizeof(Msg)); Msg_New(); /* * Update statistic counter for message area */ fseek(fp, - msgshdr.recsize, SEEK_CUR); msgs.Posted.total++; msgs.Posted.tweek++; msgs.Posted.tdow[Diw]++; msgs.Posted.month[Miy]++; fwrite(&msgs, msgshdr.recsize, 1, fp); fclose(fp); /* * Start writing the message */ snprintf(Msg.From, 101, CFG.sysop_name); snprintf(Msg.To, 101, To); /* * If netmail, clean the To field. */ if ((msgs.Type == NETMAIL) && strchr(To, '@')) { for (i = 0; i < strlen(Msg.To); i++) { if (Msg.To[i] == '_') Msg.To[i] = ' '; if (Msg.To[i] == '@') { Msg.To[i] = '\0'; break; } } } snprintf(Msg.Subject, 101, "%s", Subj); snprintf(Msg.FromAddress, 101, "%s", aka2str(msgs.Aka)); Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Local = TRUE; if (strchr(Flavor, 'c')) Msg.Crash = TRUE; if (strchr(Flavor, 'p')) Msg.Private = TRUE; if (strchr(Flavor, 'h')) Msg.Hold = TRUE; switch (msgs.Type) { case LOCALMAIL: Msg.Localmail = TRUE; break; case NETMAIL: Msg.Netmail = TRUE; snprintf(Msg.ToAddress, 101, "%s", ascfnode(parsefaddr(To), 0xff)); break; case ECHOMAIL: Msg.Echomail = TRUE; break; case NEWS: Msg.News = TRUE; break; } temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "\001MSGID: %s %08x", aka2str(msgs.Aka), sequencer()); MsgText_Add2(temp); Msg.MsgIdCRC = upd_crc32(temp, crc, strlen(temp)); Msg.ReplyCRC = 0xffffffff; snprintf(temp, PATH_MAX, "\001PID: FTND-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU()); MsgText_Add2(temp); if (msgs.Charset != FTNC_NONE) { snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(msgs.Charset)); } else { snprintf(temp, PATH_MAX, "\001CHRS: %s", getftnchrs(FTNC_LATIN_1)); } MsgText_Add2(temp); snprintf(temp, PATH_MAX, "\001TZUTC: %s", gmtoffset(tt)); MsgText_Add2(temp); while ((Fgets(temp, PATH_MAX, tp)) != NULL) { if (strncmp(temp, "--- ", 4) == 0) has_tear = TRUE; if (strncmp(temp, " * Origin: ", 11) == 0) has_origin = TRUE; } rewind(tp); Syslog('m', "has tearline=%s, has origin=%s", has_tear?"True":"False", has_origin?"True":"False"); /* * Add the file as text */ Msg_Write(tp); fclose(tp); /* * Finish the message */ if ((! has_tear) && (! has_origin)) { MsgText_Add2((char *)""); MsgText_Add2(TearLine()); } if (! has_origin) { aka = calloc(40, sizeof(char)); if (msgs.Aka.point) snprintf(aka, 40, "(%d:%d/%d.%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node, msgs.Aka.point); else snprintf(aka, 40, "(%d:%d/%d)", msgs.Aka.zone, msgs.Aka.net, msgs.Aka.node); if (strlen(msgs.Origin)) snprintf(temp, 81, " * Origin: %s %s", msgs.Origin, aka); else snprintf(temp, 81, " * Origin: %s %s", CFG.origin, aka); MsgText_Add2(temp); free(aka); } Msg_AddMsg(); Msg_UnLock(); Syslog('+', "Posted message %ld", Msg.Id); if (msgs.Type != LOCALMAIL) { snprintf(temp, PATH_MAX, "%s/tmp/%smail.jam", getenv("FTND_ROOT"), (msgs.Type == ECHOMAIL) ? "echo" : "net"); if ((fp = fopen(temp, "a")) != NULL) { fprintf(fp, "%s %u\n", msgs.Base, Msg.Id); fclose(fp); } CreateSema((char *)"mailout"); } free(temp); Msg_Close(); return 0; }