/*
**	OldConfig.c
**
**	Old configuration processing routines
**
**	Copyright © 1990-1996 by Olaf `Olsen' Barthel
**		All Rights Reserved
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

struct OldSerialSettings
{
	ULONG	BaudRate;
	ULONG	BreakLength;
	ULONG	SerialBufferSize;

	UBYTE	SerialDevice[256];
	LONG	UnitNumber;

	BOOLEAN	BitsPerChar;
	BOOLEAN	Parity;
	BOOLEAN	StopBits;
	BOOLEAN	HandshakingProtocol;
	BOOLEAN	Duplex;

	BOOLEAN	xONxOFF;
	BOOLEAN	HighSpeed;
	BOOLEAN	Shared;
	BOOLEAN	StripBit8;
	BOOLEAN	CheckCarrier;
	BOOLEAN	PassThrough;
};

struct OldModemSettings
{
	UBYTE	ModemInit[80];
	UBYTE 	ModemExit[80];
	UBYTE 	ModemHangup[80];
	UBYTE	DialPrefix[80];
	UBYTE	DialSuffix[80];

	UBYTE	NoCarrier[16];
	UBYTE	NoDialTone[16];
	UBYTE	Connect[16];
	UBYTE	Voice[16];
	UBYTE	Ring[16];
	UBYTE	Busy[16];

	LONG	RedialDelay;
	LONG	DialRetries;
	LONG	DialTimeout;
	BOOLEAN	ConnectAutoBaud;
	BOOLEAN	DropDTR;
};

struct OldCommandSettings
{
	UBYTE	StartupMacro[256];
	UBYTE	LogoffMacro[256];
	UBYTE	UploadMacro[256];
	UBYTE	DownloadMacro[256];
};

struct OldScreenSettings
{
	ULONG	DisplayMode;
	WORD	ColourMode;
	UWORD	Colours[16];
	UBYTE	FontName[256];
	WORD	FontHeight;

	BOOLEAN	MakeScreenPublic;
	BOOLEAN	ShanghaiWindows;

	BOOLEAN	Blinking;
	BOOLEAN	FasterLayout;
	BOOLEAN	TitleBar;
	BOOLEAN	StatusLine;
};

struct OldTerminalSettings
{
	BOOLEAN	BellMode;
	BOOLEAN	AlertMode;
	BOOLEAN	EmulationMode;
	BOOLEAN	FontMode;

	BOOLEAN	SendCR;
	BOOLEAN	SendLF;
	BOOLEAN	ReceiveCR;
	BOOLEAN	ReceiveLF;

	UWORD	NumColumns,
		NumLines;

	UBYTE	KeyMapFileName[256];
	UBYTE	EmulationFileName[256];
	UBYTE	BeepFileName[256];

	UBYTE	TextFontName[256];
	WORD	TextFontHeight;
};

struct OldPathSettings
{
	UBYTE	ASCIIUploadPath[256];
	UBYTE	ASCIIDownloadPath[256];

	UBYTE	TextUploadPath[256];
	UBYTE	TextDownloadPath[256];

	UBYTE	BinaryUploadPath[256];
	UBYTE	BinaryDownloadPath[256];

	UBYTE	DefaultStorage[256];

	UBYTE	Editor[256];
};

struct OldMiscSettings
{
	BOOLEAN	Priority;
	BOOLEAN	BackupConfig;

	BOOLEAN	OpenFastMacroPanel;
	BOOLEAN	ReleaseDevice;

	BOOLEAN	TransferServer;
	BOOLEAN	EmulationServer;

	BOOLEAN	OverridePath;
	BOOLEAN	AutoUpload;
	BOOLEAN	SetArchivedBit;
	BOOLEAN	IdentifyFiles;
};

struct OldClipSettings
{
	WORD	ClipboardUnit;

	WORD	LineDelay,
		CharDelay;

	UBYTE	InsertPrefix[80];
	UBYTE	InsertSuffix[80];
};

struct OldCaptureSettings
{
	BOOLEAN	LogActions;
	BOOLEAN	LogCall;
	UBYTE	LogFileName[256];

	LONG	MaxBufferSize;
	BOOLEAN	BufferEnabled;

	BOOLEAN	ConnectAutoCapture;
	BOOLEAN	CaptureFilterMode;
	UBYTE	CapturePath[256];
};

struct OldFileSettings
{
	UBYTE	ProtocolFileName[256];
	UBYTE	TranslationFileName[256];
	UBYTE	MacroFileName[256];
	UBYTE	CursorFileName[256];
	UBYTE	FastMacroFileName[256];
};

struct OldEmulationSettings
{
	BOOLEAN	CursorMode;
	BOOLEAN	NumericMode;

	BOOLEAN	CursorWrap;
	BOOLEAN	LineWrap;

	BOOLEAN	InsertMode;
	BOOLEAN	NewLineMode;

	BOOLEAN	FontScale;
	BOOLEAN	ScrollMode;
	BOOLEAN	DestructiveBackspace;
	BOOLEAN	SwapBSDelete;
	BOOLEAN	PrinterEnabled;
	BOOLEAN	Pad;

	UBYTE	AnswerBack[80];
};

struct OldConfiguration
{
	struct OldSerialSettings	SerialConfig;
	struct OldModemSettings		ModemConfig;
	struct OldScreenSettings	ScreenConfig;
	struct OldTerminalSettings	TerminalConfig;
	struct OldEmulationSettings	EmulationConfig;
	struct OldClipSettings		ClipConfig;
	struct OldCaptureSettings	CaptureConfig;
	struct OldCommandSettings	CommandConfig;
	struct OldMiscSettings		MiscConfig;
	struct OldPathSettings		PathConfig;
	struct OldFileSettings		FileConfig;
};

struct OldPhoneHeader
{
	UBYTE	Name[40],		/* BBS name. */
		Number[60],		/* Phone number. */
		Comment[40];		/* Comment. */

	UBYTE	UserName[30],		/* User name for this BSS. */
		Password[30];		/* Password for user name. */
};

	/* ConvertHeader():
	 *
	 *	Convert old style phone book header to new style
	 *	phone book header.
	 */

STATIC VOID
ConvertHeader(struct OldPhoneHeader *OldHeader,struct PhoneHeader *NewHeader)
{
	strcpy(NewHeader -> Name,	OldHeader -> Name);
	strcpy(NewHeader -> Number,	OldHeader -> Number);
	strcpy(NewHeader -> Comment,	OldHeader -> Comment);

	strcpy(NewHeader -> UserName,	OldHeader -> UserName);
	strcpy(NewHeader -> Password,	OldHeader -> Password);
}

	/* ConvertConfig():
	 *
	 *	Convert old style configuration to new style configuration.
	 */

STATIC BOOL
ConvertConfig(struct OldConfiguration *OldConfig,struct Configuration *NewConfig,BOOL IsPhonebook)
{
	if(CreateConfigEntry(NewConfig,PREF_SERIAL))
	{
		ResetConfigEntry(NewConfig,PREF_SERIAL,FALSE);

		CopyMem(&OldConfig -> SerialConfig,NewConfig -> SerialConfig,MIN(sizeof(struct SerialSettings),sizeof(struct OldSerialSettings)));

		FixOldConfig(NewConfig,PREF_SERIAL,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_MODEM))
	{
		ResetConfigEntry(NewConfig,PREF_MODEM,FALSE);

		CopyMem(&OldConfig -> ModemConfig,NewConfig -> ModemConfig,MIN(sizeof(struct ModemSettings),sizeof(struct OldModemSettings)));

		FixOldConfig(NewConfig,PREF_MODEM,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_COMMAND))
	{
		ResetConfigEntry(NewConfig,PREF_COMMAND,FALSE);

		CopyMem(&OldConfig -> CommandConfig,NewConfig -> CommandConfig,MIN(sizeof(struct CommandSettings),sizeof(struct OldCommandSettings)));

		FixOldConfig(NewConfig,PREF_COMMAND,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_SCREEN))
	{
		ResetConfigEntry(NewConfig,PREF_SCREEN,FALSE);

		CopyMem(&OldConfig -> ScreenConfig,NewConfig -> ScreenConfig,MIN(sizeof(struct ScreenSettings),sizeof(struct OldScreenSettings)));

		FixOldConfig(NewConfig,PREF_SCREEN,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_TERMINAL))
	{
		ResetConfigEntry(NewConfig,PREF_TERMINAL,FALSE);

		CopyMem(&OldConfig -> TerminalConfig,NewConfig -> TerminalConfig,MIN(sizeof(struct TerminalSettings),sizeof(struct OldTerminalSettings)));

		FixOldConfig(NewConfig,PREF_TERMINAL,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_PATH))
	{
		ResetConfigEntry(NewConfig,PREF_PATH,FALSE);

		CopyMem(&OldConfig -> PathConfig,NewConfig -> PathConfig,MIN(sizeof(struct PathSettings),sizeof(struct OldPathSettings)));

		FixOldConfig(NewConfig,PREF_PATH,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_MISC))
	{
		ResetConfigEntry(NewConfig,PREF_MISC,FALSE);

		CopyMem(&OldConfig -> MiscConfig,NewConfig -> MiscConfig,MIN(sizeof(struct MiscSettings),sizeof(struct OldMiscSettings)));

		FixOldConfig(NewConfig,PREF_MISC,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_CLIP))
	{
		ResetConfigEntry(NewConfig,PREF_CLIP,FALSE);

		CopyMem(&OldConfig -> ClipConfig,NewConfig -> ClipConfig,MIN(sizeof(struct ClipSettings),sizeof(struct OldClipSettings)));

		FixOldConfig(NewConfig,PREF_CLIP,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_CAPTURE))
	{
		ResetConfigEntry(NewConfig,PREF_CAPTURE,FALSE);

		CopyMem(&OldConfig -> CaptureConfig,NewConfig -> CaptureConfig,MIN(sizeof(struct CaptureSettings),sizeof(struct OldCaptureSettings)));

		strcpy(NewConfig -> CaptureConfig -> CallLogFileName,NewConfig -> CaptureConfig -> LogFileName);

		AddPart(NewConfig -> CaptureConfig -> CallLogFileName,"term-call.log",MAX_FILENAME_LENGTH);

		FixOldConfig(NewConfig,PREF_CAPTURE,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_FILE))
	{
		LONG i,Error = 0;

		ResetConfigEntry(NewConfig,PREF_FILE,FALSE);

		CopyMem(&OldConfig -> FileConfig,NewConfig -> FileConfig,MIN(sizeof(struct FileSettings),sizeof(struct OldFileSettings)));

		FixOldConfig(NewConfig,PREF_FILE,IsPhonebook,2,4);

		for(i = PREF_TRANSLATIONFILENAME ; i <= PREF_FASTMACROFILENAME ; i++)
		{
			if(!CreateConfigEntry(NewConfig,i))
			{
				Error = ERROR_NO_FREE_STORE;
				break;
			}
		}

		if(!Error)
		{
			strcpy(NewConfig -> TranslationFileName,	NewConfig -> FileConfig -> TranslationFileName);
			strcpy(NewConfig -> MacroFileName,		NewConfig -> FileConfig -> MacroFileName);
			strcpy(NewConfig -> CursorFileName,		NewConfig -> FileConfig -> CursorFileName);
			strcpy(NewConfig -> FastMacroFileName,		NewConfig -> FileConfig -> FastMacroFileName);

			DeleteConfigEntry(NewConfig,PREF_FILE);
		}
		else
		{
			SetIoErr(Error);
			return(FALSE);
		}
	}
	else
		return(FALSE);

	if(CreateConfigEntry(NewConfig,PREF_EMULATION))
	{
		ResetConfigEntry(NewConfig,PREF_EMULATION,FALSE);

		CopyMem(&OldConfig -> EmulationConfig,NewConfig -> EmulationConfig,MIN(sizeof(struct EmulationSettings),sizeof(struct OldEmulationSettings)));

		FixOldConfig(NewConfig,PREF_EMULATION,IsPhonebook,2,4);
	}
	else
		return(FALSE);

	FinalFix(NewConfig,IsPhonebook,2,4);

	return(TRUE);
}

	/* LoadOldPhonebook(STRPTR Name):
	 *
	 *	Restore a phone book from a disk file.
	 */

BOOL
LoadOldPhonebook(STRPTR Name,PhonebookHandle *BookHandle)
{
	STATIC ULONG Stops[6 * 2] =
	{
		ID_TERM,ID_VERS,
		ID_TERM,ID_DIAL,
		ID_TERM,ID_PREF,
		ID_TERM,ID_DATE,
		ID_TERM,ID_PHON,
		ID_TERM,ID_PSWD
	};

	struct PhoneEntry	**PrivatePhonebook;
	LONG			 PrivatePhoneSize = 0;
	LONG			 Size = 0,Count = 0,Last = -1;
	struct IFFHandle	*Handle;
	BOOL			 Success = FALSE;
	struct ContextNode	*Chunk;
	BOOL			 LastHadTime	= TRUE,
				 HadPassword	= FALSE;
	struct TimeDateNode	*TimeDateNode;
	struct OldConfiguration	*OldConfig;
	struct OldPhoneHeader	*OldHeader;
	LONG			 Error;

	if(OldConfig = (struct OldConfiguration *)AllocVecPooled(sizeof(struct OldConfiguration) + sizeof(struct OldPhoneHeader),MEMF_ANY))
	{
		OldHeader = (struct OldPhoneHeader *)(OldConfig + 1);

		if(Handle = AllocIFF())
		{
			if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
			{
				InitIFFasDOS(Handle);

				if(!(Error = OpenIFF(Handle,IFFF_READ)))
				{
					if(!(Error = StopChunks(Handle,(LONG *)Stops,6)))
					{
						while(!ParseIFF(Handle,IFFPARSE_SCAN))
						{
							Chunk = CurrentChunk(Handle);

							if(Chunk -> cn_ID == ID_VERS)
							{
								struct TermInfo TermInfo;

								if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
								{
									if(TermInfo . Version != 2 || TermInfo . Revision != 4)
									{
										Error = ERR_OUTDATED;

										break;
									}
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PSWD)
							{
								UBYTE DummyBuffer[20];

								HadPassword = TRUE;

								if(ReadChunkBytes(Handle,DummyBuffer,20) == 20)
								{
									if(BookHandle)
									{
										if(BookHandle -> PhonePasswordUsed)
										{
											if(!memcmp(BookHandle -> PhonePassword,DummyBuffer,20))
												continue;
										}
									}
									else
									{
										if(PhonePasswordUsed)
										{
											if(!memcmp(PhonePassword,DummyBuffer,20))
												continue;
										}
									}

									memset(SharedBuffer,0,21);

									if(GetString(FALSE,TRUE,21,LocaleString(MSG_PHONEPANEL_PLEASE_ENTER_PASSWORD_TXT),SharedBuffer))
									{
										UBYTE AnotherBuffer[20];

										Encrypt(SharedBuffer,20,AnotherBuffer,SharedBuffer,strlen(SharedBuffer));

										if(!memcmp(DummyBuffer,AnotherBuffer,20))
										{
											if(BookHandle)
											{
												CopyMem(DummyBuffer,BookHandle -> PhonePassword,20);

												BookHandle -> PhonePasswordUsed = TRUE;
											}
											else
											{
												CopyMem(DummyBuffer,PhonePassword,20);

												PhonePasswordUsed = TRUE;
											}

											continue;
										}
										else
										{
											ShowRequest(Window,LocaleString(MSG_TERMPHONE_WRONG_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Name);

											break;
										}
									}
									else
										break;
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_DIAL)
							{
								if(ReadChunkBytes(Handle,&Size,sizeof(LONG)) == sizeof(LONG))
								{
									if(!(PrivatePhonebook = CreatePhonebook(Size,&PrivatePhoneSize,TRUE)))
										break;
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PHON)
							{
								LONG Size = MIN(sizeof(struct OldPhoneHeader),Chunk -> cn_Size);

								if(ReadChunkBytes(Handle,OldHeader,Size) == Size)
								{
									if(BookHandle)
									{
										if(BookHandle -> PhonePasswordUsed)
											Decrypt((UBYTE *)OldHeader,Size,(UBYTE *)OldHeader,BookHandle -> PhonePassword,20);
									}
									else
									{
										if(PhonePasswordUsed)
											Decrypt((UBYTE *)OldHeader,Size,(UBYTE *)OldHeader,PhonePassword,20);
									}
								}
								else
								{
									Error = IoErr();

									break;
								}
							}

							if(Chunk -> cn_ID == ID_PREF)
							{
								if(Last != -1)
								{
									if(!LastHadTime)
									{
										if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
											AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
									}
								}

								if(Size && Count < Size)
								{
									LONG LastSize = MIN(Chunk -> cn_Size,sizeof(struct OldConfiguration));

									if(BookHandle)
										BookHandle -> PhonePasswordUsed = HadPassword;
									else
										PhonePasswordUsed = HadPassword;

									if(ReadChunkBytes(Handle,OldConfig,LastSize) == LastSize)
									{
										if(BookHandle)
										{
											if(BookHandle -> PhonePasswordUsed)
												Decrypt((UBYTE *)OldConfig,LastSize,(UBYTE *)OldConfig,BookHandle -> PhonePassword,20);
										}
										else
										{
											if(PhonePasswordUsed)
												Decrypt((UBYTE *)OldConfig,LastSize,(UBYTE *)OldConfig,PhonePassword,20);
										}

										if(ConvertConfig(OldConfig,PrivatePhonebook[Count] -> Config,TRUE))
										{
											memset(PrivatePhonebook[Count] -> Header,0,sizeof(struct PhoneHeader));

											ConvertHeader(OldHeader,PrivatePhonebook[Count] -> Header);

											Last = Count;

											PrivatePhonebook[Count] -> Count = -1;

											Count++;

											LastHadTime = FALSE;
										}
										else
										{
											if(Count)
												Size = Count - 1;
											else
												Size = 0;

											break;
										}
									}
									else
									{
										Error = IoErr();

										if(Count)
											Size = Count - 1;
										else
											Size = 0;

										break;
									}
								}
							}

							if(Chunk -> cn_ID == ID_DATE)
							{
								if(Last != -1)
								{
									LONG Count = (Chunk -> cn_Size - sizeof(struct TimeDateHeader)) / sizeof(struct TimeDateOld);

									if(TimeDateNode = CreateTimeDateNode(-1,-1,"",Count))
									{
										struct TimeDateOld *Old;

										if(Old = (struct TimeDateOld *)AllocVecPooled(sizeof(struct TimeDateOld) * Count,MEMF_ANY))
										{
											if(ReadChunkBytes(Handle,&TimeDateNode -> Header,sizeof(struct TimeDateHeader)) == sizeof(struct TimeDateHeader))
											{
												if(ReadChunkBytes(Handle,Old,sizeof(struct TimeDateOld) * Count) == sizeof(struct TimeDateOld) * Count)
												{
													LONG i;

													for(i = 0 ; i < Count ; i++)
														ConvertTimeDate(&Old[i],&TimeDateNode->Table[i]);

													AdaptTimeDateNode(TimeDateNode);

													AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);

													LastHadTime = TRUE;

													FreeVecPooled(Old);
												}
												else
												{
													FreeVecPooled(Old);

													Error = IoErr();

													FreeTimeDateNode(TimeDateNode);
												}
											}
											else
											{
												FreeVecPooled(Old);

												Error = IoErr();

												FreeTimeDateNode(TimeDateNode);
											}
										}
										else
										{
											Error = ERROR_NO_FREE_STORE;

											FreeTimeDateNode(TimeDateNode);
										}
									}
								}
							}
						}

						if(Size)
						{
							if(!LastHadTime && Last != -1)
							{
								if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
									AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
							}

							if(!BookHandle)
							{
								struct timeval Now;
								LONG i;

								GetSysTime(&Now);

								PhonebookID = Now . tv_secs;

								NewList((struct List *)&PhoneGroupList);

								if(Phonebook)
									DeletePhonebook(Phonebook,PhoneSize,TRUE);

								Phonebook = PrivatePhonebook;
								PhoneSize = PrivatePhoneSize;
								PhonebookAutoDial = FALSE;
								PhonebookAutoExit = FALSE;
								PhonebookDefaultGroup = 0;

								NumPhoneEntries = Size;

								for(i = 0 ; i < NumPhoneEntries ; i++)
								{
									Phonebook[i] -> Header -> ID = PhonebookID++;
									StripGlobals(Phonebook[i] -> Config);
								}
							}
							else
							{
								struct timeval Now;
								LONG i;

								GetSysTime(&Now);

								BookHandle -> PhonebookID = Now . tv_secs;

								if(BookHandle -> PhoneGroupList)
									NewList((struct List *)BookHandle -> PhoneGroupList);

								if(BookHandle -> Phonebook)
									DeletePhonebook(BookHandle -> Phonebook,BookHandle -> PhoneSize,TRUE);

								BookHandle -> Phonebook = PrivatePhonebook;
								BookHandle -> PhoneSize = PrivatePhoneSize;
								BookHandle -> DefaultGroup = 0;

								BookHandle -> NumPhoneEntries = Size;
								BookHandle -> AutoDial = FALSE;
								BookHandle -> AutoExit = FALSE;

								for(i = 0 ; i < BookHandle -> NumPhoneEntries ; i++)
								{
									BookHandle -> Phonebook[i] -> Header -> ID = BookHandle -> PhonebookID++;
									StripGlobals(BookHandle -> Phonebook[i] -> Config);
								}
							}

							Success = TRUE;
						}
						else
						{
							if(PrivatePhoneSize)
							{
								DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);

								Success = FALSE;
							}
						}

						FreeDialList(TRUE);
					}

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}
			else
				Error = IoErr();

			FreeIFF(Handle);
		}
		else
			Error = ERR_NO_MEM;

		FreeVecPooled(OldConfig);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	return(Success);
}

	/* ReadConfig(STRPTR Name,struct Configuration *Config):
	 *
	 *	Read the configuration file, very much the same as ReadIFFData().
	 */

BOOL
ReadOldConfig(STRPTR Name,struct Configuration *Config)
{
	struct IFFHandle	*Handle;
	BOOL			 Success = FALSE;
	struct StoredProperty	*Prop;
	struct TermInfo		*TermInfo;
	struct OldConfiguration	*OldConfig;
	LONG			 Error;

	if(OldConfig = (struct OldConfiguration *)AllocVecPooled(sizeof(struct OldConfiguration),MEMF_ANY))
	{
		if(Handle = AllocIFF())
		{
			if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
			{
				InitIFFasDOS(Handle);

				if(!(Error = OpenIFF(Handle,IFFF_READ)))
				{
					if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
					{
						if(!(Error = StopChunk(Handle,ID_TERM,ID_PREF)))
						{
							if(!ParseIFF(Handle,IFFPARSE_SCAN))
							{
								if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
								{
									TermInfo = (struct TermInfo *)Prop -> sp_Data;

									if(TermInfo -> Version == 2 && TermInfo -> Revision == 4)
									{
										struct ContextNode *Chunk = CurrentChunk(Handle);

										if(ReadChunkRecords(Handle,OldConfig,MIN(Chunk -> cn_Size,sizeof(struct OldConfiguration)),1) == 1)
										{
											if(ConvertConfig(OldConfig,Config,FALSE))
												Success = TRUE;
										}
										else
											Error = IoErr();
									}
									else
										Error = ERR_OUTDATED;
								}
							}
						}
					}

					CloseIFF(Handle);
				}

				Close(Handle -> iff_Stream);
			}
			else
				Error = IoErr();

			FreeIFF(Handle);
		}
		else
			Error = ERR_NO_MEM;

		FreeVecPooled(OldConfig);
	}
	else
		Error = ERR_NO_MEM;

	if(Error)
		SetIoErr(Error);

	return(Success);
}
