void formatTime(const GregorianDateTime &t, DateConversionBuffer& buffer) { int offset = abs(gmtoffset(t)); char timeZoneName[70]; struct tm gtm = t; strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); if (timeZoneName[0]) { snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d (%s)", t.hour, t.minute, t.second, gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); } else { snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d", t.hour, t.minute, t.second, gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); } }
bool DateInstance::getTime(GregorianDateTime& t, int& offset) const { double milli = internalNumber(); if (isnan(milli)) return false; msToGregorianDateTime(milli, false, t); offset = gmtoffset(t); return true; }
UString formatTime(const GregorianDateTime &t, bool utc) { char buffer[100]; if (utc) { snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second); } else { int offset = abs(gmtoffset(t)); char tzname[70]; struct tm gtm = t; strftime(tzname, sizeof(tzname), "%Z", >m); if (tzname[0]) { snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)", t.hour, t.minute, t.second, gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname); } else { snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d", t.hour, t.minute, t.second, gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); } } return UString(buffer); }
JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { if (!thisValue.isObject(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; DateInstance* thisDateObj = asDateInstance(thisValue); double milli = thisDateObj->internalNumber(); if (isnan(milli)) return jsNaN(exec); GregorianDateTime t; thisDateObj->msToGregorianDateTime(milli, utc, t); return jsNumber(exec, -gmtoffset(t) / minutesPerHour); }
/*============================================================================================================== * * NAME * wake_builtin_date - Formats a date. * * PROTOTYPE * $(<date> [ format [, time] ] ) * $(<gmdate> [ format [, time] ] ) * * DESCRIPTION * Formats a time value. * * PARAMETERS * format - * A format string, that accepts the same specifiers than the PHP date() function. * If not specified, the default format is 'Y-m-d H:i:s'. * * time - * A time value. If not specified, the current Unix time is used. * *==============================================================================================================*/ static char * __wake_builtin_date ( char * output, char * format, time_t time_value, int is_localtime ) { struct tm * tm = ( is_localtime ) ? localtime ( & time_value ) : gmtime ( & time_value ) ; char * p = format ; int ap_hour ; char buffer [128] ; char * buffer_p ; int iso_year, iso_week ; int iso_values_set = 0, tz_set = 0 ; tm -> tm_year += 1900 ; ap_hour = ( tm -> tm_hour % 12 ) ? tm -> tm_hour % 12 : 12 ; while ( * p ) { buffer_p = NULL ; * buffer = 0 ; switch ( * p ) { // 'a' : lowercase "am" or "pm" case 'a' : buffer_p = ( tm -> tm_hour >= 12 ) ? "pm" : "am" ; break ; // 'A' : uppercase "AM" or "PM" case 'A' : buffer_p = ( tm -> tm_hour >= 12 ) ? "PM" : "AM" ; break ; // 'B' : internet Swatch hour case 'B' : { int result = ( ( ( time_value - ( time_value - ( ( time_value % 86400 ) + 3600 ) ) ) * 10 ) / 864 ) ; while ( result < 0 ) result += 1000 ; result %= 1000 ; sprintf ( buffer, "%03d", result ) ; break ; } // 'c' : Full date, in ISO8601 format case 'c' : sprintf ( buffer, "%04d-%02d-%02dT%02d:%02d:%02d%s", tm -> tm_year, tm -> tm_mon + 1, tm -> tm_mday, tm -> tm_hour, tm -> tm_min, tm -> tm_sec, gmtoffset ( is_localtime, tm -> tm_gmtoff, 1 ) ) ; break ; // 'd' : day of month, as a two-digits number case 'd' : sprintf ( buffer, "%02d", tm -> tm_mday ) ; break ; // 'D' : short day name case 'D' : buffer_p = short_day_names [ tm -> tm_wday ] ; break ; // 'e' : Timezone name case 'e' : if ( ! tz_set ) tzset ( ) ; buffer_p = tzname [0] ; break ; // 'F' : Long month name case 'F' : buffer_p = long_month_names [ tm -> tm_mon ] ; break ; // 'g' : Hour without leading zero (1..12) case 'g' : sprintf ( buffer, "%d", ap_hour ) ; break ; // 'G' : Hour without leading zero (0..23) case 'G' : sprintf ( buffer, "%d", tm -> tm_hour ) ; break ; // 'h' : Hour with leading zero (01..12) case 'h' : sprintf ( buffer, "%02d", ap_hour ) ; break ; // 'H' : Hour with leading zero (00..23) case 'H' : sprintf ( buffer, "%02d", tm -> tm_hour ) ; break ; // 'i' : Minute, with leading zero (00..59) case 'i' : sprintf ( buffer, "%02d", tm -> tm_min ) ; break ; // 'I' : 1 if daylight savings time is active, 0 otherwise case 'I' : sprintf ( buffer, "%d", tm -> tm_isdst ) ; break ; // 'j' : day of month, without the leading zero case 'j' : sprintf ( buffer, "%d", tm -> tm_mday ) ; break ; // 'l' : Long day name case 'l' : buffer_p = long_day_names [ tm -> tm_wday ] ; break ; // 'L' : 1 is the year is leap, 0 otherwise case 'L' : sprintf ( buffer, "%d", IS_LEAP ( tm -> tm_year ) ) ; break ; // 'M' : short month name case 'M' : buffer_p = short_month_names [ tm -> tm_mon ] ; break ; // 'm' : month of year, as a two-digits number case 'm' : sprintf ( buffer, "%02d", tm -> tm_mon + 1 ) ; break ; // 'n' : month of year, without the leading zero case 'n' : sprintf ( buffer, "%d", tm -> tm_mon + 1 ) ; break ; // 'N' : day of week, from 1 (monday) to 7 (sunday) case 'N' : sprintf ( buffer, "%d", ( tm -> tm_wday ) ? tm -> tm_wday : 7 ) ; break ; // 'o' : ISO8601 year case 'o' : if ( ! iso_values_set ) { isoweek_from_date ( tm -> tm_year, tm -> tm_mon, tm -> tm_mday, & iso_week, & iso_year ) ; iso_values_set = 1 ; } sprintf ( buffer, "%d", iso_year ) ; break ; // 'O' : GMT offset in ISO8601 format (+0200) case 'O' : buffer_p = gmtoffset ( is_localtime, tm -> tm_gmtoff, 0 ) ; break ; // 'P' : GMT offset in RFC822 format (+02:00) case 'P' : buffer_p = gmtoffset ( is_localtime, tm -> tm_gmtoff, 1 ) ; break ; // 'r' : RFC822 date case 'r' : sprintf ( buffer, "%3s %02d %3s %04d %02d:%02d:%02d %s", short_day_names [ tm -> tm_wday ], tm -> tm_mday, short_month_names [ tm -> tm_mon ], tm -> tm_year, tm -> tm_hour, tm -> tm_min, tm -> tm_sec, gmtoffset ( is_localtime, tm -> tm_gmtoff, 0 ) ) ; break ; // 's' : Seconds, with leading zero (00..59) case 's' : sprintf ( buffer, "%02d", tm -> tm_sec ) ; break ; // 'S' : 2-letters english suffix for a day of month case 'S' : buffer_p = english_suffix ( tm -> tm_mday ) ; break ; // 't' : month length case 't' : sprintf ( buffer, "%d", MONTH_LENGTH ( tm -> tm_year, tm -> tm_mon ) ) ; break ; // 'T' : Timezone abbreviation case 'T' : if ( ! tz_set ) tzset ( ) ; buffer_p = tzname [1] ; break ; // 'u' : microsecond time. Always return '000000' since we accept an integer value as time case 'u' : buffer_p = "000000" ; break ; // 'U' : Unix time case 'U' : sprintf ( buffer, "%d", ( int ) time_value ) ; break ; // 'w' : day of week, from 0 (sunday) to 6 (saturday) case 'w' : sprintf ( buffer, "%d", tm -> tm_wday ) ; break ; // 'W' : ISO8601 week number (were weeks start on monday) case 'W' : if ( ! iso_values_set ) { isoweek_from_date ( tm -> tm_year, tm -> tm_mon, tm -> tm_mday, & iso_week, & iso_year ) ; iso_values_set = 1 ; } sprintf ( buffer, "%d", iso_week ) ; break ; // 'y' : 2-digits year case 'y' : sprintf ( buffer, "%02d", ( tm -> tm_year % 100 ) ) ; break ; // 'Y' : 4-digits year case 'Y' : sprintf ( buffer, "%04d", tm -> tm_year ) ; break ; // 'z' : day of year, from 0 to 365 case 'z' : sprintf ( buffer, "%d", tm -> tm_yday ) ; break ; // 'Z' : GMT offset in seconds case 'Z' : sprintf ( buffer, "%d", ( int ) tm -> tm_gmtoff ) ; break ; // Escape character : copy the next one without interpretation unless this is the last one case '\\' : if ( * ( p + 1 ) ) p ++ ; /* Intentionally fall through the default case */ // Other characters : copy as is default : buffer [0] = * p ; buffer [1] = 0 ; break ; } if ( buffer_p == NULL ) buffer_p = buffer ; output = variable_buffer_output ( output, buffer_p, strlen ( buffer_p ) ) ; p ++ ; } return ( output ) ; }
/* * Input a RFC news message. */ int rfc2ftn(FILE *fp) { char sbe[16], *p, *q, *temp, *origin, newsubj[4 * (MAXSUBJ+1)], *oldsubj; int i, rc, newsmode, seenlen, oldnet; rfcmsg *msg = NULL, *tmsg, *tmp; ftnmsg *fmsg = NULL; FILE *ofp, *qfp; fa_list *sbl = NULL, *ptl = NULL, *tmpl; faddr *ta, *fta; int sot_kludge = FALSE, eot_kludge = FALSE, tinyorigin = FALSE; int needsplit, hdrsize, datasize, splitpart, forbidsplit, rfcheaders; time_t Now; struct tm *l_date; char *charset = NULL; temp = calloc(4097, sizeof(char)); Syslog('m', "Entering rfc2ftn"); rewind(fp); msg = parsrfc(fp); newsmode = hdr((char *)"Newsgroups", msg) ?TRUE:FALSE; if (newsmode == FALSE) { WriteError("Not a news article"); return 1; } if ((fmsg = mkftnhdr(msg, newsmode, NULL)) == NULL) { WriteError("Unable to create FTN headers from RFC ones, aborting"); tidyrfc(msg); return 1; } fmsg->area = xstrcpy(msgs.Tag); if ((p = hdr((char *)"Message-ID",msg))) { ftnmsgid(p, &fmsg->msgid_a, &fmsg->msgid_n, fmsg->area); hash_update_s(&fmsg->msgid_n, fmsg->area); } if ((p = hdr((char *)"References",msg))) { p = strrchr(p,' '); ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); //Griffin fmsg->reply_s=calloc(256,sizeof(char)); findorigmsg(p,fmsg->reply_s); fmsg->to->name=calloc(strlen(Msg.From)+1,sizeof(char)); strcpy(fmsg->to->name,Msg.From); Syslog('m', "fmsg to-name %s",fmsg->to->name); Syslog('m', "reply_s %s",fmsg->reply_s); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } else if ((p = hdr((char *)"In-Reply-To",msg))) { ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } chkftnmsgid(hdr((char *)"Message-ID",msg)); // ?? removemime = FALSE; removemsgid = FALSE; removeref = FALSE; removeinreply = FALSE; removereplyto = TRUE; removereturnto = TRUE; ftnorigin = fmsg->ftnorigin; q = hdr((char *)"Content-Transfer-Encoding",msg); if (q) while (*q && isspace(*q)) q++; if (!(q)) q = (char *)"8bit"; if ((p = hdr((char *)"Content-Type",msg))) { while (*p && isspace(*p)) p++; /* * Check for mime to remove. */ if ((strncasecmp(p, "text/plain", 10) == 0) && ((q == NULL) || (strncasecmp(q,"7bit",4) == 0) || (strncasecmp(q,"8bit",4) == 0))) { removemime = TRUE; /* no need in MIME headers */ } q = strtok(p, " \n\0"); q = strtok(NULL, "; \n\0"); if (q) { while (*q && isspace(*q)) q++; Syslog('m', "charset part: %s", printable(q, 0)); if (q && (strncasecmp(q, "charset=", 8) == 0)) { /* * google.com quotes the charset name */ if (strchr(q, '"')) { charset = xstrcpy(q + 9); charset[strlen(charset)-1] = '\0'; Syslog('m', "Unquoted charset name"); } else { charset = xstrcpy(q + 8); } Syslog('m', "Charset \"%s\"", printable(charset, 0)); } } } if (charset == NULL) { charset = xstrcpy((char *)"ISO-8859-1"); Syslog('m', "No charset, setting default to iso-8859-1"); } chartran_init(charset, get_ic_ftn(msgs.Charset), 'm'); if ((p = hdr((char *)"Message-ID",msg))) { if (!removemsgid) removemsgid = chkftnmsgid(p); } if ((!removeref) && (p = hdr((char *)"References",msg))) { p = xstrcpy(p); q = strtok(p," \t\n"); if ((q) && (strtok(NULL," \t\n") == NULL)) removeref = chkftnmsgid(q); free(p); } if ((p = hdr((char *)"Reply-To",msg))) { removereplyto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while(*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereplyto = TRUE; } } if ((p = hdr((char *)"Return-Receipt-To",msg))) { removereturnto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while (*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereturnto = TRUE; } } Syslog('m', "removemime=%s removemsgid=%s removeref=%s removeinreply=%s removereplyto=%s removereturnto=%s", removemime ?"TRUE ":"FALSE", removemsgid ?"TRUE ":"FALSE", removeref ?"TRUE ":"FALSE", removeinreply ?"TRUE ":"FALSE", removereplyto ?"TRUE ":"FALSE", removereturnto ?"TRUE ":"FALSE"); p = ascfnode(fmsg->from,0x1f); i = 79-11-3-strlen(p); if (ftnorigin && fmsg->origin && (strlen(fmsg->origin) > i)) { /* This is a kludge... I don't like it too much. But well, if this is a message of FTN origin, the original origin (:) line MUST have been short enough to fit in 79 chars... So we give it a try. Probably it would be better to keep the information about the address format from the origin line in a special X-FTN-... header, but this seems even less elegant. Any _good_ ideas, anyone? */ /* OK, I am keeping this, though if should never be used al long as X-FTN-Origin is used now */ p = ascfnode(fmsg->from,0x0f); Syslog('m', "checkorigin 3"); i = 79-11-3-strlen(p); tinyorigin = TRUE; } if (tinyorigin) Syslog('m', "tinyorigin = %s", tinyorigin ? "True":"False"); if ((fmsg->origin) && (strlen(fmsg->origin) > i)) fmsg->origin[i]='\0'; forbidsplit = (ftnorigin || ((p = hdr((char *)"X-FTN-Split",msg)) && (strcasecmp(p," already\n") == 0))); needsplit = 0; splitpart = 0; hdrsize = 20; hdrsize += (fmsg->subj)?strlen(fmsg->subj):0; if (fmsg->from) hdrsize += (fmsg->from->name)?strlen(fmsg->from->name):0; if (fmsg->to) hdrsize += (fmsg->to->name)?strlen(fmsg->to->name):0; do { Syslog('m', "split loop, splitpart = %d", splitpart); datasize = 0; if (splitpart) { snprintf(newsubj,4 * (MAXSUBJ+1),"[part %d] ",splitpart+1); strncat(newsubj,fmsg->subj,MAXSUBJ-strlen(newsubj)); } else { strncpy(newsubj,fmsg->subj,MAXSUBJ); } newsubj[MAXSUBJ]='\0'; if (splitpart) { hash_update_n(&fmsg->msgid_n,splitpart); } oldsubj = fmsg->subj; fmsg->subj = newsubj; /* * Create a new temp message in FTN style format */ if ((ofp = tmpfile()) == NULL) { WriteError("$Can't open second tmpfile"); tidyrfc(msg); return 1; } if ((fmsg->msgid_a == NULL) && (fmsg->msgid_n == 0)) { Syslog('n', "No Messageid from poster, creating new MSGID"); fprintf(ofp, "\001MSGID: %s %08x\n", aka2str(msgs.Aka), sequencer()); } else { fprintf(ofp, "\001MSGID: %s %08x\n", MBSE_SS(fmsg->msgid_a),fmsg->msgid_n); } if (fmsg->reply_s) fprintf(ofp, "\1REPLY: %s\n", fmsg->reply_s); else if (fmsg->reply_a) fprintf(ofp, "\1REPLY: %s %08x\n", fmsg->reply_a, fmsg->reply_n); Now = time(NULL) - (gmt_offset((time_t)0) * 60); fprintf(ofp, "\001TZUTC: %s\n", gmtoffset(Now)); fprintf(ofp, "\001CHRS: %s\n", getftnchrs(msgs.Charset)); fmsg->subj = oldsubj; if ((p = hdr((char *)"X-FTN-REPLYADDR",msg))) { hdrsize += 10+strlen(p); fprintf(ofp,"\1REPLYADDR:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 10+strlen(replyaddr); fprintf(ofp,"\1REPLYADDR: "); kludgewrite(replyaddr,ofp); } if ((p = hdr((char *)"X-FTN-REPLYTO",msg))) { hdrsize += 8+strlen(p); fprintf(ofp,"\1REPLYTO:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 15; if (newsmode) fprintf(ofp,"\1REPLYTO: %s UUCP\n", aka2str(msgs.Aka)); else { fta = bestaka_s(fmsg->to); fprintf(ofp,"\1REPLYTO: %s UUCP\n", ascfnode(fta, 0x1f)); tidy_faddr(fta); } } else if ((p = hdr((char *)"Reply-To",msg))) { if ((ta = parsefaddr(p))) { if ((q = hdr((char *)"From",msg))) { if (!strcasestr(q,p)) { fprintf(ofp,"\1REPLYTO: %s %s\n", ascfnode(ta,0x1f), ta->name); } } tidy_faddr(ta); } } if ((p=strip_flags(hdr((char *)"X-FTN-FLAGS",msg)))) { hdrsize += 15; fprintf(ofp,"\1FLAGS:%s\n",p); free(p); } if (!hdr((char *)"X-FTN-PID", msg)) { p = hdr((char *)"User-Agent", msg); if (p == NULL) p = hdr((char *)"X-Newsreader", msg); if (p == NULL) p = hdr((char *)"X-Mailer", msg); if (p) { hdrsize += 4 + strlen(p); fprintf(ofp, "\1PID:"); kludgewrite(p, ofp); } else { fprintf(ofp, "\001PID: MBSE-NNTPD %s (%s-%s)\n", VERSION, OsName(), OsCPU()); } } if (!(hdr((char *)"X-FTN-Tearline", msg)) && !(hdr((char *)"X-FTN-TID", msg))) { snprintf(temp, 4096, " MBSE-NNTPD %s (%s-%s)", VERSION, OsName(), OsCPU()); hdrsize += 4 + strlen(temp); fprintf(ofp, "\1TID:"); kludgewrite(temp, ofp); } if ((splitpart == 0) || (hdrsize < MAXHDRSIZE)) { for (tmp = msg; tmp; tmp = tmp->next) { if ((!strncmp(tmp->key,"X-Fsc-",6)) || (!strncmp(tmp->key,"X-FTN-",6) && strcasecmp(tmp->key,"X-FTN-Tearline") && strcasecmp(tmp->key,"X-FTN-Origin") && strcasecmp(tmp->key,"X-FTN-Sender") && strcasecmp(tmp->key,"X-FTN-Split") && strcasecmp(tmp->key,"X-FTN-FLAGS") && strcasecmp(tmp->key,"X-FTN-AREA") && strcasecmp(tmp->key,"X-FTN-MSGID") && strcasecmp(tmp->key,"X-FTN-REPLY") && strcasecmp(tmp->key,"X-FTN-SEEN-BY") && strcasecmp(tmp->key,"X-FTN-PATH") && strcasecmp(tmp->key,"X-FTN-REPLYADDR") && strcasecmp(tmp->key,"X-FTN-REPLYTO") && strcasecmp(tmp->key,"X-FTN-To") && strcasecmp(tmp->key,"X-FTN-From") && strcasecmp(tmp->key,"X-FTN-CHARSET") && strcasecmp(tmp->key,"X-FTN-CHRS") && strcasecmp(tmp->key,"X-FTN-CODEPAGE") && strcasecmp(tmp->key,"X-FTN-ORIGCHRS") && strcasecmp(tmp->key,"X-FTN-SOT") && strcasecmp(tmp->key,"X-FTN-EOT") && strcasecmp(tmp->key,"X-FTN-Via"))) { if ((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0)) { if (!strcasecmp(tmp->val," SOT:\n")) sot_kludge = TRUE; else if (!strcasecmp(tmp->val," EOT:\n")) eot_kludge = TRUE; else { hdrsize += strlen(tmp->val); fprintf(ofp,"\1"); /* we should have restored the original string here... */ kludgewrite((tmp->val)+1,ofp); } } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+6); kludgewrite(tmp->val,ofp); } } } /* ZConnect are X-ZC-*: in usenet, \1ZC-*: in FTN */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,"X-ZC-",5))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+2); kludgewrite(tmp->val,ofp); } /* mondo.org gateway uses ".MSGID: ..." in usenet */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,".",1)) && (strcasecmp(tmp->key,".MSGID"))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+1); kludgewrite(tmp->val,ofp); } for (tmp = msg; tmp; tmp = tmp->next) { if ((needputrfc(tmp, newsmode) == 1)) { if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"\1RFC-Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1RFC-%s:",tmp->key); } kludgewrite(tmp->val, ofp); } } rfcheaders=0; for (tmp=msg;tmp;tmp=tmp->next) { if ((needputrfc(tmp, newsmode) > 1)) { rfcheaders++; if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"%s:",tmp->key); } charwrite(tmp->val, ofp); } } if (rfcheaders) charwrite((char *)"\n",ofp); if ((hdr((char *)"X-FTN-SOT",msg)) || (sot_kludge)) fprintf(ofp,"\1SOT:\n"); } if (replyaddr) { replyaddr = NULL; } if (needsplit) { fprintf(ofp," * Continuation %d of a split message *\n\n", splitpart); needsplit = FALSE; } else if ((p=hdr((char *)"X-Body-Start",msg))) { datasize += strlen(p); charwrite(p, ofp); } while (!(needsplit=(!forbidsplit) && (((splitpart && (datasize > (CFG.new_split * 1024))) || (!splitpart && ((datasize+hdrsize) > (CFG.new_split * 1024)))))) && (bgets(temp,4096-1,fp))) { datasize += strlen(temp); charwrite(temp, ofp); } if (needsplit) { fprintf(ofp,"\n * Message split, to be continued *\n"); splitpart++; } if ((p=hdr((char *)"X-FTN-EOT",msg)) || (eot_kludge)) fprintf(ofp,"\1EOT:\n"); if ((p=hdr((char *)"X-FTN-Tearline",msg))) { fprintf(ofp,"---"); if (strcasecmp(p," (none)\n") == 0) charwrite((char *)"\n",ofp); else charwrite(p,ofp); } else fprintf(ofp,"\n%s\n", TearLine()); if ((p = hdr((char *)"X-FTN-Origin",msg))) { if (*(q=p+strlen(p)-1) == '\n') *q='\0'; origin = xstrcpy((char *)" * Origin: "); origin = xstrcat(origin, p); } else { origin = xstrcpy((char *)" * Origin: "); if (fmsg->origin) origin = xstrcat(origin, fmsg->origin); else origin = xstrcat(origin, CFG.origin); origin = xstrcat(origin, (char *)" ("); origin = xstrcat(origin, ascfnode(fmsg->from,tinyorigin?0x0f:0x1f)); origin = xstrcat(origin, (char *)")"); } fprintf(ofp, "%s", origin); if (newsmode) { /* * Setup SEEN-BY lines, first SEEN-BY from RFC message, then all matching AKA's */ for (tmsg = msg; tmsg; tmsg = tmsg->next) if (strcasecmp(tmsg->key, "X-FTN-SEEN-BY") == 0) fill_list(&sbl, tmsg->val, NULL); for (i = 0; i < 40; i++) { if (CFG.akavalid[i] && (CFG.aka[i].point == 0) && (msgs.Aka.zone == CFG.aka[i].zone) && !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { snprintf(sbe, 16, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); fill_list(&sbl, sbe, NULL); } } if (msgs.Aka.point == 0) { snprintf(sbe, 16, "%u/%u", msgs.Aka.net, msgs.Aka.node); fill_list(&sbl, sbe, NULL); } /* * Only add SEEN-BY lines if there are any */ if (sbl != NULL) { uniq_list(&sbl); sort_list(&sbl); seenlen = MAXSEEN + 1; memset(&sbe, 0, sizeof(sbe)); /* ensure it will not match for the first entry */ oldnet = sbl->addr->net-1; for (tmpl = sbl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,16," %u",tmpl->addr->node); else snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXSEEN) { seenlen = 0; fprintf(ofp,"\nSEEN-BY:"); snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&sbl); } /* * Setup PATH lines */ for (tmp = msg; tmp; tmp = tmp->next) if (!strcasecmp(tmp->key,"X-FTN-PATH")) fill_path(&ptl,tmp->val); if (msgs.Aka.point == 0) { snprintf(sbe,16,"%u/%u",msgs.Aka.net, msgs.Aka.node); fill_path(&ptl,sbe); } /* * Only add PATH line if there is something */ if (ptl != NULL) { uniq_list(&ptl); seenlen = MAXPATH+1; /* ensure it will not match for the first entry */ oldnet = ptl->addr->net-1; for (tmpl = ptl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,16," %u",tmpl->addr->node); else snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXPATH) { seenlen = 0; fprintf(ofp,"\n\1PATH:"); snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&ptl); } } /* if (newsmode) */ /* * Add newline and message is ready. */ fprintf(ofp,"\n"); fflush(ofp); rewind(ofp); Syslog('m', "========== Fido start"); while (fgets(temp, 4096, ofp) != NULL) { /* * Only log kludges, skip the body */ if ((temp[0] == '\001') || !strncmp(temp, "AREA:", 5) || !strncmp(temp, "SEEN-BY", 7)) { Striplf(temp); Syslogp('m', printable(temp, 0)); } } Syslog('m', "========== Fido end"); if (!Msg_Open(msgs.Base)) { WriteError("Failed to open msgbase \"%s\"", msgs.Base); } else { if (!Msg_Lock(30L)) { WriteError("Can't lock %s", msgs.Base); } else { Msg_New(); strcpy(Msg.From, fmsg->from->name); strcpy(Msg.To, fmsg->to->name); strcpy(Msg.FromAddress, ascfnode(fmsg->from,0x1f)); strcpy(Msg.Subject, fmsg->subj); Msg.Written = Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); Msg.Local = TRUE; rewind(ofp); while (fgets(temp, 4096, ofp) != NULL) { Striplf(temp); MsgText_Add2(temp); } Msg_AddMsg(); Msg_UnLock(); Syslog('+', "Msg (%ld) to \"%s\", \"%s\"", Msg.Id, Msg.To, Msg.Subject); do_mailout = TRUE; /* * Create fast scan index */ snprintf(temp, PATH_MAX, "%s/tmp/echomail.jam", getenv("MBSE_ROOT")); if ((qfp = fopen(temp, "a")) != NULL) { fprintf(qfp, "%s %u\n", msgs.Base, Msg.Id); fclose(qfp); } /* * Link messages */ rc = Msg_Link(msgs.Base, TRUE, CFG.slow_util); if (rc != -1) Syslog('+', "Linked %d message%s", rc, (rc != 1) ? "s":""); else Syslog('+', "Could not link messages"); /* * Update statistical counters */ Now = time(NULL); l_date = localtime(&Now); msgs.LastPosted = time(NULL); msgs.Posted.total++; msgs.Posted.tweek++; msgs.Posted.tdow[l_date->tm_wday]++; msgs.Posted.month[l_date->tm_mon]++; mgroup.LastDate = time(NULL); mgroup.MsgsSent.total++; mgroup.MsgsSent.tweek++; mgroup.MsgsSent.tdow[l_date->tm_wday]++; mgroup.MsgsSent.month[l_date->tm_mon]++; UpdateMsgs(); snprintf(temp, PATH_MAX, "%s/etc/users.data", getenv("MBSE_ROOT")); if ((qfp = fopen(temp, "r+"))) { fread(&usrconfighdr, sizeof(usrconfighdr), 1, qfp); fseek(qfp, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), SEEK_SET); if (fread(&usrconfig, usrconfighdr.recsize, 1, qfp) == 1) { usrconfig.iPosted++; fseek(qfp, usrconfighdr.hdrsize + (grecno * usrconfighdr.recsize), SEEK_SET); fwrite(&usrconfig, usrconfighdr.recsize, 1, qfp); } fclose(qfp); } } Msg_Close(); } free(origin); fclose(ofp); } while (needsplit); free(temp); if (charset) free(charset); chartran_close(); tidyrfc(msg); tidy_ftnmsg(fmsg); UpdateMsgs(); return 0; }
int Bounce(faddr *f, faddr *t, FILE *fp, char *reason) { int rc = 0, count = 0; char *Buf; FILE *np; time_t Now; faddr *from; Now = time(NULL); if (SearchFidonet(f->zone)) f->domain = xstrcpy(fidonet.domain); Syslog('+', "Bounce msg from %s", ascfnode(f, 0xff)); Buf = calloc(MAX_LINE_LENGTH +1, sizeof(char)); rewind(fp); np = tmpfile(); from = bestaka_s(f); from->zone = t->zone; from->net = t->net; from->node = t->node; from->point = t->point; from->name = xstrcpy((char *)"Postmaster"); if (f->point) fprintf(np, "\001TOPT %d\r", f->point); if (from->point) fprintf(np, "\001FMPT %d\r", from->point); fprintf(np, "\001INTL %d:%d/%d %d:%d/%d\r", f->zone, f->net, f->node, from->zone, from->net, from->node); /* * Add MSGID, REPLY and PID */ fprintf(np, "\001MSGID: %s %08x\r", ascfnode(from, 0x1f), sequencer()); while ((fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL) { Striplf(Buf); if (strncmp(Buf, "\001MSGID:", 7) == 0) { fprintf(np, "\001REPLY:%s\r", Buf+7); } } fprintf(np, "\001PID: FTND-FIDO %s (%s-%s)\r", VERSION, OsName(), OsCPU()); fprintf(np, "\001TZUTC: %s\r", gmtoffset(Now)); fprintf(np, " Dear %s\r\r", FTND_SS(f->name)); fprintf(np, "Your message could not be delevered, reason: %s\r\r", reason); fprintf(np, "Here are the first lines of the original message from you:\r\r"); fprintf(np, "======================================================================\r"); rewind(fp); while ((fgets(Buf, MAX_LINE_LENGTH, fp)) != NULL) { Striplf(Buf); if (Buf[0] == '\001') { fprintf(np, "^a"); fwrite(Buf + 1, strlen(Buf) -1, 1, np); } else { fwrite(Buf, strlen(Buf), 1, np); } fputc('\r', np); count++; if (count == 50) break; } fprintf(np, "======================================================================\r"); if (count == 50) { fprintf(np, "\rOnly the first 50 lines are displayed\r"); } fprintf(np, "\rWith regards, %s\r\r", CFG.sysop_name); fprintf(np, "%s\r", TearLine()); Now = time(NULL) - (gmt_offset((time_t)0) * 60); rc = postnetmail(np, from, f, NULL, (char *)"Bounced message", Now, 0x0000, FALSE, from->zone, f->zone); tidy_faddr(from); fclose(np); free(Buf); return rc; }
/* * Input a RFC message. */ int rfc2ftn(FILE *fp, faddr *recipient) { char sbe[128], *p, *q, *temp, *origin, newsubj[4 * (MAXSUBJ+1)], *oldsubj, *acup_a = NULL, *charset = NULL; int i, rc, newsmode, seenlen, oldnet, chars_in = FTNC_NONE, chars_out = FTNC_NONE; rfcmsg *msg = NULL, *tmsg, *tmp; ftnmsg *fmsg = NULL; FILE *ofp; fa_list *sbl = NULL, *ptl = NULL, *tmpl; faddr *ta, *fta; unsigned int acup_n = 0; int sot_kludge = FALSE, eot_kludge = FALSE, tinyorigin = FALSE; int needsplit, hdrsize, datasize, splitpart, forbidsplit, rfcheaders; time_t Now; temp = calloc(MAXHDRSIZE +1, sizeof(char)); Syslog('m', "Entering rfc2ftn"); if (recipient) Syslog('m', "Recipient: %s", ascfnode(recipient, 0xff)); rewind(fp); msg = parsrfc(fp); newsmode = hdr((char *)"Newsgroups", msg) ?TRUE:FALSE; Syslog('m', "RFC message is %s", newsmode ? "news article":"e-mail message"); if (newsmode) { news_in++; snprintf(currentgroup, 81, "%s", msgs.Newsgroup); } else email_in++; if (!CFG.allowcontrol) { if (hdr((char *)"Control",msg)) { Syslog('+', "Rfc2ftn: Control message skipped"); tidyrfc(msg); return 1; } } if ((fmsg = mkftnhdr(msg, newsmode, recipient)) == NULL) { WriteError("Rfc2ftn: unable to create FTN headers from RFC ones, aborting"); tidyrfc(msg); return 1; } if (newsmode) fmsg->area = xstrcpy(msgs.Tag); if ((p = hdr((char *)"Message-ID",msg))) { ftnmsgid(p, &fmsg->msgid_a, &fmsg->msgid_n, fmsg->area); hash_update_s(&fmsg->msgid_n, fmsg->area); } if ((p = hdr((char *)"References",msg))) { p = strrchr(p,' '); ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } else if ((p = hdr((char *)"In-Reply-To",msg))) { ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); if (!chkftnmsgid(p)) { hash_update_s(&fmsg->reply_n, fmsg->area); } } chkftnmsgid(hdr((char *)"Message-ID",msg)); // ?? removemime = FALSE; removemsgid = FALSE; removeref = FALSE; removeinreply = FALSE; removereplyto = TRUE; removereturnto = TRUE; ftnorigin = fmsg->ftnorigin; q = hdr((char *)"Content-Transfer-Encoding",msg); if (q) while (*q && isspace(*q)) q++; if (!(q)) q = (char *)"8bit"; if ((p = hdr((char *)"Content-Type",msg))) { while (*p && isspace(*p)) p++; /* * Check for mime to remove. */ if ((strncasecmp(p, "text/plain", 10) == 0) && ((q == NULL) || (strncasecmp(q,"7bit",4) == 0) || (strncasecmp(q,"8bit",4) == 0))) { removemime = TRUE; /* no need in MIME headers */ } q = strtok(p, " \n\0"); q = strtok(NULL, "; \n\0"); if (q) { while (*q && isspace(*q)) q++; Syslog('m', "charset part: %s", printable(q, 0)); if (q && (strncasecmp(q, "charset=", 8) == 0)) { /* * google.com quotes the charset name */ if (strchr(q, '"')) { charset = xstrcpy(q + 9); charset[strlen(charset)-1] = '\0'; } else { charset = xstrcpy(q + 8); } Syslog('m', "Charset \"%s\"", printable(charset, 0)); } } } if (charset == NULL) { charset = xstrcpy((char *)"ISO-8859-1"); Syslog('m', "No charset, setting default to ISO-8859-1"); } if ((p = hdr((char *)"Message-ID",msg))) { if (!removemsgid) removemsgid = chkftnmsgid(p); } if ((!removeref) && (p = hdr((char *)"References",msg))) { p = xstrcpy(p); q = strtok(p," \t\n"); if ((q) && (strtok(NULL," \t\n") == NULL)) removeref = chkftnmsgid(q); free(p); } if ((p = hdr((char *)"Reply-To",msg))) { removereplyto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while(*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereplyto = TRUE; } } if ((p = hdr((char *)"Return-Receipt-To",msg))) { removereturnto = FALSE; if ((q = hdr((char *)"From",msg))) { char *r; r = xstrcpy(p); p = r; while (*p && isspace(*p)) p++; if (p[strlen(p)-1] == '\n') p[strlen(p)-1]='\0'; if (strcasestr(q,p)) removereturnto = TRUE; } } Syslog('m', "removemime=%s removemsgid=%s removeref=%s removeinreply=%s removereplyto=%s removereturnto=%s", removemime ?"TRUE ":"FALSE", removemsgid ?"TRUE ":"FALSE", removeref ?"TRUE ":"FALSE", removeinreply ?"TRUE ":"FALSE", removereplyto ?"TRUE ":"FALSE", removereturnto ?"TRUE ":"FALSE"); p = ascfnode(fmsg->from,0x1f); i = 79-11-3-strlen(p); if (ftnorigin && fmsg->origin && (strlen(fmsg->origin) > i)) { /* This is a kludge... I don't like it too much. But well, if this is a message of FTN origin, the original origin (:) line MUST have been short enough to fit in 79 chars... So we give it a try. Probably it would be better to keep the information about the address format from the origin line in a special X-FTN-... header, but this seems even less elegant. Any _good_ ideas, anyone? */ /* OK, I am keeping this, though if should never be used al long as X-FTN-Origin is used now */ p = ascfnode(fmsg->from,0x0f); Syslog('m', "checkorigin 3"); i = 79-11-3-strlen(p); tinyorigin = TRUE; } if (tinyorigin) Syslog('m', "tinyorigin = %s", tinyorigin ? "True":"False"); if ((fmsg->origin) && (strlen(fmsg->origin) > i)) fmsg->origin[i]='\0'; forbidsplit = (ftnorigin || ((p = hdr((char *)"X-FTN-Split",msg)) && (strcasecmp(p," already\n") == 0))); needsplit = 0; splitpart = 0; hdrsize = 20; hdrsize += (fmsg->subj)?strlen(fmsg->subj):0; if (fmsg->from) hdrsize += (fmsg->from->name)?strlen(fmsg->from->name):0; if (fmsg->to) hdrsize += (fmsg->to->name)?strlen(fmsg->to->name):0; chars_in = find_rfc_charset(charset); chars_out = msgs.Charset; if (chars_in == FTNC_ERROR) { /* * Not in standard tables, go ahead with the uppercase name * and see if iconv will take it. It doesn't really matter if * we support the incoming rfc charset, */ tu(charset); Syslog('m', "rfc2ftn: charset in: %s charset out: %s", charset, get_ic_ftn(chars_out)); chartran_init(charset, get_ic_ftn(chars_out), 'm'); } else { Syslog('m', "rfc2ftn: charset in: %s charset out: %s", get_ic_rfc(chars_in), get_ic_ftn(chars_out)); chartran_init(get_ic_rfc(chars_in), get_ic_ftn(chars_out), 'm'); } do { Syslog('m', "rfc2ftn: split loop, splitpart = %d", splitpart); datasize = 0; if (splitpart) { snprintf(newsubj,4 * MAXSUBJ,"[part %d] ",splitpart+1); strncat(newsubj,fmsg->subj,MAXSUBJ-strlen(newsubj)); Syslog('+', "Rfc2ftn: split message part %d", splitpart); } else { strncpy(newsubj,fmsg->subj,MAXSUBJ); } newsubj[MAXSUBJ]='\0'; if (splitpart) { hash_update_n(&fmsg->msgid_n,splitpart); } oldsubj = fmsg->subj; fmsg->subj = newsubj; /* * Create a new temp message in FTN style format */ if ((ofp = tmpfile()) == NULL) { WriteError("$Rfc2ftn: Can't open second tmpfile"); tidyrfc(msg); return 1; } if (newsmode) { fprintf(ofp, "AREA:%s\n", msgs.Tag); } else { if (fmsg->to->point != 0) fprintf(ofp, "\001TOPT %d\n", fmsg->to->point); if (fmsg->from->point != 0) fprintf(ofp, "\001FMPT %d\n", fmsg->from->point); fprintf(ofp, "\001INTL %d:%d/%d %d:%d/%d\n", fmsg->to->zone, fmsg->to->net, fmsg->to->node, fmsg->from->zone, fmsg->from->net, fmsg->from->node); } if ((fmsg->msgid_a == NULL) || (fmsg->msgid_n == 0)) { Syslog('!', "Rfc2ftn: warning, no MSGID %s %08lx", MBSE_SS(fmsg->msgid_a), fmsg->msgid_n); } fprintf(ofp, "\001MSGID: %s %08x\n", MBSE_SS(fmsg->msgid_a),fmsg->msgid_n); if (fmsg->reply_s) fprintf(ofp, "\1REPLY: %s\n", fmsg->reply_s); else if (fmsg->reply_a) fprintf(ofp, "\1REPLY: %s %08x\n", fmsg->reply_a, fmsg->reply_n); Now = time(NULL) - (gmt_offset((time_t)0) * 60); fprintf(ofp, "\001TZUTC: %s\n", gmtoffset(Now)); fprintf(ofp, "\001CHRS: %s\n", getftnchrs(msgs.Charset)); fmsg->subj = oldsubj; if ((p = hdr((char *)"X-FTN-REPLYADDR",msg))) { hdrsize += 10+strlen(p); fprintf(ofp,"\1REPLYADDR:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 10+strlen(replyaddr); fprintf(ofp,"\1REPLYADDR: "); kludgewrite(replyaddr,ofp); } if ((p = hdr((char *)"X-FTN-REPLYTO",msg))) { hdrsize += 8+strlen(p); fprintf(ofp,"\1REPLYTO:"); kludgewrite(p,ofp); } else if (replyaddr) { hdrsize += 15; if (newsmode) fprintf(ofp,"\1REPLYTO: %s UUCP\n", aka2str(msgs.Aka)); else { fta = bestaka_s(fmsg->to); fprintf(ofp,"\1REPLYTO: %s UUCP\n", ascfnode(fta, 0x1f)); tidy_faddr(fta); } } else if ((p = hdr((char *)"Reply-To",msg))) { if ((ta = parsefaddr(p))) { if ((q = hdr((char *)"From",msg))) { if (!strcasestr(q,p)) { fprintf(ofp,"\1REPLYTO: %s %s\n", ascfnode(ta,0x1f), ta->name); } } tidy_faddr(ta); } } if ((p=strip_flags(hdr((char *)"X-FTN-FLAGS",msg)))) { hdrsize += 15; fprintf(ofp,"\1FLAGS:%s\n",p); free(p); } if (!hdr((char *)"X-FTN-PID", msg)) { p = hdr((char *)"User-Agent", msg); if (p == NULL) p = hdr((char *)"X-Newsreader", msg); if (p == NULL) p = hdr((char *)"X-Mailer", msg); if (p) { hdrsize += 4 + strlen(p); fprintf(ofp, "\1PID:"); kludgewrite(p, ofp); } else { fprintf(ofp, "\001PID: MBSE-FIDO %s (%s-%s)\n", VERSION, OsName(), OsCPU()); } } if (CFG.allowcontrol && (!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Control",msg))) { if (strstr(p,"cancel")) { ftnmsgid(p,&acup_a,&acup_n,fmsg->area); if (acup_a) { hash_update_s(&acup_n,fmsg->area); hdrsize += 26 + strlen(acup_a); fprintf(ofp,"\1ACUPDATE: DELETE %s %08x\n", acup_a,acup_n); } } } if ((!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Supersedes",msg))) { ftnmsgid(p,&acup_a,&acup_n,fmsg->area); if (acup_a) { hash_update_s(&acup_n,fmsg->area); hdrsize += 26 + strlen(acup_a); fprintf(ofp,"\1ACUPDATE: MODIFY %s %08x\n", acup_a,acup_n); } } if (!(hdr((char *)"X-FTN-Tearline", msg)) && !(hdr((char *)"X-FTN-TID", msg))) { snprintf(temp, MAXHDRSIZE, " MBSE-FIDO %s (%s-%s)", VERSION, OsName(), OsCPU()); hdrsize += 4 + strlen(temp); fprintf(ofp, "\1TID:"); kludgewrite(temp, ofp); } if ((splitpart == 0) || (hdrsize < MAXHDRSIZE)) { for (tmp = msg; tmp; tmp = tmp->next) { if ((!strncmp(tmp->key,"X-Fsc-",6)) || (!strncmp(tmp->key,"X-FTN-",6) && strcasecmp(tmp->key,"X-FTN-Tearline") && strcasecmp(tmp->key,"X-FTN-Origin") && strcasecmp(tmp->key,"X-FTN-Sender") && strcasecmp(tmp->key,"X-FTN-Split") && strcasecmp(tmp->key,"X-FTN-FLAGS") && strcasecmp(tmp->key,"X-FTN-AREA") && strcasecmp(tmp->key,"X-FTN-MSGID") && strcasecmp(tmp->key,"X-FTN-REPLY") && strcasecmp(tmp->key,"X-FTN-SEEN-BY") && strcasecmp(tmp->key,"X-FTN-PATH") && strcasecmp(tmp->key,"X-FTN-REPLYADDR") && strcasecmp(tmp->key,"X-FTN-REPLYTO") && strcasecmp(tmp->key,"X-FTN-To") && strcasecmp(tmp->key,"X-FTN-From") && strcasecmp(tmp->key,"X-FTN-CHARSET") && strcasecmp(tmp->key,"X-FTN-CHRS") && strcasecmp(tmp->key,"X-FTN-CODEPAGE") && strcasecmp(tmp->key,"X-FTN-ORIGCHRS") && strcasecmp(tmp->key,"X-FTN-SOT") && strcasecmp(tmp->key,"X-FTN-EOT") && strcasecmp(tmp->key,"X-FTN-Via"))) { if ((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0)) { if (!strcasecmp(tmp->val," SOT:\n")) sot_kludge = TRUE; else if (!strcasecmp(tmp->val," EOT:\n")) eot_kludge = TRUE; else { hdrsize += strlen(tmp->val); fprintf(ofp,"\1"); /* we should have restored the original string here... */ kludgewrite((tmp->val)+1,ofp); } } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+6); kludgewrite(tmp->val,ofp); } } } /* ZConnect are X-ZC-*: in usenet, \1ZC-*: in FTN */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,"X-ZC-",5))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+2); kludgewrite(tmp->val,ofp); } /* mondo.org gateway uses ".MSGID: ..." in usenet */ for (tmp=msg;tmp;tmp=tmp->next) if ((!strncmp(tmp->key,".",1)) && (strcasecmp(tmp->key,".MSGID"))) { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1%s:",tmp->key+1); kludgewrite(tmp->val,ofp); } /* * Add the Received: header from this system to the mesage. */ if (!newsmode) { Now = time(NULL); fprintf(ofp, "\1RFC-Received: by %s (mbfido) via RFC2FTN; %s\n", CFG.sysdomain, rfcdate(Now)); hdrsize += 72+strlen(CFG.sysdomain); } for (tmp = msg; tmp; tmp = tmp->next) { if ((needputrfc(tmp, newsmode) == 1)) { if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"\1RFC-Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"\1RFC-%s:",tmp->key); } kludgewrite(tmp->val, ofp); } } rfcheaders=0; for (tmp=msg;tmp;tmp=tmp->next) { if ((needputrfc(tmp, newsmode) > 1)) { rfcheaders++; if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { hdrsize += 10+strlen(tmp->val); fprintf(ofp,"Newsgroups:"); } else { hdrsize += strlen(tmp->key)+strlen(tmp->val); fprintf(ofp,"%s:",tmp->key); } charwrite(tmp->val, ofp); } } if (rfcheaders) charwrite((char *)"\n",ofp); if ((hdr((char *)"X-FTN-SOT",msg)) || (sot_kludge)) fprintf(ofp,"\1SOT:\n"); } if (replyaddr) { replyaddr = NULL; } if (needsplit) { fprintf(ofp," * Continuation %d of a split message *\n\n", splitpart); needsplit = FALSE; } else if ((p=hdr((char *)"X-Body-Start",msg))) { datasize += strlen(p); charwrite(p, ofp); } while (!(needsplit=(!forbidsplit) && (((splitpart && (datasize > (CFG.new_split * 1024))) || (!splitpart && ((datasize+hdrsize) > (CFG.new_split * 1024)))))) && (bgets(temp,4096-1,fp))) { datasize += strlen(temp); charwrite(temp, ofp); } if (needsplit) { fprintf(ofp,"\n * Message split, to be continued *\n"); splitpart++; } if ((p=hdr((char *)"X-FTN-EOT",msg)) || (eot_kludge)) fprintf(ofp,"\1EOT:\n"); if ((p=hdr((char *)"X-FTN-Tearline",msg))) { fprintf(ofp,"---"); if (strcasecmp(p," (none)\n") == 0) charwrite((char *)"\n",ofp); else charwrite(p,ofp); } else fprintf(ofp,"\n%s\n", TearLine()); if ((p = hdr((char *)"X-FTN-Origin",msg))) { if (*(q=p+strlen(p)-1) == '\n') *q='\0'; origin = xstrcpy((char *)" * Origin: "); origin = xstrcat(origin, p); } else { origin = xstrcpy((char *)" * Origin: "); if (fmsg->origin) origin = xstrcat(origin, fmsg->origin); else origin = xstrcat(origin, CFG.origin); origin = xstrcat(origin, (char *)" ("); origin = xstrcat(origin, ascfnode(fmsg->from,tinyorigin?0x0f:0x1f)); origin = xstrcat(origin, (char *)")"); } fprintf(ofp, "%s", origin); if (newsmode) { /* * Setup SEEN-BY lines, first SEEN-BY from RFC message, then all matching AKA's */ for (tmsg = msg; tmsg; tmsg = tmsg->next) if (strcasecmp(tmsg->key, "X-FTN-SEEN-BY") == 0) fill_list(&sbl, tmsg->val, NULL); for (i = 0; i < 40; i++) { if (CFG.akavalid[i] && (CFG.aka[i].point == 0) && (msgs.Aka.zone == CFG.aka[i].zone) && !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { snprintf(sbe, 128, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); fill_list(&sbl, sbe, NULL); } } if (msgs.Aka.point == 0) { snprintf(sbe, 128, "%u/%u", msgs.Aka.net, msgs.Aka.node); fill_list(&sbl, sbe, NULL); } /* * Only add SEEN-BY lines if there are any */ if (sbl != NULL) { uniq_list(&sbl); sort_list(&sbl); seenlen = MAXSEEN + 1; memset(&sbe, 0, sizeof(sbe)); /* ensure it will not match for the first entry */ oldnet = sbl->addr->net-1; for (tmpl = sbl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,128," %u",tmpl->addr->node); else snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXSEEN) { seenlen = 0; fprintf(ofp,"\nSEEN-BY:"); snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&sbl); } /* * Setup PATH lines */ for (tmp = msg; tmp; tmp = tmp->next) if (!strcasecmp(tmp->key,"X-FTN-PATH")) fill_path(&ptl,tmp->val); if (msgs.Aka.point == 0) { snprintf(sbe,128,"%u/%u",msgs.Aka.net, msgs.Aka.node); fill_path(&ptl,sbe); } /* * Only add PATH line if there is something */ if (ptl != NULL) { uniq_list(&ptl); seenlen = MAXPATH+1; /* ensure it will not match for the first entry */ oldnet = ptl->addr->net-1; for (tmpl = ptl; tmpl; tmpl = tmpl->next) { if (tmpl->addr->net == oldnet) snprintf(sbe,128," %u",tmpl->addr->node); else snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); oldnet = tmpl->addr->net; seenlen += strlen(sbe); if (seenlen > MAXPATH) { seenlen = 0; fprintf(ofp,"\n\1PATH:"); snprintf(sbe,128," %u/%u",tmpl->addr->net, tmpl->addr->node); seenlen = strlen(sbe); } fprintf(ofp,"%s",sbe); } tidy_falist(&ptl); } } /* if (newsmode) */ /* * Add newline and message is ready. */ fprintf(ofp,"\n"); fflush(ofp); rewind(ofp); Syslog('m', "========== Fido start"); while (fgets(temp, 4096, ofp) != NULL) { /* * Only log kludges, skip the body */ if ((temp[0] == '\001') || !strncmp(temp, "AREA:", 5) || !strncmp(temp, "SEEN-BY", 7)) { Striplf(temp); Syslogp('m', printable(temp, 0)); } } Syslog('m', "========== Fido end"); if (newsmode) rc = postecho(NULL, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, 0, ofp, FALSE, 0); else rc = postnetmail(ofp, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, FALSE, fmsg->from->zone, fmsg->to->zone); Syslog('m', "rfc2ftn: message posted rc=%d", rc); free(origin); fclose(ofp); } while (needsplit); Syslog('m', "rfc2ftn: out of splitloop"); chartran_close(); free(temp); if (charset) free(charset); tidyrfc(msg); tidy_ftnmsg(fmsg); Syslog('m', "rfc2ftn: memory freed"); UpdateMsgs(); return 0; }
static void processNewArchiveRecord (HTML_WORK *work, WVIEW_MSG_ARCHIVE_NOTIFY *armsg) { HISTORY_DATA data; ARCHIVE_PKT arcRecord; int currHour, currDay, currMonth, currYear; float gmtOffsetHours; int startmin, starthour, startday, startmonth, startyear; int i, DSTFlag; int16_t tempShort; time_t ntime, baseTime; struct tm locTime; int deltaArchiveIntervals; // ... generate the mesonet file htmlgenMesonetFile (work->mgrId, armsg); // ... check to see if a DST change has occured DSTFlag = wvutilsDetectDSTChange(); if (DSTFlag != WVUTILS_DST_NO_CHANGE) { radMsgLog (PRI_STATUS, "DST change: updating astronomical times for new local time..."); ntime = time (NULL); localtime_r (&ntime, &locTime); currDay = locTime.tm_mday; currMonth = locTime.tm_mon + 1; currYear = locTime.tm_year + 1900; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif // ... update the sun times: sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); // restart the generation timer as the change may leave it in limbo radProcessTimerStart (work->timer, 5000L); } baseTime = time (NULL); // ... update our data by adding the new sample //// Interval change: // ... determine time to start for last sample startmin = wvutilsGetMin(armsg->dateTime); starthour = wvutilsGetHour(armsg->dateTime); startday = wvutilsGetDay(armsg->dateTime); startmonth = wvutilsGetMonth(armsg->dateTime); startyear = wvutilsGetYear(armsg->dateTime); currHour = starthour; currDay = startday; currMonth = startmonth; currYear = startyear; if (work->LastArchiveDateTime != 0) { // compute the number of archive intervals since the last good record deltaArchiveIntervals = armsg->dateTime - work->LastArchiveDateTime; deltaArchiveIntervals /= 60; if (deltaArchiveIntervals < work->archiveInterval) { // this is odd, report and bail out radMsgLog (PRI_MEDIUM, "processNewArchiveRecord: " "minutes since last archive record (%d) " "less than archive interval (%d) - " "ignoring record...", deltaArchiveIntervals, work->archiveInterval); return; } deltaArchiveIntervals /= work->archiveInterval; } else { deltaArchiveIntervals = 1; } work->LastArchiveDateTime = armsg->dateTime; if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, armsg->dateTime, 1) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for sample..."); } wvutilsLogEvent (PRI_STATUS, "Adding %d minute sample for %4.4d-%2.2d-%2.2d %2.2d:%2.2d...", work->archiveInterval, startyear, startmonth, startday, starthour, startmin); // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_SAMPLE; // add the RX check value to the data here data.values[DATA_INDEX_rxCheckPercent] = armsg->rxPercent; htmlmgrAddSampleValue (work->mgrId, &data, deltaArchiveIntervals); // generate an ASCII entry in the day's browser file (if enabled) if (dbsqliteArchiveGetRecord(armsg->dateTime, &arcRecord) == OK) { arcrecGenerate(&arcRecord, work->mgrId->isMetricUnits); } //// Hour change? if (work->histLastHour != currHour) { // determine times to start for last hour: ntime = time (NULL); localtime_r (&ntime, &locTime); locTime.tm_sec = 0; locTime.tm_min = work->archiveInterval; locTime.tm_hour = currHour; locTime.tm_mday = currDay; locTime.tm_mon = currMonth - 1; locTime.tm_year = currYear - 1900; locTime.tm_isdst = -1; ntime = mktime (&locTime); ntime -= WV_SECONDS_IN_HOUR; localtime_r (&ntime, &locTime); starthour = locTime.tm_hour; if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, ntime, WV_SECONDS_IN_HOUR/SECONDS_IN_INTERVAL(work->archiveInterval)) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for last hour..."); } wvutilsLogEvent (PRI_STATUS, "Adding hour sample..."); // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_HOUR; htmlmgrAddHourValue (work->mgrId, &data); work->histLastHour = currHour; } //// Day change? if (work->histLastDay != currDay) { // determine times to start for last day: // normalize packed time: ntime = time (NULL); localtime_r (&ntime, &locTime); locTime.tm_sec = 0; locTime.tm_min = work->archiveInterval; locTime.tm_hour = 0; locTime.tm_mday = currDay; locTime.tm_mon = currMonth - 1; locTime.tm_year = currYear - 1900; locTime.tm_isdst = -1; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif ntime = mktime (&locTime); ntime -= WV_SECONDS_IN_DAY; localtime_r (&ntime, &locTime); if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, ntime, WV_SECONDS_IN_DAY/SECONDS_IN_INTERVAL(work->archiveInterval)) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for last day..."); } else { // Add a day history record: wvutilsLogEvent(PRI_STATUS, "Storing day history for %s", ctime(&ntime)); dbsqliteHistoryInsertDay(&data); } // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_DAY; wvutilsLogEvent(PRI_STATUS, "Adding day sample..."); htmlmgrAddDayValue (work->mgrId, &data); work->histLastDay = currDay; // Start the timeout to do NOAA updates: radProcessTimerStart(work->noaaTimer, HTML_NOAA_UPDATE_DELAY); // ... update the sun times sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); } return; }
int htmlStationInfoState (int state, void *stimulus, void *data) { STIM *stim = (STIM *)stimulus; HTML_WORK *work = (HTML_WORK *)data; int seconds; WVIEW_MSG_STATION_INFO *msg = (WVIEW_MSG_STATION_INFO *)stim->msg; time_t ntime; struct tm locTime; long offset, msOffset; long oldSecs, newSecs; int currDay, currMonth, currYear; float gmtOffsetHours; int16_t tempShort; FILE* indicateFile; ntime = time (NULL); localtime_r (&ntime, &locTime); currDay = locTime.tm_mday; currMonth = locTime.tm_mon + 1; currYear = locTime.tm_year + 1900; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif switch (stim->type) { case STIM_QMSG: if (stim->msgType == WVIEW_MSG_TYPE_STATION_INFO) { radMsgRouterMessageDeregister(WVIEW_MSG_TYPE_STATION_INFO); ntime = msg->lastArcTime; localtime_r (&ntime, &locTime); radMsgLog (PRI_STATUS, "received station info from wviewd: " "%4.4d%2.2d%2.2d %2.2d:%2.2d:%2.2d", locTime.tm_year + 1900, locTime.tm_mon + 1, locTime.tm_mday, locTime.tm_hour, locTime.tm_min, locTime.tm_sec); work->archiveInterval = msg->archiveInterval; // Initialize the archive database interface: if (dbsqliteArchiveInit() == ERROR) { radMsgLog (PRI_HIGH, "dbsqliteArchiveInit failed"); statusUpdateMessage("dbsqliteArchiveInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the htmlMgr now that we know the archive interval: work->mgrId = htmlmgrInit (WVIEW_CONFIG_DIR, work->isMetricUnits, work->imagePath, work->htmlPath, work->archiveInterval, work->isExtendedData, work->stationName, work->stationCity, work->stationState, msg->elevation, msg->latitude, msg->longitude, work->mphaseIncrease, work->mphaseDecrease, work->mphaseFull, work->radarURL, work->forecastURL, work->dateFormat, work->isDualUnits); if (work->mgrId == NULL) { radMsgLog (PRI_HIGH, "htlmgrInit failed!"); statusUpdateMessage("htlmgrInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } wvstrncpy (work->mgrId->stationType, msg->stationType, sizeof(work->mgrId->stationType)); // ... initialize the sun times now sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); // ... initialize the barometric pressure trend algorithm: radMsgLog (PRI_STATUS, "initializing barometric pressure trend"); if (htmlmgrBPTrendInit (work->mgrId, work->timerInterval/60000) == ERROR) { radMsgLog (PRI_HIGH, "htmlmgrBPTrendInit failed!"); statusUpdateMessage("htmlmgrBPTrendInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // ... load up our historical stores for the history charts: radMsgLog (PRI_STATUS, "initializing historical stores (this may take some time...)"); if (htmlmgrHistoryInit (work->mgrId) == ERROR) { radMsgLog (PRI_HIGH, "htmlStationInfoState: htmlmgrHistoryInit failed!"); statusUpdateMessage("htmlmgrHistoryInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // store the "last" values ntime = time(NULL); localtime_r (&ntime, &locTime); work->histLastHour = locTime.tm_hour; work->histLastDay = locTime.tm_mday; // Initialize the HILOW database interface: // (this cannot occur before wviewd sends us the archive time) if (dbsqliteHiLowInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "dbsqliteHiLowInit failed!"); statusUpdateMessage("dbsqliteHiLowInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the NOAA database: if (dbsqliteNOAAInit() == ERROR) { radMsgLog (PRI_CATASTROPHIC, "dbsqliteNOAAInit failed!"); statusUpdateMessage("dbsqliteNOAAInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the NOAA report generator radMsgLog (PRI_STATUS, "NOAA: initializing reports (this may take some time...)"); work->noaaId = noaaGenerateInit (work->mgrId->imagePath, work->isMetricUnits, msg->latitude, msg->longitude, msg->elevation, work->stationName, work->stationCity, work->stationState, msg->lastArcTime); if (work->noaaId == NULL) { radMsgLog (PRI_CATASTROPHIC, "noaaGenerateInit failed!"); statusUpdateMessage("noaaGenerateInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the archive record browser generator radMsgLog (PRI_STATUS, "ARCREC: initializing archive browser files (this may take some time...)"); if (arcrecGenerateInit (work->mgrId->imagePath, work->arcrecDaysToKeep, work->isMetricUnits, work->archiveInterval) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "arcrecGenerateInit failed!"); statusUpdateMessage("arcrecGenerateInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initial data request then start the data acquisition timer if (requestDataPackets (work) == ERROR) { radMsgLog (PRI_HIGH, "htmlStationInfoState: requestDataPackets failed!"); statusUpdateMessage("requestDataPackets failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } radProcessTimerStart (work->rxTimer, HTML_RX_PACKETS_TIMEOUT); // wait here until a new second arrives ntime = time (NULL); localtime_r (&ntime, &locTime); oldSecs = newSecs = locTime.tm_sec; while (oldSecs == newSecs) { ntime = time (NULL); localtime_r (&ntime, &locTime); newSecs = locTime.tm_sec; } /* ... start the data timer to go off at the next 5 minute ... interval plus the user offset */ ntime = time (NULL); localtime_r (&ntime, &locTime); seconds = locTime.tm_sec - 10L; // start at 10 secs past offset = locTime.tm_min % 5L; // where are we in period? offset = 5 - offset; // how many mins to get to "0"? offset %= 5; // don't want "5" offset += work->startOffset; // user start in period if (offset == 0L) // prevent negative timeout seconds -= 60L; // make neg so timeout is pos if (seconds < -60L) { offset += 1L; seconds += 60L; } radMsgLog (PRI_STATUS, "starting html generation in %d mins %d secs", ((seconds > 0L) ? ((offset > 0L) ? offset - 1L : offset) : offset), (seconds > 0L) ? 60L - seconds : (-1L) * seconds); work->nextGenerationTime.tv_sec = (long)ntime + ((offset * 60L) - seconds); work->nextGenerationTime.tv_usec = 250L * 1000L; msOffset = 250L; // land on 250 ms mark radProcessTimerStart (work->timer, ((((offset * 60L) - seconds) * 1000L)) + msOffset); // 20041224 - Add an immediate generation cycle so longer // duration archive intervals don't have to wait up to 30 minutes // for the first generation radMsgLog (PRI_STATUS, "doing initial html generation now..."); work->numDataReceived = 0; statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); // Save an indicator in the run directory so web apps know when we are up: indicateFile = fopen (work->indicateFile, "w"); if (indicateFile == NULL) { radMsgLog (PRI_CATASTROPHIC, "indicator file create failed!"); statusUpdateMessage("indicator file create failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } fprintf (indicateFile, "%d", (int)msg->lastArcTime); fclose (indicateFile); return HTML_STATE_DATA; } break; } return state; }
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; }
/* * Start a netmail to one of our nodes in the setup. * Return a file descriptor if success else NULL. * Later the pack routine will add these mails to the outbound. */ FILE *SendMgrMail(faddr *t, int Keep, int FileAttach, char *bymgr, char *subj, char *reply) { FILE *qp; time_t Now; fidoaddr Orig, Dest; faddr From; unsigned flags = M_PVT; char ext[4]; From = *bestaka_s(t); memset(&Orig, 0, sizeof(Orig)); Orig.zone = From.zone; Orig.net = From.net; Orig.node = From.node; Orig.point = From.point; snprintf(Orig.domain, 13, "%s", From.domain); memset(&Dest, 0, sizeof(Dest)); Dest.zone = t->zone; Dest.net = t->net; Dest.node = t->node; Dest.point = t->point; snprintf(Dest.domain, 13, "%s", t->domain); if (!SearchNode(Dest)) { Syslog('!', "SendMgrMail(): Can't find node %s", aka2str(Dest)); return NULL; } Syslog('m', " Netmail from %s to %s", aka2str(Orig), ascfnode(t, 0x1f)); Now = time(NULL) - (gmt_offset((time_t)0) * 60); flags |= (nodes.Crash) ? M_CRASH : 0; flags |= (FileAttach) ? M_FILE : 0; flags |= (nodes.Hold) ? M_HOLD : 0; /* * Increase counters, update record and reload. */ StatAdd(&nodes.MailSent, 1L); UpdateNode(); SearchNode(Dest); memset(&ext, 0, sizeof(ext)); if (nodes.PackNetmail) snprintf(ext, 4, (char *)"qqq"); else if (nodes.Crash) snprintf(ext, 4, (char *)"ccc"); else if (nodes.Hold) snprintf(ext, 4, (char *)"hhh"); else snprintf(ext, 4, (char *)"nnn"); if ((qp = OpenPkt(Orig, Dest, (char *)ext)) == NULL) return NULL; if (AddMsgHdr(qp, &From, t, flags, 0, Now, nodes.Sysop, tlcap(bymgr), subj)) { fclose(qp); return NULL; } if (Dest.point) fprintf(qp, "\001TOPT %d\r", Dest.point); if (Orig.point) fprintf(qp, "\001FMPT %d\r", Orig.point); fprintf(qp, "\001INTL %d:%d/%d %d:%d/%d\r", Dest.zone, Dest.net, Dest.node, Orig.zone, Orig.net, Orig.node); /* * Add MSGID, REPLY and PID */ fprintf(qp, "\001MSGID: %s %08x\r", aka2str(Orig), sequencer()); if (reply != NULL) fprintf(qp, "\001REPLY: %s\r", reply); fprintf(qp, "\001PID: MBSE-FIDO %s (%s-%s)\r", VERSION, OsName(), OsCPU()); fprintf(qp, "\001TZUTC: %s\r", gmtoffset(Now)); return qp; }