-- Copyright (C) 1979, 1980, 1984  by Xerox Corporation. All rights reserved. 
-- FTPPrivateDefs.mesa,  Edited by: HGM 15-Sep-85 16:07:05  
-- FTPPrivateDefs.mesa,  Edited by: HGM July 31, 1980  12:07 AM  


DIRECTORY
  FTPDefs,
  Ascii USING [CR];

FTPPrivateDefs: DEFINITIONS
  -- share list
  SHARES FTPDefs =
  BEGIN OPEN FTPDefs;

  -- **********************!  System Generation Parameters  !***********************

  -- maximum string length (in characters)
  maxStringLength: CARDINAL = 128;
  maxDateLength: CARDINAL = 22;  -- dd-mmm-yy hh:mm:ss zzz

  -- default buffer size (in pages)
  defaultBufferSize: CARDINAL = 4;

  -- timeout intervals (in seconds)
  responseFromServerSeconds: CARDINAL = LAST[CARDINAL];
  responseFromUserSeconds: CARDINAL = 180;

  -- trace characters
  outgoingTraceIndicator: CHARACTER = '>;
  incomingTraceIndicator: CHARACTER = '<;
  traceByteLeftDelimiter: CHARACTER = '{;
  traceByteRightDelimiter: CHARACTER = '};

  -- miscellaneous characters
  insigniaSeparator: CHARACTER = Ascii.CR;
  majorMinorSeparator: CHARACTER = '.;
  spooledPropertyTerminator: CHARACTER = ');

  -- **********************!  Protocol Parameters  !***********************

  -- protocol version numbers
  ftpVersion: Byte = 1;
  mtpVersion: Byte = 1;

  -- well known socket numbers
  ftpSocket: CARDINAL = 3;
  mtpSocket: CARDINAL = 7;

  -- mark byte commands
  markMinimum: Byte = 1B;
  markRetrieve: Byte = 1B;
  markStore: Byte = 2B;
  markYes: Byte = 3B;
  markNo: Byte = 4B;
  markHereIsFile: Byte = 5B;
  markEndOfCommand: Byte = 6B;
  markComment: Byte = 7B;
  markIAmVersion: Byte = 10B;
  markNewStore: Byte = 11B;
  markDirectory: Byte = 12B;
  markHereIsPropertyList: Byte = 13B;
  markNewDirectory: Byte = 14B;
  markAbort: Byte = 15B;
  markDelete: Byte = 16B;
  markRename: Byte = 17B;
  markStoreMail: Byte = 20B;
  markRetrieveMail: Byte = 21B;
  markFlushMailbox: Byte = 22B;
  markMailboxException: Byte = 23B;
  markMaximum: Byte = 23B;

  -- no reply codes
  codeMinimum: Byte = 1B;
  codeCommandUndefined: Byte = 1B;
  codeMissingUserName: Byte = 2B;
  codeCommandIllegal: Byte = 3B;
  codeMalformedPropertyList: Byte = 10B;
  codeIllegalServerFilename: Byte = 11B;
  codeIllegalDirectory: Byte = 12B;
  codeIllegalNameBody: Byte = 13B;
  codeIllegalVersion: Byte = 14B;
  codeIllegalType: Byte = 15B;
  codeIllegalByteSize: Byte = 16B;
  codeIllegalEndOfLineConvention: Byte = 17B;
  codeIllegalUserName: Byte = 20B;
  codeBadUserPassword: Byte = 21B;
  codeBadUserAccount: Byte = 22B;
  codeIllegalConnectName: Byte = 23B;
  codeBadConnectPassword: Byte = 24B;
  codeIllegalCreationDate: Byte = 25B;
  codeIllegalWriteDate: Byte = 26B;
  codeIllegalReadDate: Byte = 27B;
  codeIllegalAuthor: Byte = 30B;
  codeIllegalDevice: Byte = 31B;
  codeNoValidMailbox: Byte = 40B;
  codeIllegalMailbox: Byte = 41B;
  codeFileNotFound: Byte = 100B;
  codeRequestedAccessDenied: Byte = 101B;
  codeTransferParametersInconsistent: Byte = 102B;
  codeFileDataError: Byte = 103B;
  codeStorageExhausted: Byte = 104B;
  codeDontSendFile: Byte = 105B;
  codeStoreNotCompleted: Byte = 106B;
  codeUnidentifiedTransientError: Byte = 107B;
  codeUnidentifiedPermanentError: Byte = 110B;
  codeFileBusy: Byte = 111B;
  codeFileAlreadyExists: Byte = 112B;
  codeMaximum: Byte = 112B;

  -- mailbox exception codes
  excpMinimum: Byte = 0B;
  excpUnspecifiedFailure: Byte = 0B;
  excpCannotLocateMailbox: Byte = 1B;
  excpNoForwardingProvided: Byte = 2B;
  excpTransientError: Byte = 3B;
  excpPermanentError: Byte = 4B;
  excpMaximum: Byte = 4B;

  -- property list delimiters
  propertyListLeftDelimiter: CHARACTER = '(;
  propertyListRightDelimiter: CHARACTER = ');
  propertyLeftDelimiter: CHARACTER = '(;
  propertyNameValueSeparator: CHARACTER = ' ;
  propertyRightDelimiter: CHARACTER = ');
  propertyEscape: CHARACTER = '';

  -- dump file block types
  blockDate: Byte = 373B;
  blockEnd: Byte = 374B;
  blockError: Byte = 375B;
  blockData: Byte = 376B;
  blockName: Byte = 377B;

  -- miscellaneous
  minimumDumpBlockSize: CARDINAL = 2;
  maximumDumpBlockSize: CARDINAL = 256;
  mailboxExceptionIndexTerminator: CHARACTER = ' ;

  -- **********************!  Internal State  !***********************

  -- system state information
  FTPSystem: TYPE = POINTER TO FTPSystemObject;
  FTPSystemObject: TYPE = RECORD [
    propertyNames: ARRAY Property OF STRING,
    userFilesLoaded, userMailLoaded, serverFilesLoaded, serverMailLoaded,
      accessoriesLoaded: BOOLEAN,
    bufferSize: CARDINAL,
    catchUnidentifiedErrors: BOOLEAN];

  -- server state information
  FTPServer: TYPE = POINTER TO FTPServerObject;
  FTPServerObject: TYPE = RECORD [
    ftplistener: FTPListener,
    serverQueueElementObject: ElementObject,
    purpose: Purpose,
    fileSystem: FileSystem,
    mailSystem: MailSystem,
    forwardingProvided, enqueued: BOOLEAN,
    ftper: FTPer,
    propertyList: PropertyList];

  -- dump state information
  DumpState: TYPE = LONG POINTER TO DumpStateObject;
  DumpStateObject: TYPE = RECORD [
    bufferAddress: POINTER,
    bufferLength: CARDINAL,
    ftper: FTPer,
    blockType: Byte];

  -- checksum state information
  ChecksumState: TYPE = POINTER TO ChecksumStateObject;
  ChecksumStateObject: TYPE = RECORD [
    checksum: CARDINAL, anyExcessByte: BOOLEAN, excessByte: Byte];

  -- event state information
  Event: TYPE = POINTER TO EventObject;
  EventObject: TYPE = MONITORED RECORD [fact: BOOLEAN, hint: CONDITION];

  -- word    
  Word: TYPE = LONG POINTER TO WordObject;
  WordObject: TYPE = MACHINE DEPENDENT RECORD [lhByte, rhByte: Byte];

  -- **********************!  User Procedures  !***********************

  -- common
  VerifyPurposeAndState: PROCEDURE [
    ftpuser: FTPUser, expectedPurpose: Purpose, expectedState: UserState];

  -- files
  UserFilesLoaded: PROCEDURE;
  FinishMultiFileOperation: PROCEDURE [ftpuser: FTPUser];

  -- dump
  SendHeaderBlock: PROCEDURE [dumpState: DumpState, fileName, creation: STRING];
  DumpBlock: PROCEDURE [
    dumpState: DumpState, source: LONG POINTER, byteCount: CARDINAL];
  LoadBlock: PROCEDURE [
    dumpState: DumpState, destination: LONG POINTER, maxWordCount: CARDINAL]
    RETURNS [actualByteCount: CARDINAL];

  -- mail
  UserMailLoaded: PROCEDURE;

  -- **********************!  Server Procedures  !***********************

  -- files
  ServerFilesLoaded: PROCEDURE;
  PTFDirectory: PROCEDURE [ftpserver: FTPServer];
  PTFStore: PROCEDURE [ftpserver: FTPServer, mark: Byte];
  PTFRetrieve, PTFDelete, PTFRename: PROCEDURE [ftpserver: FTPServer];

  -- mail
  ServerMailLoaded: PROCEDURE;
  PTFStoreMail, PTFRetrieveMail: PROCEDURE [ftpserver: FTPServer];

  -- **********************!  Utilities  !***********************

  -- system foothold procedure
  LocateFtpSystemObject: PROCEDURE RETURNS [POINTER TO FTPSystem];

  -- transmission primitives
  CreateFTPer: PROCEDURE [
    communicationPrimitives: CommunicationPrimitives,
    communicationSystem: CommunicationSystem] RETURNS [ftper: FTPer];
  DestroyFTPer: PROCEDURE [ftper: FTPer];
  SendBlock: PROCEDURE [ftper: FTPer, source: LONG POINTER, byteCount: CARDINAL];
  ReceiveBlock: PROCEDURE [
    ftper: FTPer, destination: LONG POINTER, maxWordCount: CARDINAL]
    RETURNS [actualByteCount: CARDINAL];
  SendBytes, ReceiveBytes: PROCEDURE [ftper: FTPer, bytePointer: BytePointer];
  SendWord: PROCEDURE [ftper: FTPer, word: WORD];
  ReceiveWord: PROCEDURE [ftper: FTPer] RETURNS [word: WORD];
  SendByte: PROCEDURE [ftper: FTPer, byte: Byte];
  ReceiveByte: PROCEDURE [ftper: FTPer] RETURNS [byte: Byte];

  -- byte primitives
  TransferBytes: PROCEDURE [srcBytePointer, dstBytePointer: BytePointer];
  AdvanceBytePointer: PROCEDURE [bytePointer: BytePointer, byteCount: CARDINAL];

  -- queue primitives
  InitializeQueue: PROCEDURE [
    queue: Queue, identifiersCoincide: IdentifiersCoincide];
  FinalizeQueue: PROCEDURE [queue: Queue];
  EnQueue: PROCEDURE [queue: Queue, element: Element, identifier: UNSPECIFIED]
    RETURNS [enqueuedElement: Element];
  DeQueue: PROCEDURE [queue: Queue, element: Element];
  LockQueue: PROCEDURE [queue: Queue, element: Element, exclusive: BOOLEAN];
  UnlockQueue: PROCEDURE [queue: Queue, element: Element];
  EnumerateQueue: PROCEDURE [
    queue: Queue, processElement: PROCEDURE [Element] RETURNS [BOOLEAN]]
    RETURNS [element: Element];

  -- parallel processing primitives
  ForkTransferPair: PROCEDURE [
    fileSystem: FileSystem,
    readFile: PROCEDURE [
      FileSystem, FileHandle, PROCEDURE [UNSPECIFIED, POINTER, CARDINAL],
      UNSPECIFIED], srcFileHandle: FileHandle,
    writeFile: PROCEDURE [
      FileSystem, FileHandle, PROCEDURE [UNSPECIFIED, POINTER, CARDINAL]
      RETURNS [CARDINAL], UNSPECIFIED], dstFileHandle: FileHandle];
  ForkProcessPair: PROCEDURE [
    process: PROCEDURE [LONG UNSPECIFIED], parameter1, parameter2: LONG UNSPECIFIED];

  -- error primitives
  Abort: PROCEDURE [ftpError: FtpError];
  AbortWithExplanation: PROCEDURE [ftpError: FtpError, message: STRING];

  -- **********************!  Protocol Procedures  !***********************

  -- command/response shorthands
  PutGetVersion: PROCEDURE [ftper: FTPer, version: Byte];
  GetAnswerAndEOC: PROCEDURE [ftper: FTPer] RETURNS [answer: BOOLEAN];
  GetYesAndEOC: PROCEDURE [ftper: FTPer];
  GetSpecificCommand: PROCEDURE [ftper: FTPer, specificMark: Byte];
  PutCommandAndEOC: PROCEDURE [ftper: FTPer, mark, code: Byte];
  GetCommandAndEOC: PROCEDURE [ftper: FTPer] RETURNS [mark, code: Byte];
  PutEOC, GetEOC: PROCEDURE [ftper: FTPer];

  -- command/response primitives
  PutCommand: PROCEDURE [ftper: FTPer, mark, code: Byte];
  GetCommand: PROCEDURE [ftper: FTPer] RETURNS [mark, code: Byte];
  PutPropertyList, GetPropertyList: PROCEDURE [
    ftper: FTPer, propertyList: PropertyList];
  PutString: PROCEDURE [ftper: FTPer, string: STRING];
  GetString: PROCEDURE [ftper: FTPer, string: STRING, terminator: UNSPECIFIED];

  -- property list primitives
  CreatePropertyList: PROCEDURE RETURNS [propertyList: PropertyList];
  DestroyPropertyList: PROCEDURE [propertyList: PropertyList];
  CopyPropertyList: PROCEDURE [srcPropertyList, dstPropertyList: PropertyList];
  ResetPropertyList: PROCEDURE [propertyList: PropertyList];
  WriteProperty: PROCEDURE [
    propertyList: PropertyList, property: Property, value: STRING];
  EncodeBooleanProperty: PROCEDURE [boolean: BOOLEAN, property: STRING];
  DecodeBooleanProperty: PROCEDURE [property: STRING] RETURNS [boolean: BOOLEAN];

  -- filename primitives
  WriteFilename: PROCEDURE [
    file: STRING, propertyList: PropertyList, filePrimitives: FilePrimitives,
    fileSystem: FileSystem, userPropertyList: PropertyList];
  ReadFilename: PROCEDURE [
    file: STRING, propertyList: PropertyList, filePrimitives: FilePrimitives,
    fileSystem: FileSystem];
  WriteVirtualFilename: PROCEDURE [
    virtualFilename: VirtualFilename, propertyList: PropertyList,
    skipNullComponents: BOOLEAN];
  ReadVirtualFilename: PROCEDURE [
    virtualFilename: VirtualFilename, propertyList: PropertyList];

  -- file attribute primitives
  ExamineCredentials: PROCEDURE [
    propertyList: PropertyList, filePrimitives: FilePrimitives,
    fileSystem: FileSystem];
  WriteFileInfo, ReadFileInfo: PROCEDURE [
    propertyList: PropertyList, fileInfo: FileInfo];
  EncodeFileType: PROCEDURE [propertyList: PropertyList, fileType: FileType];
  DecodeFileType: PROCEDURE [propertyList: PropertyList]
    RETURNS [fileType: FileType];

  -- error primitives
  SignalToCode: PROCEDURE [ftpError: FtpError] RETURNS [code: Byte];
  CodeToSignal: PROCEDURE [code: Byte] RETURNS [ftpError: FtpError];
  RecipientErrorToExceptionCode: PROCEDURE [recipientError: RecipientError]
    RETURNS [exceptionCode: Byte];
  ExceptionCodeToRecipientError: PROCEDURE [exceptionCode: Byte]
    RETURNS [recipientError: RecipientError];

  -- event primitives
  PrepareEvent, PostEvent, AwaitEvent: PROCEDURE [event: Event];


  -- **********************!  Tracing  !***********************

  TraceOut: PUBLIC PROCEDURE [ftper: FTPer, mark: Byte];
  TraceIn: PUBLIC PROCEDURE [ftper: FTPer];
  TraceString: PUBLIC PROCEDURE [ftper: FTPer, string: STRING];
  TraceCharacter: PROCEDURE [ftper: FTPer, character: CHARACTER];


  -- **********************!  Accessories  !***********************

  AccessoriesLoaded: PROCEDURE;
  VerbalizeFtpError: PROCEDURE [ftpError: FtpError, message: STRING];
  VerbalizeRecipientError: PROCEDURE [
    recipientError: RecipientError, message: STRING];


  -- **********************!  Environment  !***********************

  bytesPerWord: CARDINAL = 2;
  wordsPerPage: CARDINAL = 256;


  -- **********************!  Runtime Procedures  !***********************

  ReadCredentials: PROCEDURE [user, password: STRING];
  ReadClock: PROCEDURE RETURNS [clock: INTEGER];
  EnableDisplay, DisableDisplay: PROCEDURE;
  ConfirmProcedure: PROCEDURE [procedure: PROCEDURE] RETURNS [present: BOOLEAN];
  CallProcedure: PROCEDURE [procedure: PROCEDURE RETURNS [UNSPECIFIED]]
    RETURNS [present: BOOLEAN, result: UNSPECIFIED];
  HaltConfiguration: PROCEDURE;

  END. -- of FTPPrivateDefs