/*****************************************************************************
 *
 * $Id$
 * Purpose ...............: Offline Reader
 *
 *****************************************************************************
 * Copyright (C) 1997-2002
 *   
 * Michiel Broek		FIDO:		2:280/2802
 * Beekmansbos 10
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * MBSE BBS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

#include "../lib/libs.h"
#include "../lib/structs.h"
#include "../lib/mbse.h"
#include "../lib/users.h"
#include "../lib/records.h"
#ifndef	BIG_ENDIAN
#define	BIG_ENDIAN
#endif
#include "../lib/bluewave.h"
#include "../lib/common.h"
#include "../lib/clcomm.h"
#include "../lib/msgtext.h"
#include "../lib/msg.h"
#include "mail.h"
#include "funcs.h"
#include "input.h"
#include "language.h"
#include "file.h"
#include "filesub.h"
#include "exitinfo.h"
#include "timeout.h"
#include "msgutil.h"
#include "pop3.h"
#include "offline.h"
#include "whoson.h"



long		Total, TotalPersonal, Current, Personal;
unsigned long	TotalPack;
unsigned short	BarWidth;
lastread	LR;
static char	TempStr[128];
extern int	do_mailout;


typedef struct	_msg_high {
	struct	_msg_high	*next;
	unsigned long		Area;
	unsigned long		LastMsg;
	unsigned long		Personal;
} msg_high;



/*
 *  Internal prototypes.
 */
void		AddArc(char *, char *);
void		tidy_high(msg_high **);
void		fill_high(msg_high **, unsigned long, unsigned long, unsigned long);
void		UpdateLR(msg_high *, FILE *);
void		Add_Kludges(fidoaddr, int, char *);
int		OLR_Prescan(void);
void		DrawBar(char *);
unsigned long	BlueWave_PackArea(unsigned long, long);
void		BlueWave_Fetch(void);
unsigned long	QWK_PackArea(unsigned long, long);
void		QWK_Fetch(void);
float		IEEToMSBIN(float);
float		MSBINToIEE(float);
char		*StripSpaces(char *, int);
unsigned long	ASCII_PackArea(unsigned long, long);



/****************************************************************************
 *
 *                           Global Functions
 */


void AddArc(char *Temp, char *Pktname)
{
	execute((char *)archiver.marc, Pktname, Temp, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null");
	unlink(Temp);
	printf(".");
	fflush(stdout);
}



void tidy_high(msg_high **hdp)
{
	msg_high *tmp, *old;

	for (tmp = *hdp; tmp; tmp = old) {
		old = tmp->next;
		free(tmp);
	}
	*hdp = NULL;
}



/*
 *  Add an area to the array
 */
void fill_high(msg_high **hdp, unsigned long Area, unsigned long Last, unsigned long Pers)
{
	msg_high *tmp;

	Syslog('M', "fill_high Area %lu Msg %lu, Pers %lu", Area, Last, Pers);

	tmp = (msg_high *)malloc(sizeof(msg_high));
	tmp->next = *hdp;
	tmp->Area = Area;
	tmp->LastMsg = Last;
	tmp->Personal = Pers;
	*hdp = tmp;
}



void UpdateLR(msg_high *mhl, FILE *mf)
{
	char		*p;
	msg_high	*tmp;

	colour(14, 0);
	/*      Updating lastread pointer */
	printf("%s\n", (char *)Language(449));
	colour(13, 0);
        
	for (tmp = mhl; tmp; tmp = tmp->next) {
		printf(".");
		fflush(stdout);
		fseek(mf, ((tmp->Area -1) * (msgshdr.recsize + msgshdr.syssize)) + msgshdr.hdrsize, SEEK_SET);
		fread(&msgs, msgshdr.recsize, 1, mf);
		if (Msg_Open(msgs.Base)) {
			if (Msg_Lock(30L)) {
				if (tmp->Personal) 
					Syslog('?', "Personal messages to update");

				LR.UserID = grecno;
				p = xstrcpy(exitinfo.sUserName);
				if (Msg_GetLastRead(&LR) == TRUE) {
					LR.LastReadMsg = tmp->LastMsg;
					if (tmp->LastMsg > LR.HighReadMsg)
						LR.HighReadMsg = tmp->LastMsg;
					if (LR.HighReadMsg > Msg_Highest()) {
						Syslog('?', "Highread was too high");
						LR.HighReadMsg = Msg_Highest();
					}
					LR.UserCRC = StringCRC32(tl(p));
					if (!Msg_SetLastRead(LR))
						WriteError("Error update lastread");
				} else {
					/*
					 * Append new lastread pointer
					 */
					LR.UserCRC = StringCRC32(tl(p));
					LR.UserID = grecno;
					LR.LastReadMsg = tmp->LastMsg;
					LR.HighReadMsg = tmp->LastMsg;
					if (!Msg_NewLastRead(LR))
						WriteError("Can't append new lastread");
				}
				free(p);
				Msg_UnLock();
			}
			Msg_Close();
		}
	}
}



/*
 *  Add message kludges at the start, append the message text and add 
 *  trailing kludges, tearline and originline.
 */
void Add_Kludges(fidoaddr dest, int IsReply, char *fn)
{
	char		*temp, *aka;
	FILE		*tp;

	temp = calloc(2048, sizeof(char));
	aka  = calloc(81,   sizeof(char));

	Add_Headkludges(fido2faddr(dest), IsReply);
	Syslog('m', "Kludges done, start textfile %s", fn);

	if ((tp = fopen(fn, "r")) != NULL) {
		Msg_Write(tp);
		fclose(tp);
	}

	Syslog('m', "Add footer");
	Add_Footkludges(FALSE);

	Syslog('m', "Add message now");
	Msg_AddMsg();
	Syslog('m', "Msg added");

	free(aka);
	free(temp);
}



/****************************************************************************
 *
 *                          Offline Configuration
 */


/*
 *  Tag areas, called from menu.
 */
void OLR_TagArea()
{
	char	*Msgname, *Tagname;
	FILE	*ma, *tf;
	char	*buf;
	long	total, Offset, Area;
	int	lines, input, ignore = FALSE, maxlines;

	WhosDoingWhat(OLR);

	Msgname = calloc(PATH_MAX, sizeof(char));
	Tagname = calloc(PATH_MAX, sizeof(char));
	buf     = calloc(81,  sizeof(char));

	sprintf(Msgname, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	sprintf(Tagname, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);

	clear();
	colour(14, 0);
	/*      Tag Offline Reader message areas */
	printf("%s\n", (char *)Language(66));

	do {
		colour(15, 0);
		/*        Enter the name of the conference, or ? for a list: */
		printf("\n%s", (char *)Language(228));
		colour(CFG.InputColourF, CFG.InputColourB);
		GetstrC(buf, 20);

		if (buf[0] == '?') {
			maxlines = lines = exitinfo.iScreenLen - 1;
			colour(11, 0);
			/*      Conference           Area  Msgs   Description */
			printf("%s\n", (char *)Language(229));
			if ((ma = fopen(Msgname, "r")) != NULL) {
				fread(&msgshdr, sizeof(msgshdr), 1, ma);
				Area = 0;
				if ((tf = fopen(Tagname, "r")) != NULL) {
					while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
						fseek(ma, msgshdr.syssize, SEEK_CUR);
						fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
						Area++;
						if (Msg_Open(msgs.Base)) {
							total = Msg_Number();
							Msg_Close();
						} else
							total = 0;
						colour(3, 0);
						if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
						    (!olrtagrec.Tagged) && strlen(msgs.QWKname)) {
							if ( (lines != 0) || (ignore) ) {
								lines--;
								printf("%-20.20s %-5ld %-5ld  %s\n", msgs.QWKname, Area, total, msgs.Name);
							}
							if (lines == 0) {
								fflush(stdin);
								colour(15, 0);
								/* More (Y/n/=) */
								printf("%s%c\x08", (char *) Language(61),Keystroke(61,0));
								fflush(stdout);
								alarm_on();
								input = toupper(Getone());
								printf("%c\r",input);
								if ((input == Keystroke(61, 0)) || (input == '\r'))
									lines = maxlines;

								if (input == Keystroke(61, 1)) {
									break;
								}

								if (input == Keystroke(61, 2))
									ignore = TRUE;
								else
									lines  = maxlines;
								colour(3, 0);
							}
						}
					}
					fclose(tf);
				} 
				fclose(ma);
			}
		} else 
			if (buf[0] != '\0') {
				if (atoi(buf) != 0) {
					if ((ma = fopen(Msgname, "r")) != NULL) {
						fread(&msgshdr, sizeof(msgshdr), 1, ma);
						Offset = msgshdr.hdrsize + ((atoi(buf)-1) * (msgshdr.recsize + msgshdr.syssize));
						fseek(ma, Offset, SEEK_SET);
						if (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
							if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
							    strlen(msgs.QWKname)) {
								if ((tf = fopen(Tagname, "r+")) != NULL) {
									fseek(tf, (atoi(buf)-1) * sizeof(olrtagrec), SEEK_SET);
									fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
									if (!olrtagrec.Tagged) {
										olrtagrec.Tagged = TRUE;
										fseek(tf, - sizeof(olrtagrec), SEEK_CUR);
										fwrite(&olrtagrec, sizeof(olrtagrec), 1, tf);
										Syslog('+', "OLR Tagged %d %s", 
											atoi(buf), msgs.QWKname);
									}
									fclose(tf);
								}
							}
						}
						fclose(ma);
					}
				} else {
					if ((ma = fopen(Msgname, "r")) != NULL) {
						fread(&msgshdr, sizeof(msgshdr), 1, ma);
						Area = 0;
						while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
							fseek(ma, msgshdr.syssize, SEEK_CUR);
							Area++;
							if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
							    strlen(msgs.QWKname)) {
								if (strcasecmp(msgs.QWKname, buf) == 0) {
									if ((tf = fopen(Tagname, "r+")) != NULL) {
										fseek(tf, (Area-1) * sizeof(olrtagrec), SEEK_SET);
										fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
										if (!olrtagrec.Tagged) {
											olrtagrec.Tagged = TRUE;
											fseek(tf, - sizeof(olrtagrec), SEEK_CUR);
											fwrite(&olrtagrec, sizeof(olrtagrec), 1, tf);
											Syslog('+', "OLR Tagged %d %s", 
												Area, msgs.QWKname);
										}
										fclose(tf);
									}
								}
							}
						}
						fclose(ma);
					}
				}
			}

	} while (buf[0] != '\0');

	free(buf);
	free(Tagname);
	free(Msgname);
}



/*
 *  Untag areas, called from menu.
 */
void OLR_UntagArea()
{
	char	*Msgname, *Tagname, *buf;
	FILE	*ma, *tf;
	long	total, Offset, Area;
	int     lines, input, ignore = FALSE, maxlines;

	WhosDoingWhat(OLR);

	Msgname = calloc(PATH_MAX, sizeof(char));
	Tagname = calloc(PATH_MAX, sizeof(char));
	buf	= calloc(81,  sizeof(char));

	sprintf(Msgname, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	sprintf(Tagname, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);

	clear();
	colour(14, 0);
	/*      Untag Offline Reader message areas */
	printf("%s\n", (char *)Language(256));

	do {
		colour(15, 0);
		/*        Enter the name of the conference, or ? for a list:  */
		printf("\n%s", (char *)Language(228));
		colour(CFG.InputColourF, CFG.InputColourB);
		GetstrC(buf, 20);

		if (buf[0] == '?') {
			maxlines = lines = exitinfo.iScreenLen - 1;
			colour(11, 0);
			/*      Conference           Area  Msgs   Description */
			printf("%s\n", (char *)Language(229));
			if ((ma = fopen(Msgname, "r")) != NULL) {
				fread(&msgshdr, sizeof(msgshdr), 1, ma);
				Area = 0;
				if ((tf = fopen(Tagname, "r")) != NULL) {
					while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
						fseek(ma, msgshdr.syssize, SEEK_CUR);
						fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
						Area++;
						if (Msg_Open(msgs.Base)) {
							total = Msg_Number();
							Msg_Close();
						} else
							total = 0;
						colour(3, 0);
						if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
						    olrtagrec.Tagged && strlen(msgs.QWKname)) {
							if ( (lines != 0) || (ignore) ) {
								lines--;
								printf("%-20.20s %-5ld %-5ld  %s\n", msgs.QWKname, Area, total, msgs.Name);
							}
							if (lines == 0) {
								fflush(stdin);
								colour(15, 0);
								/* More (Y/n/=) */
								printf("%s%c\x08", (char *) Language(61),Keystroke(61,0));
								fflush(stdout);
								alarm_on();
								input = toupper(Getone());
								printf("%c\r",input);
								if ((input == Keystroke(61, 0)) || (input == '\r'))
								lines = maxlines;

								if (input == Keystroke(61, 1)) {
									break;
								}

								if (input == Keystroke(61, 2))
									ignore = TRUE;
								else
									lines  = maxlines;
								colour(3, 0);
							}
						}
					}
					fclose(tf);
				} 
				fclose(ma);
			}
		} else 
			if (buf[0] != '\0') {
				if (atoi(buf) != 0) {
					if ((ma = fopen(Msgname, "r")) != NULL) {
						fread(&msgshdr, sizeof(msgshdr), 1, ma);
						Offset = msgshdr.hdrsize + ((atoi(buf)-1) * (msgshdr.recsize + msgshdr.syssize));
						fseek(ma, Offset, SEEK_SET);
						if (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
							if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
							    strlen(msgs.QWKname)) {
								if ((tf = fopen(Tagname, "r+")) != NULL) {
									fseek(tf, (atoi(buf)-1) * sizeof(olrtagrec), SEEK_SET);
									fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
									if (olrtagrec.Tagged) {
										if (msgs.OLR_Forced) {
											printf("Area cannot be switched off\n");
										} else {
											olrtagrec.Tagged = FALSE;
											fseek(tf, - sizeof(olrtagrec), SEEK_CUR);
											fwrite(&olrtagrec, sizeof(olrtagrec), 1, tf);
											Syslog('+', "OLR Untagged %d %s", 
												atoi(buf), msgs.QWKname);
										}
									}
									fclose(tf);
								}
							}
						}
						fclose(ma);
					}
				} else {
					if ((ma = fopen(Msgname, "r")) != NULL) {
						fread(&msgshdr, sizeof(msgshdr), 1, ma);
						Area = 0;
						while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
							fseek(ma, msgshdr.syssize, SEEK_CUR);
							Area++;
							if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && 
							     strlen(msgs.QWKname)) {
								if (strcasecmp(msgs.QWKname, buf) == 0) {
									if ((tf = fopen(Tagname, "r+")) != NULL) {
										fseek(tf, (Area-1) * sizeof(olrtagrec), SEEK_SET);
										fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
										if (olrtagrec.Tagged) {
											if (msgs.OLR_Forced) {
												printf("Area cannot be switched off\n");
											} else {
												olrtagrec.Tagged = FALSE;
												fseek(tf, - sizeof(olrtagrec), SEEK_CUR);
												fwrite(&olrtagrec, sizeof(olrtagrec), 1, tf);
												Syslog('+', "OLR Untagged %d %s", 
													Area, msgs.QWKname);
											}
										}
										fclose(tf);
									}
								}
							}
						}
						fclose(ma);
					}
				}
			}

	} while (buf[0] != '\0');

	free(buf);
	free(Tagname);
	free(Msgname);
}



void New_Hdr(void);
void New_Hdr()
{
	char	*temp;

	temp = calloc(81, sizeof(char));
	clear();
	colour(14, 0);
	/* New or deleted mail areas at */
	sprintf(temp, "%s%s", (char *) Language(364), CFG.bbs_name);
	Center(temp);
	free(temp);
	printf("\n");
	colour(15, 1);
	/* Area  State  Type     Description */
	printf("%-79s\n", (char *) Language(365));
}



void New_Area(long);
void New_Area(long Area)
{
	colour(11, 0);
		/*    New    */
	printf("%4ld  %s", Area, (char *)Language(391));
	switch (msgs.Type) {
		case LOCALMAIL:	printf(Language(392)); /* Local    */
				break;
		case NETMAIL:	printf(Language(393)); /* Netmail  */
				break;
		case LIST:
		case ECHOMAIL:	printf(Language(394)); /* Echomail */
				break;
		case NEWS:	printf(Language(395)); /* News     */
				break;
	}
	printf("%s\n", msgs.Name);
}



void Old_Area(long);
void Old_Area(long Area)
{
	colour(12, 0);
	/*            Del */
	printf("%4ld  %s\n", Area, (char *)Language(397));
}



/*
 *  Sync tagged areas file. If CFG.NewAreas is on then we show the
 *  changed areas to the user. This one is called by user.c during login.
 */
void OLR_SyncTags()
{
	char	*Tagname, *Msgname;
	FILE	*fp, *ma;
	long	Area;
	int	Changed = FALSE;

	Tagname = calloc(PATH_MAX, sizeof(char));
	Msgname = calloc(PATH_MAX, sizeof(char));
	sprintf(Tagname, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	sprintf(Msgname, "%s/etc/mareas.data", getenv("MBSE_ROOT"));

	if ((fp = fopen(Tagname, "r+")) == NULL) {

		/*
		 *  If the user has no .olrtagsfile yet, we silently create
		 *  a new one. The user will not be notified of new areas
		 *  of coarse.
		 */
		Syslog('m', "Creating %s", Tagname);
		if ((fp = fopen(Tagname, "w")) != NULL) {

			if ((ma = fopen(Msgname, "r")) != NULL) {
				fread(&msgshdr, sizeof(msgshdr), 1, ma);

				while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
					memset(&olrtagrec, 0, sizeof(olrtagrec));
					if ((msgs.Active) && Access(exitinfo.Security, msgs.RDSec)) {
						olrtagrec.Available = TRUE;
						olrtagrec.ScanNew = TRUE;
						if (msgs.OLR_Forced || msgs.OLR_Default)
							olrtagrec.Tagged = TRUE;
					}
					fwrite(&olrtagrec, sizeof(olrtagrec), 1, fp);
					fseek(ma, msgshdr.syssize, SEEK_CUR);
				}

				fclose(ma);
			}
		}
	} else {
		/*
		 *  The user has been here before...
		 */
		if ((ma = fopen(Msgname, "r")) != NULL) {
			fread(&msgshdr, sizeof(msgshdr), 1, ma);
			Area = 0;

			while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
				Area++;

				if (fread(&olrtagrec, sizeof(olrtagrec), 1, fp) == 1) {

					/*
					 *  Check if this is a new area for the user.
					 */
					if ((msgs.Active) && Access(exitinfo.Security, msgs.RDSec) && (!olrtagrec.Available)) {
						Syslog('m', "New msg area %ld %s", Area, msgs.Name);
						fseek(fp, - sizeof(olrtagrec), SEEK_CUR);
						olrtagrec.Available = TRUE;
						olrtagrec.ScanNew = TRUE;
						if (msgs.OLR_Forced || msgs.OLR_Default)
							olrtagrec.Tagged = TRUE;
						fwrite(&olrtagrec, sizeof(olrtagrec), 1, fp);
						if (CFG.NewAreas) {
							if (!Changed) {
								New_Hdr();
								Changed = TRUE;
							}
							New_Area(Area);
						}
					} else {
						/*
						 *  Check if this area is no longer
						 *  available for the user.
						 */
						if (((!msgs.Active) || (!Access(exitinfo.Security, msgs.RDSec))) && 
						     olrtagrec.Available) {
							Syslog('m', "Deleted msg area %ld", Area);
							fseek(fp, - sizeof(olrtagrec), SEEK_CUR);
							olrtagrec.Available = FALSE;
							olrtagrec.ScanNew = FALSE;
							olrtagrec.Tagged = FALSE;
							fwrite(&olrtagrec, sizeof(olrtagrec), 1, fp);
							if (CFG.NewAreas) {
								if (!Changed) {
									New_Hdr();
									Changed = TRUE;
								}
								Old_Area(Area);
							}
						}
					}

				} else {
					/*
					 * If the number if msg areas was increased,
					 * append a new tagrecord.
					 */
					memset(&olrtagrec, 0, sizeof(olrtagrec));
					if ((msgs.Active) && Access(exitinfo.Security, msgs.RDSec)) {
						Syslog('m', "Append new area %ld %s", Area, msgs.Name);
						olrtagrec.Available = TRUE;
						olrtagrec.ScanNew = TRUE;
						if (msgs.OLR_Forced || msgs.OLR_Default)
							olrtagrec.Tagged = TRUE;
						if (CFG.NewAreas) {
							if (!Changed) {
								New_Hdr();
								Changed = TRUE;
							}
							New_Area(Area);
						}
					}
					fwrite(&olrtagrec, sizeof(olrtagrec), 1, fp);
				}
				fseek(ma, msgshdr.syssize, SEEK_CUR);
			}

			fclose(ma);
		}
	}

	fclose(fp);

	if (Changed) {
		colour(10, 0);
		fLine(79);
		Pause();
	}

	SetMsgArea(exitinfo.iLastMsgArea);
	free(Tagname);
	free(Msgname);
}



/*
 *  View tagged areas, called from menu.
 */
void OLR_ViewTags()
{
	char	*Tagname, *Msgname;
	FILE	*tf, *ma;
	long	total, Area = 0;
	int     lines, input, ignore = FALSE, maxlines;

	WhosDoingWhat(OLR);

	Tagname = calloc(PATH_MAX, sizeof(char));
	Msgname = calloc(PATH_MAX, sizeof(char));
	sprintf(Tagname, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	sprintf(Msgname, "%s/etc/mareas.data", getenv("MBSE_ROOT"));

	if ((tf = fopen(Tagname, "r")) == NULL) {
		WriteError("$Can't open %s", Tagname);
		return;
	}

	if ((ma = fopen(Msgname, "r")) == NULL) {
		WriteError("$Can't open %s", Msgname);
		fclose(tf);
		return;
	}
	fread(&msgshdr, sizeof(msgshdr), 1, ma);

	clear();
	colour(14, 0);
	/*       You have selected the following Conference(s): */
	printf ("%s\n", (char *)Language(260));
	colour(11, 0);
	/*         Conference           Area  Msgs   Description */
	printf ("\n%s\n", (char *)Language(229));
	colour(3, 0);
	fflush(stdout);
	maxlines = lines = exitinfo.iScreenLen - 1;

	while (fread(&msgs, msgshdr.recsize, 1, ma) == 1) {
		fseek(ma, msgshdr.syssize, SEEK_CUR);
		fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
		Area++;

		if (olrtagrec.Tagged) {
			if (Msg_Open(msgs.Base)) {
				total = Msg_Number();
				Msg_Close();
			} else
				total = 0;
			if ( (lines != 0) || (ignore) ) {
				lines--;
				printf("%-20.20s %-5ld %-5ld  %s\n", msgs.QWKname, Area, total, msgs.Name);
			}
			if (lines == 0) {
				fflush(stdin);
				colour(15, 0);
				/* More (Y/n/=) */
				printf("%s%c\x08", (char *) Language(61),Keystroke(61,0));
				fflush(stdout);
				alarm_on();
				input = toupper(Getone());
				printf("%c\r",input);
				if ((input == Keystroke(61, 0)) || (input == '\r'))
					lines = maxlines;

				if (input == Keystroke(61, 1)) {
					break;
				}
				if (input == Keystroke(61, 2))
					ignore = TRUE;
				else
					lines  = maxlines;
				colour(3, 0);
			}
			fflush(stdout);
		}
	}

	fclose(tf);
	fclose(ma);
	Pause();
	free(Tagname);
	free(Msgname);
}



/*
 *  Prescan all selected areas. Show the user the areas and messages in it.
 */
int OLR_Prescan()
{
	unsigned short	RetVal = FALSE, Areas;
	unsigned long	Number;
	char		*Temp;
	FILE		*mf, *tf;
	int		x;

	WhosDoingWhat(OLR);
	clear();
	colour(13, 0);
	/*      Offline Reader Download */
	printf("%s\n\n", (char *)Language(277));
	fflush(stdout);

	if (exitinfo.Email)
		check_popmail(exitinfo.Name, exitinfo.Password);

	Temp = calloc(PATH_MAX, sizeof(char));
	sprintf(Temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	mf = fopen(Temp, "r");
	fread(&msgshdr, sizeof(msgshdr), 1, mf);

	sprintf(Temp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	tf = fopen(Temp, "r");
	Total = TotalPersonal = Areas = 0;

	colour(15, 1);
	/*        Forum                Description                               Msgs. Pers.   */
	printf("\n%s\n", (char *)Language(297));

	while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
		fseek(mf, msgshdr.syssize, SEEK_CUR);
		fread(&olrtagrec, sizeof(olrtagrec), 1, tf);

		if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && strlen(msgs.QWKname) && olrtagrec.Tagged) {
			if (Msg_Open(msgs.Base)) {
				Areas++;
				Current = Personal = 0;
				colour(11, 0);
				printf("%-20.20s %-41.41s ", msgs.QWKname, msgs.Name);
				fflush(stdout);

				memset(&LR, 0, sizeof(LR));
				LR.UserID = grecno;
				if (Msg_GetLastRead(&LR))
					Number = LR.HighReadMsg;
				else
					Number = Msg_Lowest() -1;
				if (Number > Msg_Highest())
					Number = Msg_Highest();
				if (Msg_Next(&Number)) {
					do {
						Msg_ReadHeader(Number);
						Current++;
						Total++;
						if ((strcasecmp(Msg.To, exitinfo.sUserName) == 0) ||
						    (strcasecmp(Msg.To, exitinfo.sHandle) == 0)) {
							Personal++;
							TotalPersonal++;
						} else if (msgs.Type == NETMAIL) {
							Current--;
							Total--;
						}
					} while (Msg_Next(&Number));
				}

				colour(10, 0);
				printf("%5lu %5lu\n", Current, Personal);
				fflush(stdout);
				Msg_Close();
			}
		}
	}

	Syslog('+', "OLR Prescan: %u Areas, %lu Messages", Areas, Total);

	colour(9, 0);
	/*        Total messages found: */
	printf("\n%s %lu\n\n", (char *)Language(338), Total);
	if (Total == 0L) {
		colour(14, 0);
		/*      No messages found to download! */
		printf("%s\n\007", (char *)Language(374));
		Pause();
	} else {
		if (CFG.OLR_MaxMsgs != 0 && Total > CFG.OLR_MaxMsgs) {
			/*      Too much messages. Only the first    will be packed! */
			printf("%s %d %s\n\n\007", (char *)Language(377), CFG.OLR_MaxMsgs, (char *)Language(411));
			Total = CFG.OLR_MaxMsgs;
		}

		colour(CFG.HiliteF, CFG.HiliteB);
		/*      Do you want to download these messages [Y/n]? */
		printf("%s", (char *)Language(425));
		fflush(stdout);
		alarm_on();
		x = toupper(Getone());

		if (x != Keystroke(425, 1)) {
			RetVal = TRUE;
			TotalPack = Total;
			BarWidth = 0;
		}
	}

	if (mf != NULL)	
		fclose(mf);
	if (tf != NULL)
		fclose(tf);

	free(Temp);
	return(RetVal);
}



/*
 * Draw progess bar
 */
void DrawBar(char *Pktname)
{
	colour(14, 0);
	/*        Preparing packet */
	printf("\n%s %s...\n\n", (char *)Language(445), Pktname);
	colour(10, 0);
	printf("0%%    10%%  20%%   30%%   40%%   50%%   60%%   70%%   80%%   90%%   100%%\n");
	printf("|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|\r");
	fflush(stdout);
}



void OLR_RestrictDate()
{
	WhosDoingWhat(OLR);

	printf("Not Yet Implemented\n");
	Pause();
}


/*
VOID TOffline::RestrictDate (VOID)
{
   int dd, mm, yy;
   CHAR Temp[32];
   ULONG Restrict;
   struct tm ltm;
   class TMsgTag *MsgTag = User->MsgTag;

   memcpy (&ltm, localtime ((time_t *)&User->LastCall), sizeof (struct tm));
   Embedded->Printf ("\n\026\001\017Enter date of oldest message to pack, or press <enter> for %d-%02d-%d: ", ltm.tm_mday, ltm.tm_mon + 1, ltm.tm_year % 100);
   Embedded->Input (Temp, 10);

   if (Embedded->AbortSession () == FALSE) {
      Restrict = User->LastCall;
      if (Temp[0] != '\0') {
         sscanf (Temp, "%d-%d-%d", &dd, &mm, &yy);
         if (yy < 90)
            yy += 100;
         memset (&ltm, 0, sizeof (struct tm));
         ltm.tm_mday = dd;
         ltm.tm_mon = mm - 1;
         ltm.tm_year = yy;
         Restrict = mktime (&ltm);
      }

      if (MsgTag->First () == TRUE)
         do {
            if (MsgTag->Tagged == TRUE) {
               MsgTag->LastRead = 0L;
               MsgTag->OlderMsg = Restrict;
               MsgTag->Update ();
            }
         } while (MsgTag->Next () == TRUE);
   }
}
*/

/*
USHORT TOffline::TooOld (ULONG Restrict, class TMsgBase *Msg)
{
   USHORT RetVal = FALSE;
   struct tm ltm;

   memset (&ltm, 0, sizeof (struct tm));
   ltm.tm_mday = Msg->Written.Day;
   ltm.tm_mon = Msg->Written.Month - 1;
   ltm.tm_year = Msg->Written.Year - 1900;
   if (mktime (&ltm) < Restrict)
      RetVal = TRUE;

   return (RetVal);
}
*/



/*
 *  Upload offline mail. Filenames: BBSID.NEW or BBSID.REP.
 *  Should also do hhhhhhhh.SU0 for point uploads.
 *  NOTE: THE FIRST PART OF THE CODE IS FROM UPLOAD_HOME
 */
void OLR_Upload(void)
{
	char		*File, *temp, *Arc;
	time_t		ElapstimeStart, ElapstimeFin, iTime;
	int		err, Strlen, RetVal = FALSE;
	struct stat	statbuf;
	FILE		*fp;

	WhosDoingWhat(OLR);
	clear();
	colour(13, 0);
	/*      Offline Reader Upload */
	printf("%s\n", (char *)Language(439));

	if (!ForceProtocol())
		return;

	File  = calloc(PATH_MAX, sizeof(char));
	temp  = calloc(PATH_MAX, sizeof(char));

	if (!uProtBatch) {
		Enter(1);
		/* Please enter file to upload: */
		pout(14, 0, (char *) Language(276));

		colour(CFG.InputColourF, CFG.InputColourB);
		GetstrC(File, 80);

		Syslog('+', "Filename entered \"%s\"", File);

		if ((strcmp(File, "")) == 0)
			return;

		if (File[0] == '.' || File[0] == '*' || File[0] == ' ') {
			colour(CFG.HiliteF, CFG.HiliteB);
			/* Illegal filename! */
			printf("\n%s\n\n", (char *) Language(247));
			Pause();
			return;
		}

		Strlen = strlen(File);
		Strlen--;

		if (File[Strlen] == '.' || File[Strlen] == '/' || File[Strlen] == ' ') {
			colour(CFG.HiliteF, CFG.HiliteB);
			/* Illegal Filename! */
			printf("\n%s\n\n", (char *) Language(247));
			Pause();
			return;
		}

		if (strncasecmp(File, CFG.bbsid, strlen(CFG.bbsid))) {
			colour(CFG.HiliteF, CFG.HiliteB);
			/* Illegal filename! */
			printf("\n%s\n\n", (char *) Language(247));
			Pause();
			return;
		}
		Syslog('+', "Filename accepted");
	}

	colour(CFG.HiliteF, CFG.HiliteB);
	/* Please start your upload now */
	printf("\n%s, %s\n\n", sProtAdvice, (char *) Language(283));
	if (uProtBatch)
		Syslog('+', "Upload using %s", sProtName);
	else
		Syslog('+', "Upload \"%s\" using %s", File, sProtName);

	sprintf(temp, "%s/%s/upl", CFG.bbs_usersdir, exitinfo.Name);

	if (chdir(temp)) {
		WriteError("$Can't chdir to %s", temp);
		return;
	}

	fflush(stdout);
	fflush(stdin);
	sleep(2);
	ElapstimeStart = time(NULL);

	/*
	 *  Get the file
	 */
	Altime(7200);
	alarm_set(7190);
	if ((err = execute(sProtUp, (char *)"", NULL, NULL, NULL, NULL))) {
		colour(CFG.HiliteF, CFG.HiliteB);
		WriteError("$Upload error %d, prot: %s", err, sProtUp);
	}
	Altime(0);
	alarm_off();
	alarm_on();
	printf("\n");
	fflush(stdout);
	fflush(stdin);
	ElapstimeFin = time(NULL);

	/*
	 *  Get the upload time.
	 */
	iTime = ElapstimeFin - ElapstimeStart;
	if (!iTime)
		iTime = 1;

	Syslog('m', "Transfer time %ld", iTime);
	Home();

	if (!RetVal) {
		sprintf(File, "%s/%s/upl/%s.NEW", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		Syslog('m', "Check %s", File);
		if (stat(File, &statbuf) == 0)
			RetVal = TRUE;
	}

	if (!RetVal) {
		File = tl(File);
		Syslog('m', "Check %s", File);
		if (stat(File, &statbuf) == 0)
			RetVal = TRUE;
	}

	if (!RetVal) {
		sprintf(File, "%s/%s/upl/%s.REP", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		Syslog('m', "Check %s", File);
		if (stat(File, &statbuf) == 0)
			RetVal = TRUE;
	}

	if (!RetVal) {
		File = tl(File);
		Syslog('m', "Check %s", File);
		if (stat(File, &statbuf) == 0)
			RetVal = TRUE;
	}

	if (RetVal == FALSE) {
		WriteError("Invalid OLR packed received");
		/*      Invalid packet received */
		printf("%s\n\n", (char *)Language(440));
		sleep(2);
		return;
	}
	Syslog('+', "Received OLR packet %s", File);

	if ((Arc = GetFileType(File)) == NULL) {
		/*      Unknown compression type */
		printf("%s\n", (char *)Language(441));
		Syslog('+', "Unknown compression type");
		Pause();
		return;
	}

	Syslog('m', "File type is %s", Arc);

	sprintf(temp, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
	if ((fp = fopen(temp, "r")) == NULL)
		return;

	fread(&archiverhdr, sizeof(archiverhdr), 1, fp);

	while (fread(&archiver, archiverhdr.recsize, 1, fp) == 1) {
		if ((strcmp(Arc, archiver.name) == 0) && archiver.available)
			break;
	}
	fclose(fp);

	if (strcmp(Arc, archiver.name) || (!archiver.available)) {
		Syslog('+', "Archiver %s not available", Arc);
		/*      Archiver not available */
		printf("%s\n", (char *)Language(442));
		Pause();
		return;
	}

	Syslog('m', "Archiver %s", archiver.comment);

	colour(CFG.TextColourF, CFG.TextColourB);
	/* Unpacking archive */
	printf("%s ", (char *) Language(201));
	fflush(stdout);
	sprintf(temp, "%s %s", archiver.funarc, File);
	Syslog('m', "Unarc %s", temp);
	colour(CFG.HiliteF, CFG.HiliteB);

	if ((err = execute(archiver.funarc, File, NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null"))) {
		WriteError("$Failed %s", temp);
		/* ERROR */
		printf("%s\n", (char *) Language(217));
		fflush(stdout);
		Pause();
		return;
	}

	/* Ok */
	printf("%s\n", (char *) Language(200));
	fflush(stdout);
	unlink(File);

	/*
	 * Check for BlueWave files, upper and lowercase.
	 */
	RetVal = FALSE;
	sprintf(temp, "%s/%s/%s.UPL", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

	temp = tl(temp);
	if (!file_exist(temp, R_OK))
		RetVal = TRUE;

	sprintf(temp, "%s/%s/%s.UPI", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	sprintf(temp, "%s/%s/%s.NET", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	sprintf(temp, "%s/%s/%s.REQ", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	sprintf(temp, "%s/%s/%s.PDQ", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	sprintf(temp, "%s/%s/%s.OLC", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	if (RetVal) {
		Syslog('+', "OLR packet is BlueWave");
		free(File);
		free(temp);
		BlueWave_Fetch();
		return;
	}

	sprintf(temp, "%s/%s/%s.MSG", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if (!file_exist(temp, R_OK)) 
		RetVal = TRUE;

        temp = tl(temp);
        if (!file_exist(temp, R_OK))
                RetVal = TRUE;

	if (RetVal) {
		Syslog('+', "OLR packet is QWK");
		free(File);
		free(temp);
		QWK_Fetch();
		return;
	}

	WriteError("OLR_Upload: Garbage in mailpacket, clean directory!");
	/*      Unknown type mailpacket */
	printf("%s\n", (char *)Language(443));
	Pause();
	free(File);
	free(temp);
}



/***************************************************************************
 *
 *                    BlueWave specific functions.
 */


char *Extensions[] = {
   (char *)".SU0", (char *)".MO0", (char *)".TU0", (char *)".WE0", 
   (char *)".TH0", (char *)".FR0", (char *)".SA0"
};



/*
 *  Download a BlueWave mailpacket, called from menu.
 */
void OLR_DownBW()
{
	struct	tm	*tp;
	time_t		Now;
	char		Pktname[32];
	char		*Work, *Temp;
	long		Area = 0;
	int		RetVal = FALSE, rc;
	FILE		*fp, *tf, *mf, *af;
	INF_HEADER	Inf;
	INF_AREA_INFO	AreaInf;
	unsigned long	Start, High;
	msg_high	*mhl = NULL;

	if (!OLR_Prescan())
		return;

	Total = TotalPersonal = 0;
	clear();
	colour(9, 0);
	/*      BlueWave Offline download */
	printf("%s\n", (char *)Language(444));

	Work = calloc(PATH_MAX, sizeof(char));
	Temp = calloc(PATH_MAX, sizeof(char));

	Now = time(NULL);
	tp = localtime(&Now);
	Syslog('+', "Preparing BlueWave packet");

	sprintf(Pktname, "%s%s", CFG.bbsid , Extensions[tp->tm_wday]);
	Syslog('m', "Packet name %s", Pktname);
	sprintf(Work, "%s/%s/tmp", CFG.bbs_usersdir, exitinfo.Name);
	Syslog('m', "Work path %s", Work);

	sprintf(Temp, "%s/%s.INF", Work, CFG.bbsid);
	if ((fp = fopen(Temp, "w+")) == NULL) {
		WriteError("$Can't create %s", Temp);
		return;
	}

	/*
	 *  Write the info header.
	 */
	memset(&Inf, 0, sizeof(Inf));
	Inf.ver = PACKET_LEVEL;
	strcpy((char *)Inf.loginname, exitinfo.sUserName);
	strcpy((char *)Inf.aliasname, exitinfo.sHandle);
	Inf.zone  = CFG.aka[0].zone;
	Inf.net   = CFG.aka[0].net;
	Inf.node  = CFG.aka[0].node;
	Inf.point = CFG.aka[0].point;
	strcpy((char *)Inf.sysop, CFG.sysop_name);
	strcpy((char *)Inf.systemname, CFG.bbs_name);
	Inf.maxfreqs = CFG.OLR_MaxReq;
	if (exitinfo.HotKeys)
		Inf.uflags |= INF_HOTKEYS;
	if (exitinfo.GraphMode)
		Inf.uflags |= INF_GRAPHICS;
	if (exitinfo.OL_ExtInfo)
		Inf.uflags |= INF_EXT_INFO;
	Inf.credits = exitinfo.Credit;
	Inf.inf_header_len = sizeof(INF_HEADER);
	Inf.inf_areainfo_len = sizeof(INF_AREA_INFO);
	Inf.mix_structlen = sizeof(MIX_REC);
	Inf.fti_structlen = sizeof(FTI_REC);
	Inf.uses_upl_file = TRUE;
	Inf.can_forward = TRUE;
	strcpy((char *)Inf.packet_id, CFG.bbsid);
	fwrite(&Inf, sizeof(INF_HEADER), 1, fp);

	/*
	 *  Check to see if this stuff is compiled packed. If not the
	 *  download packet is useless.
	 */
	if ((sizeof(Inf) != ORIGINAL_INF_HEADER_LEN) ||
	    (sizeof(AreaInf) != ORIGINAL_INF_AREA_LEN)) {
		WriteError("PANIC: Probably not \"packed\" compiled!");
		fclose(fp);
		return;
	}

	sprintf(Temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	if ((mf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		return;
	}
	fread(&msgshdr, sizeof(msgshdr), 1, mf);

	sprintf(Temp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	if ((tf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		fclose(mf);
		return;
	}

	/*
	 *  Write the areas information
	 */
	while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
		fseek(mf, msgshdr.syssize, SEEK_CUR);
		fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
		Area++;

		if (msgs.Active && Access(exitinfo.Security, msgs.RDSec)) {
			memset(&AreaInf, 0, sizeof(AreaInf));
			sprintf((char *)AreaInf.areanum, "%lu", Area);
			strcpy((char *)AreaInf.echotag, msgs.QWKname);
			strcpy((char *)AreaInf.title, msgs.Name);
			if (olrtagrec.Tagged) {
				AreaInf.area_flags |= INF_SCANNING;
				RetVal = TRUE;
			}

			switch(msgs.Type) {
				case LOCALMAIL:
						break;

				case NETMAIL:	AreaInf.area_flags |= (INF_ECHO+INF_NETMAIL+INF_HASFILE);
						break;

				case LIST:
				case ECHOMAIL:	AreaInf.area_flags |= INF_ECHO;
						break;

//				case EMAIL:	AreaInf.area_flags |= (INF_ECHO+INF_NETMAIL);
//						AreaInf.network_type |= INF_NET_INTERNET;
//						break;

				case NEWS:	AreaInf.area_flags |= INF_ECHO;
						AreaInf.network_type |= INF_NET_INTERNET;
						break;
			}
			switch(msgs.MsgKinds) {
				case BOTH:	if (Access(exitinfo.Security, msgs.WRSec))
							AreaInf.area_flags |= INF_POST;
						break;

				case PRIVATE:	if (Access(exitinfo.Security, msgs.WRSec))
							AreaInf.area_flags |= INF_POST;
						AreaInf.area_flags |= INF_NO_PUBLIC;
						break;

				case PUBLIC:	if (Access(exitinfo.Security, msgs.WRSec))
							AreaInf.area_flags |= INF_POST;
						AreaInf.area_flags |= INF_NO_PRIVATE;
						break;

				case RONLY:	break;
			}

			if (msgs.Aliases)
				AreaInf.area_flags |= INF_ALIAS_NAME;

			fwrite(&AreaInf, sizeof(AreaInf), 1, fp);
		}
	}
	fclose(fp);

	if (RetVal) {
		Area = 0;
		DrawBar(Pktname);
		fseek(mf, sizeof(msgshdr), SEEK_SET);
		fseek(tf, 0, SEEK_SET);

		while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
			fseek(mf, msgshdr.syssize, SEEK_CUR);
			fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
			Area++;
			if (olrtagrec.Tagged) {
				if (Msg_Open(msgs.Base)) {
					Current = Personal = 0;
					if (Msg_Highest() != 0) {
						memset(&LR, 0, sizeof(LR));
						LR.UserID = grecno;
						if (Msg_GetLastRead(&LR))
							Start = LR.HighReadMsg;
						else
							Start = Msg_Lowest() -1;
						if (Start > Msg_Highest())
							Start = Msg_Highest();
						if (Start < Msg_Highest()) {
							Syslog('m', "First %lu, Last %lu, Start %lu", Msg_Lowest(), Msg_Highest(), Start);
							High = BlueWave_PackArea(Start, Area);
							fill_high(&mhl, Area, High, Personal);
						}
					}
					Syslog('+', "Area %-20s %5ld (%ld personal)", msgs.QWKname, Current, Personal);
					Msg_Close();
				}
			}
		}
		Syslog('+', "Packed %ld messages (%ld personal)", Total, TotalPersonal);
	}
	fclose(tf);

	rc = FALSE;
	alarm_on();

	if (Total) {
		/*        Packing with */
		printf("\n%s ", (char *)Language(446));
		sprintf(Temp, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
		if ((af = fopen(Temp, "r")) != NULL) {
			fread(&archiverhdr, sizeof(archiverhdr), 1, af);
			while (fread(&archiver, archiverhdr.recsize, 1, af) == 1) {
				if (archiver.available && (!strcmp(archiver.name, exitinfo.Archiver))) {
					Syslog('+', "Archiver %s", archiver.comment);
					printf("%s ", archiver.comment);
					sprintf(Temp, "%s/%s.DAT", Work, CFG.bbsid);
					AddArc(Temp, Pktname);
					alarm_on();
					sprintf(Temp, "%s/%s.FTI", Work, CFG.bbsid);
					AddArc(Temp, Pktname);
					sprintf(Temp, "%s/%s.INF", Work, CFG.bbsid);
					AddArc(Temp, Pktname);
					sprintf(Temp, "%s/%s.MIX", Work, CFG.bbsid);
					AddArc(Temp, Pktname);
					sprintf(Temp, "%s/%s/%s", CFG.bbs_usersdir, exitinfo.Name, Pktname);
					rc = DownloadDirect(Temp, FALSE);
					Syslog('m', "Download result %d", rc);
					unlink(Temp);
				}
			}
			fclose(af);
		}
	}

	colour(CFG.HiliteF, CFG.HiliteB);
	if (rc == FALSE) {
		Syslog('+', "BlueWave download failed");
		/*      Download failed */
		printf("%s", (char *)Language(447));
	} else {
		Syslog('+', "BlueWave download successfull");
		/*        Download successfull */
		printf("\r%s\n", (char *)Language(448));

		if (mhl != NULL)
			UpdateLR(mhl, mf);
	}

	fclose(mf);
	tidy_high(&mhl);

	free(Temp);
	free(Work);
	printf("\n\n");
	Pause();
}



/*
 *  BlueWave Fetch reply packet.
 */
void BlueWave_Fetch()
{
	char		*temp;
	FILE		*up, *mf, *tp;
	UPL_HEADER	Uph;
	UPL_REC		Upr;
	PDQ_HEADER	Pdh;
	PDQ_REC		Pdr;
	REQ_REC		Req;
	int		i, Found;
	fidoaddr	dest;

	colour(9, 0);
	/*      Processing BlueWave reply packet */
	printf("%s\n", (char *)Language(450));
	temp = calloc(PATH_MAX, sizeof(char));

	/*
	 *  Process uploaded mail
	 */
	sprintf(temp, "%s/%s/%s.UPL", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if ((up = fopen(temp, "r")) == NULL) {
		temp = tl(temp);
		up = fopen(temp, "r");
	}
	if (up != NULL) {
		fread(&Uph, sizeof(UPL_HEADER), 1, up);
		Syslog('+', "Processing BlueWave .UPL file");
		Syslog('+', "Client: %s %d.%d", Uph.reader_name, Uph.reader_major, Uph.reader_minor);
		if (Uph.upl_header_len != sizeof(UPL_HEADER)) {
			WriteError("Recordsize mismatch");
			fclose(up);
			/*      ERROR in packet */
			printf("%s\n", (char *)Language(451));
			Pause();
			return;
		}
		Syslog('+', "Login %s, Alias %s", Uph.loginname, Uph.aliasname);
		/* MORE CHECKS HERE */

		colour(CFG.TextColourF, CFG.TextColourB);
		/*      Import messages  */
		printf("%s ", (char *)Language(452));
		colour(CFG.HiliteF, CFG.HiliteB);
		fflush(stdout);
		i = 0;

		memset(&Upr, 0, sizeof(UPL_REC));
		while (fread(&Upr, Uph.upl_rec_len, 1, up) == 1) {
			printf(".");
			fflush(stdout);
			Syslog('m', "  From  : %s", Upr.from);
			Syslog('m', "  To    : %s", Upr.to);
			Syslog('m', "  Subj  : %s", Upr.subj);
			Syslog('m', "  Date  : %ld", Upr.unix_date);
			Syslog('m', "  Dest  : %d:%d/%d.%d", Upr.destzone, Upr.destnet, Upr.destnode, Upr.destpoint);
			if (Upr.msg_attr & UPL_INACTIVE)
				Syslog('m', "  Message is Inactive");
			if (Upr.msg_attr & UPL_PRIVATE)
				Syslog('m', "  Message is Private");
			if (Upr.msg_attr & UPL_HAS_FILE)
				Syslog('m', "  File Attach");
			if (Upr.msg_attr & UPL_NETMAIL)
				Syslog('m', "  Is Netmail");
			if (Upr.msg_attr & UPL_IS_REPLY)
				Syslog('m', "  Is Reply");
			if (Upr.network_type)
				Syslog('m', "  Type  : Internet");
			else
				Syslog('m', "  Type  : Fidonet");
			Syslog('m', "  File  : %s", Upr.filename);
			Syslog('m', "  Tag   : %s", Upr.echotag);

			sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
			if ((mf = fopen(temp, "r+")) != NULL) {
				fread(&msgshdr, sizeof(msgshdr), 1, mf);
				Found = FALSE;

				if (strlen(Upr.echotag)) {
					while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
						fseek(mf, msgshdr.syssize, SEEK_CUR);
						if (msgs.Active && (strcasecmp(msgs.QWKname, Upr.echotag) == 0)) {
							Found = TRUE;
							break;
						}
					}
				} else {
					/*
					 *  If there is no echotag, the filename is used
					 *  this is "areanum.msgnum" so we pick the part
					 *  before the dot and pray that it's ok.
					 */
					temp = strtok(strdup(Upr.filename), ".");
					if (fseek(mf, ((atoi(temp) -1) * (msgshdr.recsize + msgshdr.syssize)) + msgshdr.hdrsize, SEEK_SET) == 0)
						if (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
							Found = TRUE;
							fseek(mf, msgshdr.syssize, SEEK_CUR);
						}
				}

				/* SHOULD ALSO CHECK FROM FIELD */
				if (!Found) {
					WriteError("No msg area, File \"%s\"", Upr.filename);
				} else {
					if ((Access(exitinfo.Security, msgs.WRSec)) && (msgs.MsgKinds != RONLY)) {

						if (Open_Msgbase(msgs.Base, 'w')) {
							Msg_New();
							Syslog('m', "Msgbase open and locked");
							strcpy(Msg.From, Upr.from);
							strcpy(Msg.To, Upr.to);
							strcpy(Msg.Subject, Upr.subj);
							if (Upr.msg_attr & UPL_PRIVATE)
								Msg.Private = TRUE;
							if (msgs.MsgKinds == PRIVATE)
								Msg.Private = TRUE;
							Msg.Written = Upr.unix_date;
							Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
							Msg.Local  = TRUE;
							dest.zone  = Upr.destzone;
							dest.net   = Upr.destnet;
							dest.node  = Upr.destnode;
							dest.point = Upr.destpoint;
							Syslog('m', "Header fields are set, starting kludges");
							Add_Kludges(dest, FALSE, Upr.filename);
							Syslog('+', "Msg (%ld) to \"%s\", \"%s\", in %s", Msg.Id, Msg.To, Msg.Subject, msgs.QWKname);
							sprintf(temp, "%s/%s/%s", CFG.bbs_usersdir, exitinfo.Name, Upr.filename);
							unlink(temp);
							i++;
							Close_Msgbase();
							Syslog('m', "Msgbase closed again");
							fseek(mf, - (msgshdr.recsize + msgshdr.syssize), SEEK_CUR);
							msgs.Posted.total++;
							msgs.Posted.tweek++;
							msgs.Posted.tdow[Diw]++;
							msgs.Posted.month[Miy]++;
							msgs.LastPosted = time(NULL);
							fwrite(&msgs, msgshdr.recsize, 1, mf);
						}
					} else {
						/*        No Write access to area */
						printf("\n%s %s\n", (char *)Language(453), msgs.Name);
						WriteError("No Write Access to area %s", msgs.Name);
					}
				}
				fclose(mf);
			}
			memset(&Upr, 0, sizeof(UPL_REC));
		}
		printf("\n");
		colour(CFG.TextColourF, CFG.TextColourB);
		if (i) {
			/*         Messages imported */
			printf("%d %s\n", i, (char *)Language(454));
			ReadExitinfo();
			exitinfo.iPosted += i;
			WriteExitinfo();
			do_mailout = TRUE;
		}
		fflush(stdout);
		fclose(up);

		/*
		 *  Remove processed files.
		 */
		sprintf(temp, "%s/%s/%s.UPL", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		unlink(temp);
		temp = tl(temp);
		unlink(temp);
		sprintf(temp, "%s/%s/%s.UPI", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		unlink(temp);
		temp = tl(temp);
		unlink(temp);
		sprintf(temp, "%s/%s/%s.NET", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		unlink(temp);
		temp = tl(temp);
		unlink(temp);
	}

	/*
	 * If a .UPL file was not found it is possible we received an version 2
	 * reply packet.
	 */
	sprintf(temp, "%s/%s/%s.UPI", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if ((up = fopen(temp, "r")) == NULL) {
		temp = tl(temp);
		up = fopen(temp, "r");
	}
	if (up != NULL) {
		Syslog('+', "Received Version 2 .UPI packet, not supported");
		fclose(up);
	}
	sprintf(temp, "%s/%s/%s.NET", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if ((up = fopen(temp, "r")) == NULL) {
		temp = tl(temp);
		up = fopen(temp, "r");
	}
	if (up != NULL) {
		Syslog('+', "Received Version 2 .NET packet, not supported");
		fclose(up);
	}

	/*
	 *  Process offline configuration
	 */
	sprintf(temp, "%s/%s/%s.PDQ", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if ((tp = fopen(temp, "r")) == NULL) {
		temp = tl(temp);
		tp = fopen(temp, "r");
	}
	if (tp != NULL) {
		colour(9, 0);
		/*      Processing Offline Configuration */
		printf("%s\n", (char *)Language(455));
		Syslog('+', "Processing offline configuration");

		fread(&Pdh, sizeof(PDQ_HEADER), 1, tp);
		for (i = 0; i < 10; i++)
			if (strlen(Pdh.keywords[i]))
				Syslog('m', "  Kwrd %2d : %s", i+1, Pdh.keywords[i]);
		for (i = 0; i < 10; i++)
			if (strlen(Pdh.filters[i]))
				Syslog('m', "  Filt %2d : %s", i+1, Pdh.filters[i]);
		for (i = 0; i < 3; i++)
			if (strlen(Pdh.macros[i]))
				Syslog('m', "  Macro %d : %s", i+1, Pdh.macros[i]);
		Syslog('m', "  Pwtype  : %d", Pdh.passtype);
		Syslog('m', "  Flags   : %08x", Pdh.flags);

		/*
		 *  If the changes flag is set there are records with
		 *  active areas. Reset all areas first and then set
		 *  the active areas back on.
		 */
		if (Pdh.flags & PDQ_AREA_CHANGES) {
			Syslog('m', "  New Area Configuration present");
			i = 0;

			sprintf(temp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
			if ((up = fopen(temp, "r+")) != NULL) {

				sprintf(temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
				if ((mf = fopen(temp, "r")) != NULL) {

					fread(&msgshdr, sizeof(msgshdr), 1, mf);

					while (fread(&olrtagrec, sizeof(olrtagrec), 1, up) == 0) {
						fread(&msgs, msgshdr.recsize, 1, mf);
						fseek(mf, msgshdr.syssize, SEEK_CUR);
						if (!msgs.OLR_Forced)
							olrtagrec.Tagged = FALSE;
						fseek(up, - sizeof(olrtagrec), SEEK_CUR);
						fwrite(&olrtagrec, sizeof(olrtagrec), 1, up);
					}

					while (fread(&Pdr, sizeof(PDQ_REC), 1, tp) == 1) {
						if (strlen(Pdr.echotag)) {
							fseek(mf, msgshdr.hdrsize, SEEK_SET);
							fseek(up, 0, SEEK_SET);
							while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
								fseek(mf, msgshdr.syssize, SEEK_CUR);
								fread(&olrtagrec, sizeof(olrtagrec), 1, up);
								if ((strcmp(msgs.QWKname, Pdr.echotag) == 0) &&
								    (msgs.Active) &&
								    (Access(exitinfo.Security, msgs.RDSec))) {
									Syslog('m', "  Area %s", Pdr.echotag);
									olrtagrec.Tagged = TRUE;
									fseek(up, - sizeof(olrtagrec), SEEK_CUR);
									fwrite(&olrtagrec, sizeof(olrtagrec), 1, up);
									i++;
									break;
								}
							}
						}
					}
					fclose(mf);
					colour(3, 0);
					/*         Message areas selected */
					printf("%d %s\n", i, (char *)Language(456));
				}
				fclose(up);
			}
		}
		fclose(tp);
		sprintf(temp, "%s/%s/%s.PDQ", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
		unlink(temp);
	}

	/*
	 *  Check for .REQ file.
	 */
	sprintf(temp, "%s/%s/%s.REQ", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	if ((tp = fopen(temp, "r")) == NULL) {
		temp = tl(temp);
		tp = fopen(temp, "r");
	}
	if (tp != NULL) {
		i = 0;
		colour(9, 0);
		/*      Processing file requests */
		printf("%s\n", (char *)Language(457));
		Syslog('+', "Processing file requests");

		while (fread(&Req, sizeof(REQ_REC), 1, tp) == 1) {
			Syslog('m', "  File %s", Req.filename);
			colour(CFG.TextColourF, CFG.TextColourB);
			printf("%-12s ", Req.filename);
			colour(CFG.HiliteF, CFG.HiliteB);
			fflush(stdout);

			printf("\n");
		}

		fclose(tp);
	}

	free(temp);
	Pause();
}



/*
 *  Add one area to the BlueWave download packet
 */
unsigned long BlueWave_PackArea(unsigned long ulLast, long Area)
{
	FILE		*fdm, *fdfti, *fdmix;
	char		*Temp, *Text;
	unsigned long	Number;
	MIX_REC		Mix;
	FTI_REC		Fti;
	struct	tm	*tp;
	int		Pack;

	Number = ulLast;
	Temp = calloc(PATH_MAX, sizeof(char));

	sprintf(Temp, "%s/%s/tmp/%s.FTI", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	fdfti = fopen(Temp, "a+");

	sprintf(Temp, "%s/%s/tmp/%s.MIX", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	fdmix = fopen(Temp, "a+");

	sprintf(Temp, "%s/%s/tmp/%s.DAT", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
	fdm = fopen(Temp, "a+");

	memset(&Mix, 0, sizeof(MIX_REC));
	sprintf((char *)Mix.areanum, "%lu", Area);
	Mix.msghptr = ftell(fdfti);

	if ((fdfti != NULL) && (fdmix != NULL) && (fdm != NULL)) {
		if (Msg_Next(&Number)) {
			do {
				Msg_ReadHeader(Number);
				Msg_Read(Number, 78);
				Pack = TRUE;

				if ((strcasecmp(Msg.To, exitinfo.sUserName) == 0) ||
				    (strcasecmp(Msg.To, exitinfo.sHandle) == 0)) {
					Personal++;
					TotalPersonal++;
				} else if (msgs.Type == NETMAIL) {
					Pack = FALSE;
				} else if (msgs.MsgKinds == PRIVATE ) {
					Pack = FALSE;
				} else if (msgs.MsgKinds == BOTH ) {
					if (Msg.Private == TRUE ) Pack = FALSE;
                                }

				if (Pack) {
					Current++;
					Total++;
					memset (&Fti, 0, sizeof (FTI_REC));

					Msg.From[sizeof(Fti.from) - 1] = '\0';
					strcpy((char *)Fti.from, Msg.From);
					Msg.To[sizeof(Fti.to) - 1] = '\0';
					strcpy((char *)Fti.to, Msg.To);
					Msg.Subject[sizeof(Fti.subject) - 1] = '\0';
					strcpy((char *)Fti.subject, Msg.Subject);
					tp = localtime(&Msg.Written);
					sprintf((char *)Fti.date, "%2d %.3s %2d %2d:%02d:%02d", tp->tm_mday, 
						(char *) Language(398 + tp->tm_mon), tp->tm_year, 
						tp->tm_hour, tp->tm_min, tp->tm_sec);
					Fti.msgnum = Number;
					Fti.msgptr = ftell(fdm);
					Fti.replyto = Msg.Original;
					Fti.replyat = Msg.Reply;
					if (msgs.Type == NETMAIL) {
						Fti.orig_zone = msgs.Aka.zone;
						Fti.orig_net  = msgs.Aka.net;
						Fti.orig_node = msgs.Aka.node;
					}

					Fti.msglength += fwrite(" ", 1, 1, fdm);

					if ((Text = (char *)MsgText_First()) != NULL)
						do {
							if ((Text[0] != 0x01 && strncmp(Text, "SEEN-BY: ", 9))||
							    (strncmp(Text, "\001MSGID", 6) == 0) /* || 
							    (exitinfo.OL_ExtInfo) */ ) {
								Fti.msglength += fwrite(Text, 1, strlen(Text), fdm);
								Fti.msglength += fwrite("\r\n", 1, 2, fdm);
							}
						} while ((Text = (char *)MsgText_Next()) != NULL);

					fwrite(&Fti, sizeof (Fti), 1, fdfti);
				}

				if (BarWidth != (unsigned short)((Total * 61L) / TotalPack)) {
					BarWidth = (unsigned short)((Total * 61L) / TotalPack);
					colour(3, 0);
					printf("\r%.*s", BarWidth, "�������������������������������������������������������������");
					fflush(stdout);
				}
			} while (Msg_Next(&Number));
		}
	}

	Mix.totmsgs = (tWORD)Current;
	Mix.numpers = (tWORD)Personal;
	fwrite(&Mix, sizeof (Mix), 1, fdmix);

	if (fdfti != NULL)
		fclose(fdfti);
	if (fdmix != NULL)
		fclose(fdmix);
	if (fdm != NULL)
		fclose(fdm);

	free(Temp);
	return Number;
}



/***********************************************************************************
 *
 *  QWK specific functions
 *
 */



void OLR_DownQWK(void)
{
	struct	tm	*tp;
	time_t		Now;
	char		Pktname[32];
	long		Area = 0;
	char		*Work, *Temp;
	int		i, rc = 0;
	FILE		*fp = NULL, *tf, *mf, *af;
	unsigned long	Start, High;
	msg_high	*tmp, *mhl = NULL;

	if (!OLR_Prescan())
		return;

	Total = TotalPersonal = 0L;
	clear();
	colour(9, 0);
	/*      QWK Offline Download */
	printf("%s\n", (char *)Language(458));

	Work = calloc(PATH_MAX, sizeof(char));
	Temp = calloc(PATH_MAX, sizeof(char));

	Now = time(NULL);
	tp = localtime(&Now);
	Syslog('+', "Preparing QWK packet");

	sprintf(Temp, "%s.QWK", CFG.bbsid);
	sprintf(Pktname, "%s", tl(Temp));
	Syslog('m', "Packet name %s", Pktname);
	sprintf(Work, "%s/%s/tmp", CFG.bbs_usersdir, exitinfo.Name);
	Syslog('m', "Work path %s", Work);

	sprintf(Temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	if ((mf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		return;
	}
	fread(&msgshdr, sizeof(msgshdr), 1, mf);

	sprintf(Temp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	if ((tf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		fclose(mf);
		return;
	}

	Area = 0;
	DrawBar(Pktname);
	fseek(mf, sizeof(msgshdr), SEEK_SET);
	fseek(tf, 0, SEEK_SET);

	while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
		fseek(mf, msgshdr.syssize, SEEK_CUR);
		fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
		Area++;
		if (olrtagrec.Tagged) {
			if (Msg_Open(msgs.Base)) {
				Current = Personal = 0;
				if (Msg_Highest() != 0) {
					memset(&LR, 0, sizeof(LR));
					LR.UserID = grecno;
					if (Msg_GetLastRead(&LR))
						Start = LR.HighReadMsg;
					else
						Start = Msg_Lowest() -1;
					if (Start > Msg_Highest())
						Start = Msg_Highest();
					if (Start < Msg_Highest()) {
						Syslog('m', "First %lu, Last %lu, Start %lu", Msg_Lowest(), Msg_Highest(), Start);
						High = QWK_PackArea(Start, Area);
						fill_high(&mhl, Area, High, Personal);
					}
				}
				Syslog('+', "Area %-20s %5ld (%ld personal)", msgs.QWKname, Current, Personal);
				Msg_Close();
			}
		}
	}

	sprintf(Temp, "%s/CONTROL.DAT", Work);
	if ((fp = fopen(Temp, "w+")) != NULL) {
		fprintf(fp, "%s\n", CFG.bbs_name);
		fprintf(fp, "%s\n", CFG.location);
		fprintf(fp, "%s\n", CFG.Phone);
		fprintf(fp, "%s\n", CFG.sysop_name);
		fprintf(fp, "00000,%s\n", CFG.bbsid);
		
		fprintf(fp, "%02d-%02d-%04d,%02d:%02d:%02d\n", tp->tm_mday, tp->tm_mon+1, tp->tm_year+1900, 
				tp->tm_hour, tp->tm_min, tp->tm_sec);
		sprintf(Temp, "%s", exitinfo.sUserName);
		fprintf(fp, "%s\n", tu(Temp));
		fprintf(fp, " \n");
		fprintf(fp, "0\n");
		fprintf(fp, "%lu\n", Total);

		/*
		 * Count available areas.
		 */
		i = 0;
		fseek(mf, msgshdr.hdrsize, SEEK_SET);
		fseek(tf, 0, SEEK_SET);
		while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
			fseek(mf, msgshdr.syssize, SEEK_CUR);
			if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && strlen(msgs.QWKname))
				i++;
		}
		fprintf(fp, "%d\n", i - 1);

		/*
		 * Write available areas
		 */
		i = 0;
		fseek(mf, msgshdr.hdrsize, SEEK_SET);
		fseek(tf, 0, SEEK_SET);
		while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
			fseek(mf, msgshdr.syssize, SEEK_CUR);
			i++;
			if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) && strlen(msgs.QWKname)) {
				fprintf(fp, "%d\n%s\n", i, msgs.QWKname);
			}
		}

		fprintf(fp, "WELCOME\n");
		fprintf(fp, "NEWS\n");
		fprintf(fp, "GOODBYE\n");
		fclose(fp);	
	}

	sprintf(Temp, "%s/DOOR.ID", Work);
	if ((fp = fopen(Temp, "w+")) != 0) {
		fprintf(fp, "DOOR = MBSE BBS QWK\n");
		fprintf(fp, "VERSION = %s\n", VERSION);
		fprintf(fp, "SYSTEM = %s\n", CFG.bbs_name);
		fprintf(fp, "CONTROLNAME = MBSEQWK\n");
		fprintf(fp, "CONTROLTYPE = ADD\n");
		fprintf(fp, "CONTROLTYPE = DROP\n");
		fclose(fp);
	}

	Syslog('+', "Packed %ld messages (%ld personal)", Total, TotalPersonal);
	fclose(tf);

	if (Total) {
		/*        Packing with */
		printf("\n%s ", (char *)Language(446));
		sprintf(Temp, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
		if ((af = fopen(Temp, "r")) != NULL) {
			fread(&archiverhdr, sizeof(archiverhdr), 1, af);
			while (fread(&archiver, archiverhdr.recsize, 1, af) == 1) {
				if (archiver.available && (!strcmp(archiver.name, exitinfo.Archiver))) {
					Syslog('+', "Archiver %s", archiver.comment);
					printf("%s ", archiver.comment);
					sprintf(Temp, "%s/CONTROL.DAT", Work);
					AddArc(Temp, Pktname);
					alarm_on();
					sprintf(Temp, "%s/MESSAGES.DAT", Work);
					AddArc(Temp, Pktname);

					for (tmp = mhl; tmp; tmp = tmp->next) {
						sprintf(Temp, "%s/%03ld.NDX", Work, tmp->Area);
						AddArc(Temp, Pktname);
					}

					sprintf(Temp, "%s/PERSONAL.NDX", Work);
					if (TotalPersonal) {
						AddArc(Temp, Pktname);
					} else
						unlink(Temp);

					sprintf(Temp, "%s/DOOR.ID", Work);
					AddArc(Temp, Pktname);
					sprintf(Temp, "%s/%s/%s", CFG.bbs_usersdir, exitinfo.Name, Pktname);
					rc = DownloadDirect(Temp, FALSE);
					Syslog('m', "Download result %d", rc);
					unlink(Temp);
				}
			}
			fclose(af);
		}
	}

	colour(CFG.HiliteF, CFG.HiliteB);
	if (rc == FALSE) {
		Syslog('+', "QWK download failed");
		/*      Download failed */
		printf("%s", (char *)Language(447));
	} else {
		Syslog('+', "QWK download successfull");
		/*        Download successfull */
		printf("\r%s\n", (char *)Language(448));

		if (mhl != NULL)
			UpdateLR(mhl, mf);
	}
	fclose(mf);
	tidy_high(&mhl);

	free(Temp);
	free(Work);
	printf("\n\n");
	Pause();
}



/*
 *  QWK Fetch Reply packet
 */
void QWK_Fetch()
{
	char		*temp, *otemp, Temp[128], szLine[132], *pLine = NULL, *pBuff;
	FILE		*up, *op, *mf;
	unsigned short	nRec, i, r, x, nCol = 0, nWidth, nReaded, nPosted = 0;
	unsigned long	Area;
	struct tm	*ltm = NULL;
	fidoaddr	dest;

	colour(9, 0);
	/*      Processing BlueWave reply packet */
	printf("%s\n", (char *)Language(459));
	temp = calloc(2048, sizeof(char));
	otemp = calloc(PATH_MAX, sizeof(char));
	nWidth = 78;

        sprintf(temp, "%s/%s/%s.MSG", CFG.bbs_usersdir, exitinfo.Name, CFG.bbsid);
        if ((up = fopen(temp, "r")) == NULL) {
                temp = tl(temp);
                up = fopen(temp, "r");
        }

        if (up != NULL) {
		Syslog('+', "Processing QWK file %s", temp);

		fread(&Temp, 128, 1, up);
		Temp[8] = '\0';
		if (strcmp(CFG.bbsid, StripSpaces(Temp, 8))) {
			Syslog('?', "Wrong QWK packet id: \"%s\"", StripSpaces(Temp, 8));
			fclose(up);
			unlink(temp);
			/*      ERROR in packet */
			printf("%s\n", (char *)Language(451));
			free(temp);
			free(otemp);
			Pause();
			return;
		}

		while (fread(&Qwk, sizeof(Qwk), 1, up) == 1) {
			Area = atol(StripSpaces(Qwk.Msgnum, sizeof(Qwk.Msgnum)));
			nRec = atoi(StripSpaces(Qwk.Msgrecs, sizeof(Qwk.Msgrecs)));

			/*
			 * Test for blank records.
			 */
			if (Area && nRec) {
				Syslog('m', "Conference %u", Area);
				Syslog('m', "Records    %d", nRec);
				Syslog('m', "To         %s", tlcap(StripSpaces(Qwk.MsgTo, sizeof(Qwk.MsgTo))));
				Syslog('m', "From       %s", tlcap(StripSpaces(Qwk.MsgFrom, sizeof(Qwk.MsgFrom))));
				Syslog('m', "Subject    %s", StripSpaces(Qwk.MsgSubj, sizeof(Qwk.MsgSubj)));
				sprintf(Temp, "%s", StripSpaces(Qwk.Msgdate, sizeof(Qwk.Msgdate)));
				Syslog('m', "Date       %s %s", Temp, StripSpaces(Qwk.Msgtime, sizeof(Qwk.Msgtime)));

				if (strcmp("MBSEQWK", StripSpaces(Qwk.MsgTo, sizeof(Qwk.MsgTo))) == 0) {
					Syslog('m', "Command %s", StripSpaces(Qwk.MsgSubj, sizeof(Qwk.MsgSubj)));
					sprintf(otemp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
					if ((op = fopen(otemp, "r+")) != NULL) {

						sprintf(otemp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
						if ((mf = fopen(otemp, "r")) != NULL) {
							fread(&msgshdr, sizeof(msgshdr), 1, mf);
							fseek(mf, ((Area -1) * (msgshdr.recsize + msgshdr.syssize)) + 
										msgshdr.hdrsize, SEEK_SET);
							fread(&msgs, msgshdr.recsize, 1, mf);
							fseek(op, (Area -1) * sizeof(olrtagrec), SEEK_SET);
							fread(&olrtagrec, sizeof(olrtagrec), 1, op);

							if (strcmp("ADD", StripSpaces(Qwk.MsgSubj, sizeof(Qwk.MsgSubj))) == 0) {
								if (msgs.Active && Access(exitinfo.Security, msgs.RDSec) &&
								    strlen(msgs.QWKname) && !olrtagrec.Tagged) {
									olrtagrec.Tagged = TRUE;
									fseek(op, - sizeof(olrtagrec), SEEK_CUR);
									Syslog('m', "%d", fwrite(&olrtagrec, sizeof(olrtagrec), 1, op));
									Syslog('+', "QWK added area   %s", msgs.QWKname);
								}
							}

							if (strcmp("DROP", StripSpaces(Qwk.MsgSubj, sizeof(Qwk.MsgSubj))) == 0) {
								if (!msgs.OLR_Forced && olrtagrec.Tagged) {
									olrtagrec.Tagged = FALSE;
									fseek(op, - sizeof(olrtagrec), SEEK_CUR);
									fwrite(&olrtagrec, sizeof(olrtagrec), 1, op);
									Syslog('+', "QWK dropped area %s", msgs.QWKname);
								}
							}

							fclose(mf);
						}
						fclose(op);
					}
				} else {
					/*
					 * Normal message
					 */
					Syslog('m', "Message");
					sprintf(otemp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
					if ((mf = fopen(otemp, "r+")) != NULL) {
						fread(&msgshdr, sizeof(msgshdr), 1, mf);
						fseek(mf, ((Area -1) * (msgshdr.recsize + msgshdr.syssize)) +
									msgshdr.hdrsize, SEEK_SET);
						fread(&msgs, msgshdr.recsize, 1, mf);

						/*
						 * Check access to this area
						 */
						if (msgs.Active && strlen(msgs.QWKname) && Access(exitinfo.Security, msgs.WRSec) &&
						    (msgs.MsgKinds != RONLY)) {
							if (Open_Msgbase(msgs.Base, 'w')) {
								Msg_New();
								pLine = szLine;
								nCol = 0;
								Syslog('m', "Msgbase open and locked");
								strcpy(Msg.From, tlcap(StripSpaces(Qwk.MsgFrom, sizeof(Qwk.MsgFrom))));
								strcpy(Msg.To, tlcap(StripSpaces(Qwk.MsgTo, sizeof(Qwk.MsgTo))));
								strcpy(Msg.Subject, StripSpaces(Qwk.MsgSubj, sizeof(Qwk.MsgSubj)));
								if ((Qwk.Msgstat == '*') || (Qwk.Msgstat == '+'))
									Msg.Private = TRUE;
								strcpy(Temp, StripSpaces(Qwk.Msgdate, sizeof(Qwk.Msgdate)));
								ltm = malloc(sizeof(struct tm));
								memset(ltm, 0, sizeof(struct tm));
								ltm->tm_mday = atoi(&Temp[3]);
								ltm->tm_mon = atoi(&Temp[0]) -1;
								ltm->tm_year = atoi(&Temp[6]);
								if (ltm->tm_year < 96)
									ltm->tm_year += 100;
								strcpy(Temp, StripSpaces(Qwk.Msgtime, sizeof(Qwk.Msgtime)));
								ltm->tm_hour = atoi(&Temp[0]);
								ltm->tm_min = atoi(&Temp[3]);
								ltm->tm_sec = 0;
								Msg.Written = mktime(ltm);
								free(ltm);
								Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60);
								Msg.Local  = TRUE;
								memset(&dest, 0, sizeof(dest));
//								dest.zone  = Upr.destzone;
//								dest.net   = Upr.destnet;
//								dest.node  = Upr.destnode;
//								dest.point = Upr.destpoint;
								Add_Headkludges(fido2faddr(dest), FALSE);

								for (r = 1; r < nRec; r++) {
									nReaded = fread(Temp, 1, 128, up);
									Syslog('m', "nReaded=%d", nReaded);
									if (r == (nRec - 1)) {
										x = 127;
										while (x > 0 && Temp[x] == ' ') {
											nReaded--;
											x--;
										}
										Syslog('m', "Final=%d", nReaded);
									}

									for (i = 0, pBuff = Temp; i < nReaded; i++, pBuff++) {
										if (*pBuff == '\r' || *pBuff == (char)0xE3) {
											*pLine = '\0';
											Syslog('m', "1 Len=%d \"%s\"", strlen(szLine), printable(szLine, 0));
											MsgText_Add2(szLine);
											pLine = szLine;
											nCol = 0;
										} else if (*pBuff != '\n') {
											*pLine++ = *pBuff;
											nCol++;
											if (nCol >= nWidth) {
												*pLine = '\0';
												while (nCol > 1 && *pLine != ' ') {
													nCol--;
													pLine--;
												}
												if (nCol > 0) {
													while (*pLine == ' ')
														pLine++;
													strcpy (szWrp, pLine);
												}
												*pLine = '\0';
												Syslog('m', "2 Len=%d \"%s\"", strlen(szLine), printable(szLine, 0));
												MsgText_Add2(szLine);
												strcpy(szLine, szWrp);
												pLine = strchr(szLine, '\0');
												nCol = (short)strlen (szLine);
											}
										}
									}
								}
								if (nCol > 0) {
									*pLine = '\0';
									Syslog('m', "3 Len=%d \"%s\"", strlen(szLine), printable(szLine, 0));
									MsgText_Add2(szLine);
								}

								Add_Footkludges(FALSE);
								Msg_AddMsg();

								Syslog('+', "Msg (%ld) to \"%s\", \"%s\", in %s", Msg.Id, 
											Msg.To, Msg.Subject, msgs.QWKname);
								nPosted++;
								Close_Msgbase();
								Syslog('m', "Msgbase closed again");
								fseek(mf, ((Area -1) * (msgshdr.recsize + msgshdr.syssize)) +
									msgshdr.hdrsize, SEEK_SET);
								msgs.Posted.total++;
								msgs.Posted.tweek++;
								msgs.Posted.tdow[Diw]++;
								msgs.Posted.month[Miy]++;
								msgs.LastPosted = time(NULL);
								fwrite(&msgs, msgshdr.recsize, 1, mf);
							}
						} else {
							Syslog('+', "Can't post messages in area %u", Area);
						}
						fclose(mf);
					}
				}
			} else {
				Syslog('m', "Skip blank record");
			}
		}

		fclose(up);
	}

	printf("\n");
	colour(CFG.TextColourF, CFG.TextColourB);
	if (nPosted) {
		/*         Messages imported */
		printf("%d %s\n", nPosted, (char *)Language(454));
		ReadExitinfo();
		exitinfo.iPosted += nPosted;
		WriteExitinfo();
		do_mailout = TRUE;
	}
	fflush(stdout);
	unlink(temp);
	free(temp);
	free(otemp);
	Pause();
}



union Converter {
	unsigned char	uc[10];
	unsigned short	ui[5];
	unsigned long	ul[2];
	float		f[2];
	double		d[1];
};



float IEEToMSBIN(float f)
{
	int		sign, exp;
	union Converter	t;

	t.f[0] = f;
	sign = t.uc[3] / 0x80;
	exp = ((t.ui[1] >> 7) - 0x7F + 0x81) & 0xFF;
	t.ui[1] = (t.ui[1] & 0x7F) | (sign << 7) | (exp << 8);

	return t.f[0];
}



float MSBINToIEEE(float f)
{
	union Converter	t;
	int		sign, exp;

	t.f[0] = f;
	sign = t.uc[2] / 0x80;
	exp  = (t.uc[3] - 0x81 + 0x7f) & 0xff;
	t.ui[1] = (t.ui[1] & 0x7f) | (exp << 7) | (sign << 15);
	return t.f[0];
}



/*
 * Pack messages in one mail area
 */
unsigned long QWK_PackArea(unsigned long ulLast, long Area)
{
	FILE		*fdm, *fdi, *fdp;
	float		out, in;
	char		*Work, *Temp, *Text;
	unsigned long	Number, Pos, Size, Blocks;
	int		Pack = FALSE;
	struct tm	*tp;

	Number = ulLast;
	Current = Personal = 0L;

	Temp = calloc(PATH_MAX, sizeof(char));
	Work = calloc(PATH_MAX, sizeof(char));
	sprintf(Work, "%s/%s/tmp", CFG.bbs_usersdir, exitinfo.Name);

	sprintf(Temp, "%s/%03ld.NDX", Work, Area);
	fdi = fopen(Temp, "a+");

	sprintf(Temp, "%s/PERSONAL.NDX", Work);
	fdp = fopen(Temp, "a+");

	/*
	 * Open MESSAGES.DAT, if it doesn't exist, create it and write
	 * the header. Then reopen the file in r/w mode.
	 */
	sprintf(Temp, "%s/MESSAGES.DAT", Work);
	if ((fdm = fopen (Temp, "r+")) == NULL) {
		Syslog('m', "Creating new %s", Temp);
		fdm = fopen(Temp, "a+");
		// ----------------------------------------------------------------------
		// The first record of the MESSAGE.DAT file must be the Sparkware id
		// block, otherwise some applications may complain.
		// ----------------------------------------------------------------------
		fprintf(fdm, "Produced by Qmail...");
		fprintf(fdm, "Copywright (c) 1987 by Sparkware.  ");
		fprintf(fdm, "All Rights Reserved");
		memset(Temp, ' ', 54);
		fwrite(Temp, 54, 1, fdm);
		fclose(fdm);
		sprintf(Temp, "%s/MESSAGES.DAT", Work);
		fdm = fopen(Temp, "r+");
	}

	if ((fdm != NULL) && (fdp != NULL) && (fdi != NULL)) {
		fseek(fdm, 0, SEEK_END);
		if (Msg_Next(&Number)) {
			do {
				Msg_ReadHeader(Number);
				Msg_Read(Number, 78);
				Pack = TRUE;
				if ((strcasecmp(Msg.To, exitinfo.sUserName) == 0) ||
				    (strcasecmp(Msg.To, exitinfo.sHandle) == 0)) {
					Personal++;
					TotalPersonal++;
					fwrite(&out, sizeof(float), 1, fdp);
					fwrite("", 1, 1, fdp);
				} else if (msgs.Type == NETMAIL) {
					Pack = FALSE;
				} else if (msgs.MsgKinds == PRIVATE ) {
					Pack = FALSE;
				} else if (msgs.MsgKinds == BOTH ) {
					if (Msg.Private == TRUE ) Pack = FALSE;
				}

				if (Pack) {
					/*
					 * Calculate the recordnumber from the current file
					 * position and store it in M$oft BIN format.
					 */
                                        Pos = ftell(fdm);
					Blocks = (Pos / 128L) + 1L;
					sprintf(Temp, "%lu", Blocks);
					in = atof(Temp);
					out = IEEToMSBIN(in);
					fwrite(&out, sizeof(float), 1, fdi);
					fwrite(" ", 1, 1, fdi);
					Current++;
					Total++;

					memset(&Qwk, ' ', sizeof(Qwk));
					sprintf(Temp, "%-*lu", sizeof(Qwk.Msgnum), (long)Number);
					Syslog('M', "Message %s", Temp);
					memcpy(Qwk.Msgnum, Temp, sizeof(Qwk.Msgnum));
					tp = localtime(&Msg.Written);
					sprintf(Temp, "%02d-%02d-%02d", tp->tm_mon+1, tp->tm_mday, tp->tm_year % 100);
					memcpy(Qwk.Msgdate, Temp, sizeof(Qwk.Msgdate));
					sprintf(Temp, "%02d:%02d", tp->tm_hour, tp->tm_min);
					memcpy(Qwk.Msgtime, Temp, sizeof(Qwk.Msgtime));
					Msg.From[sizeof(Qwk.MsgFrom) - 1] = '\0';
					memcpy(Qwk.MsgFrom, Msg.From, strlen(Msg.From));
					Msg.To[sizeof(Qwk.MsgTo) - 1] = '\0';
					memcpy(Qwk.MsgTo, Msg.To, strlen(Msg.To));
					Msg.Subject[sizeof(Qwk.MsgSubj) - 1] = '\0';
					memcpy(Qwk.MsgSubj, Msg.Subject, strlen(Msg.Subject));
					Qwk.Msglive = 0xE1;
					Qwk.Msgarealo = (unsigned char)(Area & 0xFF);
					Qwk.Msgareahi = (unsigned char)((Area & 0xFF00) >> 8);
					fwrite(&Qwk, sizeof(Qwk), 1, fdm);
					Size = 128L;
					if ((Text = (char *)MsgText_First()) != NULL) {
						do {
							if (Text[0] != 0x01 && strncmp(Text, "SEEN-BY: ", 9)) {
								Size += fwrite(Text, 1, strlen(Text), fdm);
								Size += fwrite("\xE3", 1, 1, fdm);
							}
						} while ((Text = (char *)MsgText_Next()) != NULL);

						if ((Size % 128L) != 0) {
							memset(Temp, ' ', 128);
							Size += fwrite(Temp, (int)(128L - (Size % 128L)), 1, fdm);
						}

						sprintf(Qwk.Msgrecs, "%-*lu", sizeof(Qwk.Msgrecs), (long)((ftell(fdm) - Pos) / 128L));
						fseek(fdm, Pos, SEEK_SET);
						fwrite(&Qwk, sizeof(Qwk), 1, fdm);
						fseek(fdm, 0L, SEEK_END);
						if ((Total % 16L) == 0L)
							usleep(1);
					}

					if (BarWidth != (unsigned short)((Total * 61L) / TotalPack)) {
						BarWidth = (unsigned short)((Total * 61L) / TotalPack);
						colour(3, 0);
						printf("\r%.*s", BarWidth, "�������������������������������������������������������������");
						fflush(stdout);
					}
				}
			} while (Msg_Next(&Number));
		}
	} else {
		WriteError("Not all files open");
	}

	if (fdm != NULL)
		fclose(fdm);
	if (fdi != NULL)
		fclose(fdi);
	if (fdp != NULL)
		fclose(fdp);
	free(Work);
	free(Temp);

	return Number;
}



char *StripSpaces(char *String, int Size)
{
	int	x;

	memcpy(TempStr, String, Size);
	TempStr[Size] = '\0';
	if ((x = (Size - 1)) > 0) {
		while (x > 0 && TempStr[x] == ' ')
			TempStr[x--] = '\0';
	}

	return TempStr;
}


/*****************************************************************************
 *
 *  ASCII Offline Functions
 *
 */


void OLR_DownASCII(void)
{
	struct  tm      *tp;
	time_t          Now;
	char            Pktname[32];
	long            Area = 0;
	char            *Work, *Temp;
	int             rc = 0;
	FILE            *fp = NULL, *tf, *mf, *af;
	unsigned long   Start, High;
	msg_high        *tmp, *mhl = NULL;

	if (!OLR_Prescan())
		return;

	Total = TotalPersonal = 0L;
	clear();
	colour(9, 0);
	/*      ASCII Offline Download */
	printf("%s\n", (char *)Language(460));

	Work = calloc(PATH_MAX, sizeof(char));
	Temp = calloc(PATH_MAX, sizeof(char));
	
	Now = time(NULL);
	tp = localtime(&Now);
	Syslog('+', "Preparing ASCII packet");

	sprintf(Temp, "%s.MSG", CFG.bbsid);
	sprintf(Pktname, "%s", tl(Temp));
	sprintf(Work, "%s/%s/tmp", CFG.bbs_usersdir, exitinfo.Name);

	sprintf(Temp, "%s/etc/mareas.data", getenv("MBSE_ROOT"));
	if ((mf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		return;
	}
	fread(&msgshdr, sizeof(msgshdr), 1, mf);

	sprintf(Temp, "%s/%s/.olrtags", CFG.bbs_usersdir, exitinfo.Name);
	if ((tf = fopen(Temp, "r")) == NULL) {
		WriteError("$Can't open %s", Temp);
		fclose(fp);
		fclose(mf);
		return;
	}

	Area = 0;
	DrawBar(Pktname);
	fseek(mf, sizeof(msgshdr), SEEK_SET);
	fseek(tf, 0, SEEK_SET);

	while (fread(&msgs, msgshdr.recsize, 1, mf) == 1) {
		fseek(mf, msgshdr.syssize, SEEK_CUR);
		fread(&olrtagrec, sizeof(olrtagrec), 1, tf);
		Area++;
		if (olrtagrec.Tagged) {
			if (Msg_Open(msgs.Base)) {
				Current = Personal = 0;
				if (Msg_Highest() != 0) {
					memset(&LR, 0, sizeof(LR));
					LR.UserID = grecno;
					if (Msg_GetLastRead(&LR))
						Start = LR.HighReadMsg;
					else
						Start = Msg_Lowest() -1;
					if (Start > Msg_Highest())
						Start = Msg_Highest();
					if (Start < Msg_Highest()) {
						High = ASCII_PackArea(Start, Area);
						fill_high(&mhl, Area, High, Personal);
					}
				}
				Syslog('+', "Area %-20s %5ld (%ld personal)", msgs.QWKname, Current, Personal);
				Msg_Close();
			}
		}
	}

	if (Total) {
		/*        Packing with */
		printf("\n%s ", (char *)Language(446));
		sprintf(Temp, "%s/etc/archiver.data", getenv("MBSE_ROOT"));
		if ((af = fopen(Temp, "r")) != NULL) {
			fread(&archiverhdr, sizeof(archiverhdr), 1, af);
			while (fread(&archiver, archiverhdr.recsize, 1, af) == 1) {
				if (archiver.available && (!strcmp(archiver.name, exitinfo.Archiver))) {
					Syslog('+', "Archiver %s", archiver.comment);
					printf("%s ", archiver.comment);
					alarm_on();

					for (tmp = mhl; tmp; tmp = tmp->next) {
						sprintf(Temp, "%s/%03ld.TXT", Work, tmp->Area);
						AddArc(Temp, Pktname);
					}
					sprintf(Temp, "%s/%s/%s", CFG.bbs_usersdir, exitinfo.Name, Pktname);
					rc = DownloadDirect(Temp, FALSE);
					unlink(Temp);
				}
			}
			fclose(af);
		}
	}

	colour(CFG.HiliteF, CFG.HiliteB);
	if (rc == FALSE) {
		Syslog('+', "ASCII download failed");
		/*      Download failed */
		printf("%s", (char *)Language(447));
	} else {
		Syslog('+', "ASCII download successfull");
		/*        Download successfull */
		printf("\r%s\n", (char *)Language(448));

		if (mhl != NULL)
			UpdateLR(mhl, mf);
	}
	fclose(mf);
	tidy_high(&mhl);
	free(Temp);
	free(Work);
	printf("\n\n");
	Pause();
}



/*
 * Pack messages in one mail area
 */
unsigned long ASCII_PackArea(unsigned long ulLast, long Area)
{
        FILE            *fp;
        char            *Work, *Temp, *Text;
        unsigned long   Number;
        int             Pack = FALSE;
        struct tm       *tp;

        Number = ulLast;
        Current = Personal = 0L;

	Temp = calloc(128, sizeof(char));
        Work = calloc(128, sizeof(char));
        sprintf(Work, "%s/%s/tmp", CFG.bbs_usersdir, exitinfo.Name);

        sprintf(Temp, "%s/%03ld.TXT", Work, Area);
        if ((fp = fopen(Temp, "a+")) != NULL) {
		if (Msg_Next(&Number)) {
			do {
				Msg_ReadHeader(Number);
				Msg_Read(Number, 78);
				Pack = TRUE;
				if ((strcasecmp(Msg.To, exitinfo.sUserName) == 0) ||
                                    (strcasecmp(Msg.To, exitinfo.sHandle) == 0)) {
                                        Personal++;
                                        TotalPersonal++;
				} else if (msgs.Type == NETMAIL) {
					Pack = FALSE;
				} else if ( msgs.MsgKinds == PRIVATE ) {
					Pack = FALSE;
				} else if (msgs.MsgKinds == BOTH ) {
					if ( Msg.Private == TRUE ) Pack = FALSE;
				}

                                if (Pack) {
					fprintf (fp, "\n==============================================\n    Msg. #%ld of %ld (%s)\n", Number, Msg_Number(), msgs.Name);
					tp = localtime(&Msg.Written);
					fprintf (fp, "   Date: %d %s %d %2d:%02d\n", tp->tm_mday, 
						GetMonth(tp->tm_mon + 1), tp->tm_year, tp->tm_hour, tp->tm_min);
					fprintf (fp, "   From: %s\n", Msg.From);
					if (Msg.To[0])
						fprintf (fp, "     To: %s\n", Msg.To);
					fprintf (fp, "Subject: %s\n----------------------------------------------\n", Msg.Subject);
					Current++;
					Total++;

					if ((Text = (char *)MsgText_First()) != NULL) {
						do {
							if (Text[0] != 0x01 && strncmp(Text, "SEEN-BY: ", 9))
								fprintf(fp, "%s\n", Text);
						} while ((Text = (char *)MsgText_Next()) != NULL);
					}

					if ((Total % 16L) == 0L)
						usleep(1);

					if (BarWidth != (unsigned short)((Total * 61L) / TotalPack)) {
						BarWidth = (unsigned short)((Total * 61L) / TotalPack);
						colour(3, 0);
						printf("\r%.*s", BarWidth, "�������������������������������������������������������������");
						fflush(stdout);
					}
				}
			} while (Msg_Next(&Number));
		}
		fclose(fp);
	} else {
		WriteError("Not all files open");
	}

        free(Work);
	free(Temp);
        return Number;
}