/***************************************************************************** * * $Id$ * Purpose ...............: Read *.msg messages * ***************************************************************************** * Copyright (C) 1997-2005 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS 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, or (at your option) any * later version. * * MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "../config.h" #include "../lib/mbselib.h" #include "../lib/users.h" #include "../lib/mbsedb.h" #include "../lib/msgtext.h" #include "../lib/msg.h" #include "msgflags.h" #include "msg.h" extern int net_msgs; extern int net_in; extern int net_imp; extern int do_scan; int toss_onemsg(char *); int toss_msgs(void) { DIR *dp; struct dirent *de; int files = 0; if (strlen(CFG.msgs_path) == 0) { WriteError("No path defined for *.msg mail, check setup 1.4 screen 2, item 10"); return -1; } if ((dp = opendir(CFG.msgs_path)) == NULL) { WriteError("$Can't opendir %s", CFG.msgs_path); return -1; } Syslog('m', "Process *.msg in %s", CFG.msgs_path); IsDoing("Get *.msgs"); while ((de = readdir(dp))) { if ((de->d_name[0] != '.') && (strstr(de->d_name, ".msg"))) { if (IsSema((char *)"upsalarm")) { Syslog('+', "Detected upsalarm semafore, aborting toss"); break; } Syslog('m', "Process %s", de->d_name); toss_onemsg(de->d_name); files++; } } closedir(dp); if (files) { Syslog('+',"Processed %d msg messages", files); } return files; } /* * Toss one message and post into a JAM messagebase. Returns: * 0 = Ok * 1 = Can't open *.msg * 2 = Can't read message * 3 = Missing zone info * 4 = No ftn network or netmailboard in setup * 5 = Can't open JAM area * 6 = Empty local netmail, dropped. */ int toss_onemsg(char *msgname) { int rc = 0, islocal, empty = TRUE; char *temp, *dospath, *flagstr = NULL, *l, *r, *msgid = NULL; char fromUserName[37], toUserName[37], subject[73], DateTime[21]; FILE *fp, *np; faddr *ta; unsigned char buf[0xbe]; unsigned short destNode = 0, destNet = 0, destZone = 0, destPoint = 0; unsigned short origNode = 0, origNet = 0, origZone = 0, origPoint = 0; unsigned short Attribute = 0; struct stat sb; net_msgs++; temp = calloc(PATH_MAX, sizeof(char)); snprintf(temp, PATH_MAX, "%s/%s", CFG.msgs_path, msgname); if ((fp = fopen(temp, "r")) == NULL) { WriteError("$Can't open %s", temp); free(temp); return 1; } /* * First read message header information we need. */ memset(&fromUserName, 0, sizeof(fromUserName)); memset(&toUserName, 0, sizeof(toUserName)); memset(&subject, 0, sizeof(subject)); memset(&DateTime, 0, sizeof(DateTime)); if (fread(&buf, 1, 0xbe, fp) != 0xbe) { WriteError("$Could not read header (%s)", temp); fclose(fp); free(temp); return 2; } strncpy(fromUserName, buf, 36); strncpy(toUserName, buf+0x24, 36); strncpy(subject, buf+0x48, 72); strncpy(DateTime, buf+0x90, 20); Syslog('m', "From \"%s\"", printable(fromUserName, 0)); Syslog('m', "To \"%s\"", printable(toUserName, 0)); Syslog('m', "Subj \"%s\"", printable(subject, 0)); Syslog('m', "Date \"%s\"", printable(DateTime, 0)); destNode = (buf[0xa7] << 8) + buf[0xa6]; origNode = (buf[0xa9] << 8) + buf[0xa8]; origNet = (buf[0xad] << 8) + buf[0xac]; destNet = (buf[0xaf] << 8) + buf[0xae]; destZone = (buf[0xb1] << 8) + buf[0xb0]; origZone = (buf[0xb3] << 8) + buf[0xb2]; destPoint = (buf[0xb5] << 8) + buf[0xb4]; origPoint = (buf[0xb7] << 8) + buf[0xb6]; Attribute = (buf[0xbb] << 8) + buf[0xba]; Syslog('m', "From %d:%d/%d.%d to %d:%d/%d.%d", origZone, origNet, origNode, origPoint, destZone, destNet, destNode, destPoint); while (Fgets(temp, PATH_MAX-1, fp)) { Syslog('m', "Line \"%s\"", printable(temp, 0)); if (!strncmp(temp, "\001MSGID: ", 8)) { msgid = xstrcpy(temp + 8); /* * Extra test to see if the mail comes from a pointaddress. */ l = strtok(temp," \0"); l = strtok(NULL," \0"); if ((ta = parsefnode(l))) { if (ta->net == origNet && ta->node == origNode && !origPoint && ta->point) { Syslog('m', "Setting pointinfo (%d) from MSGID", ta->point); origPoint = ta->point; } if ((ta->net == origNet) && (ta->node == origNode) && (origZone == 0) && ta->zone) { /* * Missing zone info, maybe later we will see a INTL kludge or so, but for * now, just in case we fix it. And we need that for some Aka collecting * sysop who doesn't know how to configure his system right. */ Syslog('m', "No from zone set, setting zone %d from MSGID", ta->zone); origZone = ta->zone; /* * 99.9 % chance that the destination zone is also missing. */ if (destZone == 0) { destZone = ta->zone; Syslog('m', "No dest zone set, setting zone %d from MSGID", ta->zone); } } tidy_faddr(ta); } if (msgid) free(msgid); msgid = NULL; } if (!strncmp(temp, "\001FMPT", 5)) { l = strtok(temp, " \0"); l = strtok(NULL, " \0"); origPoint = atoi(l); } if (!strncmp(temp, "\001TOPT", 5)) { l = strtok(temp, " \0"); l = strtok(NULL, " \0"); destPoint = atoi(l); } if (!strncmp(temp, "\001INTL", 5)) { Syslog('m', "Setting addresses from INTL kludge"); l = strtok(temp," \0"); l = strtok(NULL," \0"); r = strtok(NULL," \0"); if ((ta = parsefnode(l))) { destPoint = ta->point; destNode = ta->node; destNet = ta->net; destZone = ta->zone; tidy_faddr(ta); } if ((ta = parsefnode(r))) { origPoint = ta->point; origNode = ta->node; origNet = ta->net; origZone = ta->zone; tidy_faddr(ta); } } /* * Check FLAGS kludge */ if (!strncmp(buf, "\001FLAGS ", 7)) { flagstr = xstrcpy(buf + 7); Syslog('m', "^aFLAGS %s", flagstr); } if (!strncmp(buf, "\001FLAGS: ", 8)) { flagstr = xstrcpy(buf + 8); Syslog('m', "^aFLAGS: %s", flagstr); } if (buf[0] != '\0') { if ((buf[0] != '\001') && (strcmp(buf, (char *)"--- "))) empty = FALSE; } } Syslog('m', "Mail is %sempty", empty ? "":"not "); Syslog('m', "From %d:%d/%d.%d to %d:%d/%d.%d", origZone, origNet, origNode, origPoint, destZone, destNet, destNode, destPoint); if ((origZone == 0) || (destZone == 0)) { WriteError("No zone info in %s/%s", CFG.msgs_path, msgname); fclose(fp); free(temp); return 3; } if (SearchFidonet(origZone) == FALSE) { WriteError("Can't find network for zone %d", origZone); fclose(fp); free(temp); return 4; } if (SearchNetBoard(origZone, origNet) == FALSE) { WriteError("Can't find netmail board for zone:net %d:%d", origZone, origNet); fclose(fp); free(temp); return 4; } if (Msg_Open(msgs.Base) && Msg_Lock(30L)) { Msg_New(); strcpy(Msg.From, fromUserName); strcpy(Msg.To, toUserName); strcpy(Msg.Subject, subject); if (Attribute & M_FILE) { if ((stat(subject, &sb) == 0) && (S_ISREG(sb.st_mode))) { dospath = xstrcpy(Unix2Dos(subject)); Syslog('+', "Fileattach %s in message %s", subject, msgname); if (strlen(CFG.dospath)) strcpy(Msg.Subject, dospath); Msg.FileAttach = TRUE; free(dospath); } else { WriteError("Fileattach %s in message %s not found", subject, msgname); } } Msg.Written = parsefdate(DateTime, NULL); Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.KillSent = ((Attribute & M_KILLSENT)); Msg.Hold = ((Attribute & M_HOLD)); Msg.Crash = ((Attribute & M_CRASH) || flag_on((char *)"CRA", flagstr)); Msg.ReceiptRequest = ((Attribute & M_RRQ) || flag_on((char *)"RRQ", flagstr)); Msg.Orphan = ((Attribute & M_ORPHAN)); Msg.Intransit = ((Attribute & M_TRANSIT)); Msg.FileRequest = ((Attribute & M_REQ) || flag_on((char *)"FRQ", flagstr)); Msg.ConfirmRequest = ((Attribute & M_AUDIT) || flag_on((char *)"CFM", flagstr)); Msg.Immediate = flag_on((char *)"IMM", flagstr); Msg.Direct = flag_on((char *)"DIR", flagstr); Msg.Gate = flag_on((char *)"ZON", flagstr); if ((origZone == destZone) && (origNet == destNet) && (origNode == destNode) && (origPoint == destPoint)) { /* * Message is local, make the message appear as a received netmail */ if (empty) { Syslog('+', "Empty local netmail for %s dropped", toUserName); Msg_UnLock(); Msg_Close(); fclose(fp); free(temp); return 6; } islocal = TRUE; if ((strncasecmp(toUserName, "sysop", 5) == 0) || (strncasecmp(toUserName, "postmaster", 10) == 0) || (strncasecmp(toUserName, "coordinator", 11) == 0)) { Syslog('+', " Readdress from %s to %s", toUserName, CFG.sysop_name); snprintf(toUserName, 37, "%s", CFG.sysop_name); strcpy(Msg.To, toUserName); } net_imp++; } else { Msg.Local = TRUE; islocal = FALSE; } Syslog('m', "Netmail is %s", islocal ? "Local":"for export"); Msg.Private = TRUE; Msg.Netmail = TRUE; if (origPoint) snprintf(Msg.FromAddress, 101, "%d:%d/%d.%d@%s", origZone, origNet, origNode, origPoint, fidonet.domain); else snprintf(Msg.FromAddress, 101, "%d:%d/%d@%s", origZone, origNet, origNode, fidonet.domain); if (SearchFidonet(destZone)) { if (destPoint) snprintf(Msg.ToAddress, 101, "%d:%d/%d.%d@%s", destZone, destNet, destNode, destPoint, fidonet.domain); else snprintf(Msg.ToAddress, 101, "%d:%d/%d@%s", destZone, destNet, destNode, fidonet.domain); } else { if (destPoint) snprintf(Msg.ToAddress, 101, "%d:%d/%d.%d", destZone, destNet, destNode, destPoint); else snprintf(Msg.ToAddress, 101, "%d:%d/%d", destZone, destNet, destNode); } /* * Add original message text */ fseek(fp, 0xbe, SEEK_SET); while (fgets(temp, PATH_MAX-1, fp)) { Striplf(temp); if (temp[strlen(temp)-1] == '\r') temp[strlen(temp)-1] = '\0'; MsgText_Add2(temp); } Msg_AddMsg(); Msg_UnLock(); Syslog('+', "%s => %s (%ld) to \"%s\", \"%s\"", msgname, msgs.Name, Msg.Id, Msg.To, Msg.Subject); msgs.LastPosted = time(NULL); msgs.Posted.total++; msgs.Posted.tweek++; msgs.Posted.tdow[Diw]++; msgs.Posted.month[Miy]++; UpdateMsgs(); if (!islocal) { do_scan = TRUE; snprintf(temp, PATH_MAX, "%s/tmp/netmail.jam", getenv("MBSE_ROOT")); if ((np = fopen(temp, "a")) != NULL) { fprintf(np, "%s %u\n", msgs.Base, Msg.Id); fclose(np); } } Msg_Close(); } else { WriteError("Can't open JAM %s", msgs.Base); rc = 5; } fclose(fp); if (rc == 0) { net_in++; snprintf(temp, PATH_MAX, "%s/%s", CFG.msgs_path, msgname); if (unlink(temp) != 0) WriteError("Can't remove %s", temp); } free(temp); return rc; }