/* Copyright 2001-2018 John Wiseman G8BPQ This file is part of LinBPQ/BPQ32. LinBPQ/BPQ32 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 3 of the License, or (at your option) any later version. LinBPQ/BPQ32 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 LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ // Mail and Chat Server for BPQ32 Packet Switch // // lzhuf Routines #include "bpqmail.h" BOOL isAMPRMsg(char * Addr); struct Country * FindCountry(char * Name); struct UserInfo * FindAMPR(); /************************************************************** lzhuf.c written by Haruyasu Yoshizaki 1988/11/20 some minor changes 1989/04/06 comments translated by Haruhiko Okumura 1989/04/07 getbit and getbyte modified 1990/03/23 by Paul Edwards so that they would work on machines where integers are not necessarily 16 bits (although ANSI guarantees a minimum of 16). This program has compiled and run with no errors under Turbo C 2.0, Power C, and SAS/C 4.5 (running on an IBM mainframe under MVS/XA 2.2). Could people please use YYYY/MM/DD date format so that everyone in the world can know what format the date is in? external storage of filesize changed 1990/04/18 by Paul Edwards to Intel's "little endian" rather than a machine-dependant style so that files produced on one machine with lzhuf can be decoded on any other. "little endian" style was chosen since lzhuf originated on PC's, and therefore they should dictate the standard. initialization of something predicting spaces changed 1990/04/22 by Paul Edwards so that when the compressed file is taken somewhere else, it will decode properly, without changing ascii spaces to ebcdic spaces. This was done by changing the ' ' (space literal) to 0x20 (which is the far most likely character to occur, if you don't know what environment it will be running on. **************************************************************/ int ReformatSyncMessage(CIRCUIT * conn); #define int __int16 /* crctab calculated by Mark G. Mendel, Network Systems Corporation */ UCHAR *infile, *outfile, * endinfile; short Get() { if (infile == endinfile) return -1; else return *(infile++); } static unsigned short crctab[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; #define updcrc(cp, crc) ((crc << 8) ^ crctab[(cp & 0xff) ^ (crc >> 8)]) uint32_t textsize = 0, codesize = 0; unsigned short crc; int version_1; char wterr[] = "Can't write."; void Error(char *message) { printf("\n%s\n", message); exit(EXIT_FAILURE); } /********** LZSS compression **********/ #define N 2048 /* buffer size */ #define F 60 /* lookahead buffer size */ #define THRESHOLD 2 #define NIL N /* leaf of tree */ unsigned char text_buf[N + F - 1]; static int match_position, match_length, lson[N + 1], rson[N + 257], dad[N + 1]; static int crc_fputc(unsigned short c) { crc = updcrc(c, crc); *(outfile++) = (unsigned char)c; return 0; } short crc_fgetc() { short retour = *(infile++); return(retour); } void InitTree(void) /* initialize trees */ { int i; for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; /* root */ for (i = 0; i < N; i++) dad[i] = NIL; /* node */ } static void InsertNode(int r) /* insert to tree */ { int i, p, cmp; unsigned char *key; unsigned c; cmp = 1; key = &text_buf[r]; p = N + 1 + key[0]; rson[r] = lson[r] = NIL; match_length = 0; for ( ; ; ) { if (cmp >= 0) { if (rson[p] != NIL) p = rson[p]; else { rson[p] = r; dad[r] = p; return; } } else { if (lson[p] != NIL) p = lson[p]; else { lson[p] = r; dad[r] = p; return; } } for (i = 1; i < F; i++) if ((cmp = key[i] - text_buf[p + i]) != 0) break; if (i > THRESHOLD) { if (i > match_length) { match_position = ((r - p) & (N - 1)) - 1; if ((match_length = i) >= F) break; } if (i == match_length) { if ((c = ((r - p) & (N-1)) - 1) < (unsigned)match_position) { match_position = c; } } } } dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p]; dad[lson[p]] = r; dad[rson[p]] = r; if (rson[dad[p]] == p) rson[dad[p]] = r; else lson[dad[p]] = r; dad[p] = NIL; /* remove p */ } static void DeleteNode(int p) /* remove from tree */ { int q; if (dad[p] == NIL) return; /* not registered */ if (rson[p] == NIL) q = lson[p]; else if (lson[p] == NIL) q = rson[p]; else { q = lson[p]; if (rson[q] != NIL) { do { q = rson[q]; } while (rson[q] != NIL); rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q]; lson[q] = lson[p]; dad[lson[p]] = q; } rson[q] = rson[p]; dad[rson[p]] = q; } dad[q] = dad[p]; if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q; dad[p] = NIL; } /* Huffman coding */ #define N_CHAR (256 - THRESHOLD + F) /* kinds of characters (character code = 0..N_CHAR-1) */ #define T (N_CHAR * 2 - 1) /* size of table */ #define R (T - 1) /* position of root */ #define MAX_FREQ 0x8000 /* updates tree when the */ /* root frequency comes to this value. */ typedef unsigned char uchar; /* table for encoding and decoding the upper 6 bits of position */ /* for encoding */ uchar p_len[64] = { 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }; uchar p_code[64] = { 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; /* for decoding */ uchar d_code[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, }; uchar d_len[256] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }; unsigned int freq[T + 1]; /* frequency table */ int prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */ /* elements [T..T + N_CHAR - 1] which are used to get */ /* the positions of leaves corresponding to the codes. */ int son[T]; /* pointers to child nodes (son[], son[] + 1) */ unsigned int getbuf = 0; uchar getlen = 0; static int GetBit(void) /* get one bit */ { unsigned int i; while (getlen <= 8) { if ((i = crc_fgetc()) < 0) i = 0; getbuf |= i << (8 - getlen); getlen += 8; } i = getbuf; getbuf <<= 1; getlen--; return (int)((i & 0x8000) >> 15); } static int GetByte(void) /* get one byte */ { unsigned int i; while (getlen <= 8) { if ((i = crc_fgetc()) == 0xffff) i = 0; getbuf |= i << (8 - getlen); getlen += 8; } i = getbuf; getbuf <<= 8; getlen -= 8; return (int)((i & 0xff00) >> 8); } unsigned int putbuf = 0; uchar putlen = 0; static void Putcode(int l, unsigned c) /* output c bits of code */ { putbuf |= c >> putlen; if ((putlen += l) >= 8) { if (crc_fputc(putbuf >> 8) == EOF) { Error(wterr); } if ((putlen -= 8) >= 8) { if (crc_fputc(putbuf) == EOF) { Error(wterr); } codesize += 2; putlen -= 8; putbuf = c << (l - putlen); } else { putbuf <<= 8; codesize++; } } } /* initialization of tree */ int StartHuff(void) { int i, j; for (i = 0; i < N_CHAR; i++) { freq[i] = 1; son[i] = i + T; prnt[i + T] = i; } i = 0; j = N_CHAR; while (j <= R) { freq[j] = freq[i] + freq[i + 1]; son[j] = i; prnt[i] = prnt[i + 1] = j; i += 2; j++; } freq[T] = 0xffff; prnt[R] = 0; return 0; } /* reconstruction of tree */ static void reconst(void) { int i, j, k; unsigned int f, l; /* collect leaf nodes in the first half of the table */ /* and replace the freq by (freq + 1) / 2. */ j = 0; for (i = 0; i < T; i++) { if (son[i] >= T) { freq[j] = (freq[i] + 1) / 2; son[j] = son[i]; j++; } } /* begin constructing tree by connecting sons */ for (i = 0, j = N_CHAR; j < T; i += 2, j++) { k = i + 1; f = freq[j] = freq[i] + freq[k]; for (k = j - 1; f < freq[k]; k--); k++; l = (j - k) * 2; memmove(&freq[k + 1], &freq[k], l); freq[k] = f; memmove(&son[k + 1], &son[k], l); son[k] = i; } /* connect prnt */ for (i = 0; i < T; i++) { if ((k = son[i]) >= T) { prnt[k] = i; } else { prnt[k] = prnt[k + 1] = i; } } } /* increment frequency of given code by one, and update tree */ static void update(int c) { int i, j, l; unsigned int k; if (freq[R] == MAX_FREQ) { reconst(); } c = prnt[c + T]; do { k = ++freq[c]; /* if the order is disturbed, exchange nodes */ l = c + 1; if ((unsigned)k > freq[l]) { while ((unsigned)k > freq[++l]); l--; freq[c] = freq[l]; freq[l] = k; i = son[c]; prnt[i] = l; if (i < T) prnt[i + 1] = l; j = son[l]; son[l] = i; prnt[j] = c; if (j < T) prnt[j + 1] = c; son[c] = j; c = l; } } while ((c = prnt[c]) != 0); /* repeat up to root */ } unsigned code, len; static void EncodeChar(unsigned int c) { unsigned int i; int j, k; i = 0; j = 0; k = prnt[c + T]; /* travel from leaf to root */ do { i >>= 1; /* if node's address is odd-numbered, choose bigger brother node */ if (k & 1) i += 0x8000; j++; } while ((k = prnt[k]) != R); Putcode(j, i); code = i; len = j; update(c); } static void EncodePosition(unsigned int c) { unsigned int i; /* output upper 6 bits by table lookup */ i = c >> 6; Putcode(p_len[i], (unsigned)p_code[i] << 8); /* output lower 6 bits verbatim */ Putcode(6, (c & 0x3f) << 10); } static void EncodeEnd(void) { if (putlen) { if (crc_fputc(putbuf >> 8) == EOF) { Error(wterr); } codesize++; } } int DecodeChar(void) { unsigned int c; c = son[R]; /* travel from root to leaf, */ /* choosing the smaller child node (son[]) if the read bit is 0, */ /* the bigger (son[]+1} if 1 */ while (c < T) { c += GetBit(); c = son[c]; } c -= T; update(c); return (int)c; } int DecodePosition(void) { unsigned int i, j, c; /* recover upper 6 bits from table */ i = GetByte(); c = (unsigned)d_code[i] << 6; j = d_len[i]; /* read lower 6 bits verbatim */ j -= 2; while (j--) { i = (i << 1) + GetBit(); } return (int)(c | (i & 0x3f)); } /* compression */ int32_t Encode(char * in, char * out, int32_t inlen, BOOL B1Protocol, int Compress) { int i, c, len, r, s, last_match_length; unsigned char *ptr; putbuf = 0; putlen = 0; textsize = 0; codesize = 0; crc = 0; outfile = out; if (B1Protocol) outfile+=2; // Space for CRC // infile = &conn->MailBuffer[2]; textsize = inlen; ptr = (char *)&textsize; #ifdef __BIG_ENDIAN__ crc_fputc(*(ptr+3)); crc_fputc(*(ptr+2)); crc_fputc(*(ptr+1)); crc_fputc(*(ptr)); #else crc_fputc(*(ptr++)); crc_fputc(*(ptr++)); crc_fputc(*(ptr++)); crc_fputc(*(ptr++)); #endif if (textsize == 0) return 0; infile = in; endinfile = infile + inlen; textsize = 0; /* rewind and re-read */ // if using uncompressed just copy in to out // may not be optimum but is simple! if (Compress) { StartHuff(); InitTree(); s = 0; r = N - F; for (i = s; i < r; i++) text_buf[i] = 0x20; for (len = 0; len < F && (c = Get()) != EOF; len++) text_buf[r + len] = (unsigned char)c; textsize = len; for (i = 1; i <= F; i++) InsertNode(r - i); InsertNode(r); do { if (match_length > len) match_length = len; if (match_length <= THRESHOLD) { match_length = 1; EncodeChar(text_buf[r]); } else { EncodeChar(255 - THRESHOLD + match_length); EncodePosition(match_position); } last_match_length = match_length; for (i = 0; i < last_match_length && (c = Get()) != EOF; i++) { DeleteNode(s); text_buf[s] = (unsigned char)c; if (s < F - 1) text_buf[s + N] = (unsigned char)c; s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); InsertNode(r); } while (i++ < last_match_length) { DeleteNode(s); s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); if (--len) InsertNode(r); } } while (len > 0); EncodeEnd(); } else { int32_t n = inlen; while (n--) crc_fputc(*(infile++)); codesize += inlen; } if (B1Protocol) { out[0] = crc & 0xff; out[1]= crc >> 8; codesize+=2; } codesize += 4; if (Compress) Logprintf(LOG_BBS, NULL, '|', "Compressed Message Comp Len %d Msg Len %d CRC %x", codesize, inlen, crc); else Logprintf(LOG_BBS, NULL, '|', "Uncompressed Message Sent Len %d Msg Len %d CRC %x", codesize, inlen, crc); return codesize; } BOOL CheckifPacket(char * Via) { char * ptr1, * ptr2; // Message addressed to a non-winlink address // Need to see if real smtp, or a packet address // No . in address assume Packet - g8bpq@g8bpq ptr1 = strchr(Via, '.'); if (ptr1 == NULL) return TRUE; // Packet // Find Last Element ptr2 = strchr(++ptr1, '.'); while (ptr2) { ptr1 = ptr2; ptr2 = strchr(++ptr1, '.'); } if (ptr1[0] == 0) return TRUE; // Packet // ptr1 is last element. If a valid continent, it is a packet message if (FindContinent(ptr1)) return TRUE; // Packet if (FindCountry(ptr1)) return TRUE; // Packet if ((_stricmp(ptr1, "MARS") == 0) || (_stricmp(ptr1, "USA") == 0)) // MARS used both return TRUE; // Packet return FALSE; } void Decode(CIRCUIT * conn, int FromSync) { unsigned char *ptr; char * StartofMsg; short i, j, k, r; short c; uint32_t count; unsigned short crc_read; int Index = 0; struct FBBHeaderLine * FBBHeader= &conn->FBBHeaders[0]; // The Headers from an FFB forward block BOOL NTS = FALSE; getbuf = 0; getlen = 0; textsize = 0; codesize = 0; infile = &conn->MailBuffer[0]; crc = 0; if (conn->BBSFlags & FBBB1Mode) { short val; uint32_t n; crc_read = infile[0]; crc_read |= infile[1] << 8; for (n = 2; n < conn->TempMsg->length; n++) { val = infile[n]; crc = updcrc(val, crc); } if (crc != crc_read) { nodeprintf(conn, "*** Message CRC Error File %x Calc %x\r", crc_read, crc); free(conn->MailBuffer); conn->MailBufferSize=0; conn->MailBuffer=0; conn->CloseAfterFlush = 20; // 2 Secs return; } infile+=2; } textsize = 0; ptr = (char *)&textsize; #ifdef __BIG_ENDIAN__ ptr[3] = (unsigned char)crc_fgetc(); ptr[2] = (unsigned char)crc_fgetc(); ptr[1] = (unsigned char)crc_fgetc(); ptr[0] = (unsigned char)crc_fgetc(); #else for (i = 0 ; i < sizeof(textsize) ; i++) ptr[i] = (unsigned char)crc_fgetc(); #endif // Temp fix for duff MACBPQ (Message Length sent big-endian) if (textsize > 500000) { char x[4]; char y[4]; memcpy(x, &textsize, 4); y[0] = x[3]; y[1] = x[2]; y[2] = x[1]; y[3] = x[0]; memcpy(&textsize, y, 4); if (textsize > 5000000) { nodeprintf(conn, "*** Message Size Invalid %d\r", textsize); Debugprintf("*** Message Size Invalid %d\r", textsize); free(conn->MailBuffer); conn->MailBufferSize=0; conn->MailBuffer=0; conn->CloseAfterFlush = 20; // 2 Secs return; } } Logprintf(LOG_BBS, conn, '|', "Uncompressing Message Comp Len %d Msg Len %d CRC %x", conn->TempMsg->length, textsize, crc); outfile = zalloc(textsize + 10000); // Lots of space for B2 header manipulations if (textsize == 0) return; // If compressed, decompress if (conn->BBSFlags & FBBCompressed) { StartHuff(); for (i = 0; i < N - F; i++) text_buf[i] = 0x20; r = N - F; for (count = 0; count < textsize; ) { c = DecodeChar(); if (c < 256) { *(outfile++) = (unsigned char)c; text_buf[r++] = (unsigned char)c; r &= (N - 1); count++; } else { i = (r - DecodePosition() - 1) & (N - 1); j = c - 255 + THRESHOLD; for (k = 0; k < j; k++) { c = text_buf[(i + k) & (N - 1)]; *(outfile++) = (unsigned char)c; text_buf[r++] = (unsigned char)c; r &= (N - 1); count++; } } } outfile -=count; } else { count = textsize; memcpy(outfile, infile, textsize); } free(conn->MailBuffer); conn->MailBuffer = outfile; conn->TempMsg->length = count; if (FromSync) { // Refomat Sync message as if from WLE if (ReformatSyncMessage(conn) == 0) return; FBBHeader->B2Message = TRUE; FBBHeader->MsgType = 'P'; } if (!FBBHeader->B2Message) { // With B2 the Type is specified in the body, so can't update stats now if (FBBHeader->MsgType == 'P') Index = PMSG; else if (FBBHeader->MsgType == 'B') Index = BMSG; else if (FBBHeader->MsgType == 'T') Index = TMSG; conn->UserPointer->Total.MsgsReceived[Index]++; conn->UserPointer->Total.BytesForwardedIn[Index] += count; } if (FBBHeader->B2Message) { // Parse the Message for B2 From and To info /* MID: A3EDD4P00P55 Date: 2009/07/25 10:08 Type: Private From: SMTP:john.wiseman@ntlworld.com To: G8BPQ Subject: RE: RMS Test Messaage Mbo: SMTP Body: 214 File: 3556 NOLA.XLS File: 5566 NEWBOAT.HOMEPORT.JPG */ UCHAR * ptr1, * ptr2, * ptr3; __int32 linelen, MsgLen = 0; struct MsgInfo * Msg = conn->TempMsg; time_t Date; char FullTo[100]; char FullFrom[100]; char ** RecpTo = NULL; // May be several Recipients char ** HddrTo = NULL; // May be several Recipients char ** Via = NULL; // May be several Recipients __int32 LocalMsg[1000]; // Set if Recipient is a local wl2k address char Type[1000]; // Message Type for each dest __int32 B2To; // Offset to To: fields in B2 header __int32 Recipients = 0; __int32 RMSMsgs = 0, BBSMsgs = 0; #ifndef LINBPQ struct _EXCEPTION_POINTERS exinfo; __try { #endif Msg->B2Flags |= B2Msg; // Display the whole header for debugging /* ptr1 = strstr(outfile, "\r\n\r\n"); if (ptr1) { *ptr1 = 0; Debugprintf("B2 Header = %s", outfile); *ptr1 = '\r'; } */ if (_stricmp(conn->Callsign, "RMS") == 0) Msg->B2Flags |= FromCMS; if (conn->RadioOnlyMode == 'T') Msg->B2Flags |= RadioOnlyMsg; else if (conn->RadioOnlyMode == 'R') Msg->B2Flags |= RadioOnlyFwd; ptr1 = outfile; Loop: ptr2 = strchr(ptr1, '\r'); linelen = (int)(ptr2 - ptr1); if (_memicmp(ptr1, "From:", 5) == 0) { memcpy(FullFrom, ptr1, linelen); FullFrom[linelen] = 0; if (conn->Paclink || (conn->RMSExpress && (conn->UserPointer->flags & F_NOWINLINK) == 0)) { // Messages just have the call - need to add @winlink.org strcpy(Msg->emailfrom, "@winlink.org"); } if (_memicmp(&ptr1[6], "smtp:", 5) == 0) { if (_stricmp(conn->Callsign, "RMS") == 0) { // Swap smtp: to rms: and save originator so we can reply via RMS strcpy(Msg->from, "RMS:"); memcpy(Msg->emailfrom, &ptr1[11], linelen - 11); } else { strcpy(Msg->from, "SMTP:"); memcpy(Msg->emailfrom, &ptr1[11], linelen - 11); } } else { char SaveFrom[100]; char * FromHA; // B2 From may now contain an @BBS strcpy(SaveFrom, FullFrom); FromHA = strlop(SaveFrom, '@'); // If it has an @ it could be an internet address - if it has a dot or longer than // 6 chars assume it is. // No, could also be packet // I don't think you can have an Internet message without a . in @field // Why not just use checkifpacket ?? if (FromHA && !CheckifPacket(FromHA)) { // Internet address - set from empty and full email in // emailfrom strcpy(Msg->from, "SMTP:"); if (strlen(FullFrom) > 46) FullFrom[46] = 0; strcpy(Msg->emailfrom, &FullFrom[6]); } else { // Not an Internet Address so must be a callsign and therefore <= 6 chars if (strlen(SaveFrom) > 12) SaveFrom[12] = 0; strcpy(Msg->from, &SaveFrom[6]); if (FromHA) { if (strlen(FromHA) > 39) FromHA[39] = 0; Msg->emailfrom[0] = '@'; strcpy(&Msg->emailfrom[1], _strupr(FromHA)); } } // Remove any SSID ptr3 = strchr(Msg->from, '-'); if (ptr3) *ptr3 = 0; } // If from a CMS, and no @ in message, append @winlink.org to the B2 Header. // so messages passed via B2 know it is from Winlink if ((Msg->B2Flags & FromCMS) && strchr(FullFrom, '@') == NULL) { // Move Message down buffer - ptr2 is the insertion point memmove(ptr2+12, ptr2, count); memcpy(ptr2, "@winlink.org", 12); count += 12; conn->TempMsg->length += 12; // Also set Emailfrom, in case read on BBS (eg by outpost) strcat(Msg->emailfrom, "@winlink.org"); } } else if (_memicmp(ptr1, "To:", 3) == 0 || _memicmp(ptr1, "cc:", 3) == 0) { int toLen; HddrTo=realloc(HddrTo, (Recipients+1) * sizeof(void *)); HddrTo[Recipients] = zalloc(100); memset(FullTo, 0, 99); memcpy(FullTo, &ptr1[4], linelen-4); memcpy(HddrTo[Recipients], ptr1, linelen+2); LocalMsg[Recipients] = FALSE; Type[Recipients] = Msg->type; // Default to Type from Header Logprintf(LOG_BBS, conn, '?', "B2 Msg To: %s", FullTo); conn->TempMsg->length -= (int)strlen(HddrTo[Recipients]); B2To = (int)(ptr1 - outfile); // if ending in AMPR.ORG send via ISP if we have enabled forwarding AMPR toLen = (int)strlen(FullTo); if (_memicmp(&FullTo[toLen - 8], "ampr.org", 8) == 0) { // if our domain keep here. // if not, and SendAMPRDirect set, set as ISP, // else set as RMS memcpy(Msg->via, FullTo, toLen); ptr3 = strchr(FullTo, '@'); if (ptr3) { ptr3++; if (_stricmp(ptr3, AMPRDomain) == 0) { // Our Message strcpy(Msg->via, FullTo); BBSMsgs ++; goto BBSMsg; } } if (SendAMPRDirect && FindAMPR()) { strcpy(Msg->via, FullTo); strcpy(FullTo,"AMPR"); BBSMsgs ++; goto BBSMsg; } strcpy(FullTo,"RMS"); RMSMsgs ++; } if (conn->BPQBBS && !CheckifPacket(FullTo)) // May be an message for RMS being passed to an intermediate BBS { // Internet address - send via RMS strcpy(Msg->via, FullTo); strcpy(FullTo,"RMS"); RMSMsgs ++; } else { ptr3 = strchr(FullTo, '@'); if (ptr3) { *ptr3++ = 0; strcpy(Msg->via, ptr3); } else Msg->via[0] = 0; } if (conn->Paclink) { Msg->B2Flags |= FromPaclink; // Message from paclink // Messages to WL2K just have call. // Messages to email or BBS addresses have smtp: if (_memicmp(&ptr1[4], "SMTP:", 5) == 0) { // See if Packet or SMTP if (CheckifPacket(Msg->via)) // If no RMS, don't check for routing to it) { // Packet Message memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); _strupr(FullTo); _strupr(Msg->via); // Update the saved to: line (remove the smtp:) strcpy(&HddrTo[Recipients][4], &HddrTo[Recipients][9]); BBSMsgs++; } else { // Internet address - do we send via RMS?? // ??? Need to see if RMS is available memcpy(Msg->via, &ptr1[9], linelen); Msg->via[linelen-9] = 0; strcpy(FullTo,"RMS"); RMSMsgs ++; } } else { if (conn->RadioOnlyMode == 0 && (conn->UserPointer->flags & F_NOWINLINK) == 0) // treat as Packet Address? { strcpy(Msg->via, "winlink.org"); // Message for WL2K - add via RMSMsgs ++; LocalMsg[Recipients] = CheckifLocalRMSUser(FullTo); } else { BBSMsgs++; } } } // else if (conn->RMSExpress && FindRMS()) // If no RMS, don't check for routing to it else if (conn->RMSExpress) { Msg->B2Flags |= FromRMSExpress; // Message from RMS Express // Messages to WL2K just have call. // Messages to email or BBS addresses don't have smtp: if (Msg->via[0]) { // Has an @ - See if Packet or SMTP. If to our AMPR address, treat as packet if (CheckifPacket(Msg->via) || _stricmp(Msg->via, AMPRDomain) == 0) { // Packet Message _strupr(FullTo); _strupr(Msg->via); BBSMsgs++; } else { // Internet address - do we send via RMS?? if (_memicmp(FullTo, "smtp/", 5) == 0 && ISP_Gateway_Enabled) { memcpy(Msg->via, &ptr1[9], linelen - 9); Msg->via[linelen-9] = 0; FullTo[0] = Msg->to[0] = 0; } else if (FindRMS()) // have RMS { memcpy(Msg->via, &ptr1[4], linelen); Msg->via[linelen-4] = 0; strcpy(FullTo,"RMS"); RMSMsgs ++; } else if (ISP_Gateway_Enabled) { memcpy(Msg->via, &ptr1[4], linelen); Msg->via[linelen-4] = 0; FullTo[0] = Msg->to[0] = 0; } else if (isAMPRMsg(Msg->via)) strcpy(Msg->to, "RMS"); // Routing will redirect it } } else { if (conn->RadioOnlyMode == 0 && (conn->UserPointer->flags & F_NOWINLINK) == 0) // Dont default to winlink.org { strcpy(Msg->via, "winlink.org"); // Message for WL2K - add via RMSMsgs ++; LocalMsg[Recipients] = CheckifLocalRMSUser(FullTo); } else goto BBSMsg; } } else // Not Paclink or RMS Express (or no RMS) { if (_memicmp(&ptr1[4], "SMTP:", 5) == 0) { // Airmail Sends MARS messages as SMTP if (CheckifPacket(Msg->via)) { // Packet Message memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); _strupr(FullTo); _strupr(Msg->via); // Update the saved to: line (remove the smtp:) strcpy(&HddrTo[Recipients][4], &HddrTo[Recipients][9]); BBSMsgs++; goto BBSMsg; } // If a winlink.org address we need to convert to call if (_stricmp(Msg->via, "winlink.org") == 0) { memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); _strupr(FullTo); LocalMsg[Recipients] = CheckifLocalRMSUser(FullTo); } else { memcpy(Msg->via, &ptr1[9], linelen); Msg->via[linelen - 9] = 0; strcpy(FullTo,"RMS"); } // FullTo[0] = 0; } else { BBSMsg: _strupr(FullTo); _strupr(Msg->via); } } if (memcmp(FullTo, "RMS:", 4) == 0) { // remove RMS and add @winlink.org memmove(FullTo, &FullTo[4], strlen(FullTo) - 3); strcpy(Msg->via, "winlink.org"); sprintf(HddrTo[Recipients], "To: %s\r\n", FullTo); } else if (memcmp(FullTo, "NTS:", 4) == 0) { // remove NTS and set type 'T' memmove(FullTo, &FullTo[4], strlen(FullTo) - 3); Type[Recipients] = 'T'; // NTS memmove(HddrTo[Recipients] + 4, HddrTo[Recipients] + 8, 91); // Replace Type: Private with Type: Traffic } else if ((_memicmp(FullTo, "bull/", 5) == 0) || (_memicmp(FullTo, "bull:", 5) == 0)) { // remove bull/ and set type 'B' memmove(FullTo, &FullTo[5], strlen(FullTo) - 4); Type[Recipients] = 'B'; // Bulletin memmove(HddrTo[Recipients] + 4, HddrTo[Recipients] + 9, 90); // Replace Type: Private with Type: Bulletin // Have to move rest of header down to make space } if (strcmp(Msg->via, "RMS") == 0) { // replace RMS with @winlink.org strcpy(Msg->via, "winlink.org"); sprintf(HddrTo[Recipients], "To: %s@winlink.org\r\n", FullTo); } if (strlen(FullTo) > 6) FullTo[6] = 0; strlop(FullTo, '-'); strcpy(Msg->to, FullTo); if (SendBBStoSYSOPCall) if (_stricmp(FullTo, BBSName) == 0) strcpy(Msg->to, SYSOPCall); if ((Msg->via[0] == 0 || strcmp(Msg->via, "BPQ") == 0 || strcmp(Msg->via, "BBS") == 0) && (conn->Paclink || conn->RMSExpress)) { // No routing - check @BBS and WP struct UserInfo * ToUser = LookupCall(FullTo); Msg->via[0] = 0; // In case BPQ and not found if (ToUser) { // Local User. If Home BBS is specified, use it if (ToUser->HomeBBS[0]) { strcpy(Msg->via, ToUser->HomeBBS); } } else { WPRecP WP = LookupWP(FullTo); if (WP) { strcpy(Msg->via, WP->first_homebbs); } } // Fix To: address in B2 Header if (Msg->via[0]) sprintf(HddrTo[Recipients], "To: %s@%s\r\n", FullTo, Msg->via); else sprintf(HddrTo[Recipients], "To: %s\r\n", FullTo); } RecpTo=realloc(RecpTo, (Recipients+1) * sizeof(void *)); RecpTo[Recipients] = zalloc(10); Via=realloc(Via, (Recipients+1) * sizeof(void *)); Via[Recipients] = zalloc(50); strcpy(Via[Recipients], Msg->via); strcpy(RecpTo[Recipients++], FullTo); // Remove the To: Line from the buffer memmove(ptr1, ptr2+2, count); goto Loop; } else if (_memicmp(ptr1, "Type:", 4) == 0) { if (ptr1[6] == 'N') Msg->type = 'T'; // NTS else Msg->type = ptr1[6]; } else if (_memicmp(ptr1, "Body:", 4) == 0) { MsgLen = atoi(&ptr1[5]); StartofMsg = ptr1; } else if (_memicmp(ptr1, "File:", 5) == 0) { Msg->B2Flags |= Attachments; } else if (_memicmp(ptr1, "Date:", 5) == 0) { struct tm rtime; char seps[] = " ,\t\r"; memset(&rtime, 0, sizeof(struct tm)); // Date: 2009/07/25 10:08 sscanf(&ptr1[5], "%04d/%02d/%02d %02d:%02d", &rtime.tm_year, &rtime.tm_mon, &rtime.tm_mday, &rtime.tm_hour, &rtime.tm_min); rtime.tm_year -= 1900; Date = mktime(&rtime) - (time_t)_MYTIMEZONE; if (Date == (time_t)-1) Date = time(NULL); } if (linelen) // Not Null line { ptr1 = ptr2 + 2; // Skip crlf goto Loop; } // Processed all headers // If multiple recipents, create one copy for each BBS address, and one for all others (via RMS) if (Recipients == 0 || HddrTo == NULL) { Debugprintf("B2 Message with no recipients from %s", conn->Callsign); Logprintf(LOG_BBS, conn, '!', "B2 Message with no recipients from %s", conn->Callsign); SetupNextFBBMessage(conn); return; } else { __int32 i; struct MsgInfo * SaveMsg; char * SaveBody; __int32 SaveMsgLen = count; BOOL SentToRMS = FALSE; __int32 ToLen; char * ToString = malloc(Recipients * 100); char * bang; SaveMsg = Msg; SaveBody = conn->MailBuffer; // If from WL2K, create one message for each to: or cc: that is a local user if (Msg->B2Flags & FromCMS) { struct UserInfo * user; char Call[10]; char * ptr; for (i = 0; i < Recipients; i++) { memcpy(Call, &HddrTo[i][4], 9); ptr = strchr(Call, 13); if (ptr) *ptr = 0; strlop(Call, '-'); user = LookupCall(Call); if (user == 0) continue; if (strcmp(Call, BBSName) != 0) // always accept to bbs call if ((user->flags & F_POLLRMS) == 0) continue; conn->TempMsg = Msg = malloc(sizeof(struct MsgInfo)); memcpy(Msg, SaveMsg, sizeof(struct MsgInfo)); conn->MailBuffer = malloc(SaveMsgLen + 1000); memcpy(conn->MailBuffer, SaveBody, SaveMsgLen); // Add our To: ToLen = (int)strlen(HddrTo[i]); if (_memicmp(HddrTo[i], "CC", 2) == 0) // Replace CC: with TO: memcpy(HddrTo[i], "To", 2); memmove(&conn->MailBuffer[B2To + ToLen], &conn->MailBuffer[B2To], count); memcpy(&conn->MailBuffer[B2To], HddrTo[i], ToLen); conn->TempMsg->length += ToLen; strcpy(Msg->to, RecpTo[i]); strcpy(Msg->via, Via[i]); Msg->type = Type[i]; if (Recipients > 1) Msg->bid[0] = 0; CreateMessageFromBuffer(conn); } } else { // From a client - Create one copy with all RMS recipients, and one for each packet recipient // Merge all RMS To: lines // If don't add Winlink.org or no RMS BBS keep separate ToLen = 0; ToString[0] = 0; for (i = 0; i < Recipients; i++) { if (conn->RadioOnlyMode || LocalMsg[i] || (conn->UserPointer->flags & F_NOWINLINK) || FindRMS()== NULL) { LocalMsg[i] = TRUE; // Make sure local copy is created continue; // For a local RMS user } // ?? Should a Bang Path override this ?? - I think so! if (strchr(Via[i], '!')) continue; if (_stricmp(Via[i], "WINLINK.ORG") == 0 || _memicmp (&HddrTo[i][4], "SMTP:", 5) == 0 || _stricmp(RecpTo[i], "RMS") == 0) { if (ToLen == 0) // First Addr memcpy(HddrTo[i], "To", 2); // In Case CC ToLen += (int)strlen(HddrTo[i]); strcat(ToString, HddrTo[i]); } } if (ToLen) { conn->TempMsg = Msg = malloc(sizeof(struct MsgInfo)); memcpy(Msg, SaveMsg, sizeof(struct MsgInfo)); conn->MailBuffer = malloc(SaveMsgLen + 1000); memcpy(conn->MailBuffer, SaveBody, SaveMsgLen); // Add all the To: lines back to message memmove(&conn->MailBuffer[B2To + ToLen], &conn->MailBuffer[B2To], count); memcpy(&conn->MailBuffer[B2To], ToString, ToLen); conn->TempMsg->length += ToLen; if (Recipients > 1) { strcpy(Msg->via, "winlink.org"); strcpy(Msg->to, "RMS"); Msg->bid[0] = 0; // Must Change the BID } // Don't change type, as we don't change the B2 Header for messages to RMS //Msg->type = Type[0]; CreateMessageFromBuffer(conn); } free(ToString); for (i = 0; i < Recipients; i++) { // Only Process Non - RMS Dests or local RMS Users // ?? Should a Bang Path override this ?? - I think so! if (strchr(Via[i], '!') == 0) if (LocalMsg[i] == 0) if (_stricmp (Via[i], "WINLINK.ORG") == 0 || _memicmp (&HddrTo[i][4], "SMTP:", 5) == 0 || _stricmp(RecpTo[i], "RMS") == 0) continue; conn->TempMsg = Msg = malloc(sizeof(struct MsgInfo)); memcpy(Msg, SaveMsg, sizeof(struct MsgInfo)); conn->MailBuffer = malloc(SaveMsgLen + 1000); memcpy(conn->MailBuffer, SaveBody, SaveMsgLen); // Add our To: ptr = HddrTo[i]; // We removed any nts: or bull: earlier on, // and saved type. We need to set type here, as // may be sending to more than one type // If message contains Type: Private and not 'P', // need to changes to Traffic or Bulletin // But we need to remove last bang path if any if (strchr(ptr, '!')) { bang = ptr + strlen(ptr); while (*(--bang) != '!'); // Find last ! *(bang++) = 13; // Need CR; *(bang++) = 10; // Need LF; *(bang) = 0; // remove it; } ToLen = (int)strlen(ptr); // if (_memicmp(HddrTo[i], "CC", 2) == 0) // Replace CC: with TO: memcpy(HddrTo[i], "To", 2); memmove(&conn->MailBuffer[B2To + ToLen], &conn->MailBuffer[B2To], count); memcpy(&conn->MailBuffer[B2To], HddrTo[i], ToLen); conn->TempMsg->length += ToLen; Msg->type = Type[i]; ptr = strstr(conn->MailBuffer, "\nType: "); if (ptr) { char * ptrx; ptr += 7; // This handles a message arriving with bull/ or nts/ overrides if (_memicmp(ptr, "Private", 7) == 0 && Msg->type != 'P') { if (Msg->type == 'T') memcpy(ptr, "Traffic", 7); else if (Msg->type == 'B') { // have to make space memmove(ptr + 1, ptr, count); conn->TempMsg->length++; memcpy(ptr, "Bulletin", 8); } // remove //wl2k from subject ptrx = strstr(conn->MailBuffer, "Subject: "); if (ptrx && _memicmp(ptrx + 9, "//WL2K ", 7) == 0) { memmove(ptrx + 9, ptrx + 16, count); conn->TempMsg->length -= 7; memmove(conn->TempMsg->title, &conn->TempMsg->title[7], strlen(conn->TempMsg->title) - 6); } } // if we are receiving from another BBS rather // than WLE or PAT we need to set msgtype from Type: Msg->type = ptr[0]; // I think it is safe to do it always if (Msg->type == 'N') Msg->type = 'T'; } strcpy(Msg->to, RecpTo[i]); strcpy(Msg->via, Via[i]); if (i > 0 && Msg->type != 'B') // Must Change the BID Msg->bid[0] = 0; // Update Stats if (Msg->type == 'P') Index = PMSG; else if (Msg->type == 'B') Index = BMSG; else if (Msg->type == 'T') Index = TMSG; conn->UserPointer->Total.MsgsReceived[Index]++; conn->UserPointer->Total.BytesForwardedIn[Index] += MsgLen; CreateMessageFromBuffer(conn); } } // End not from RMS free(SaveMsg); free(SaveBody); conn->MailBuffer = NULL; conn->MailBufferSize=0; if (FromSync) return; SetupNextFBBMessage(conn); return; } #ifndef LINBPQ } #define EXCEPTMSG "Error Decoding B2 Message" #include "StdExcept.c" BBSputs(conn, "*** Program Error Decoding B2 Message\r"); Flush(conn); conn->CloseAfterFlush = 20; // 2 Secs return; } #endif } // end if B2Msg CreateMessageFromBuffer(conn); SetupNextFBBMessage(conn); }