-- file: UnsafeSTPOps.mesa  Edited by:
-- Smokey,	17-Jul-81  7:57:15
-- JGS,		17-Aug-81 11:24:06
-- Karlton,	10-Nov-81 16:51:38
-- Daniels,	21-Sep-82 13:00:07
-- Davirro,	16-Nov-82 17:48:07

DIRECTORY
  PupStream USING [CloseReason],
  Stream USING [
    Byte, DeleteProcedure, GetProcedure, Handle,  Object, PutProcedure,
    SetSSTProcedure, SendAttentionProcedure, SubSequenceType,
    WaitAttentionProcedure, Word],
  UnsafeSTP USING [
    Access, CompletionProcType, ConfirmProcType, DesiredProperties, ErrorCode, FileInfo,
    Type, ValidProperties],
  Time USING [Packed];
  
UnsafeSTPOps: DEFINITIONS =
  BEGIN
  
-- Constants

  maxStringLength: CARDINAL = 100;
  myPassword: CARDINAL = 111111B;
  
-- Types

  Handle: TYPE = LONG POINTER TO Object;
  Object: TYPE = RECORD[
    byteStream: Stream.Handle ← NIL,
    userState: ARRAY UserProperties OF LONG STRING ← ALL[NIL],
    gotMark: BOOLEAN ← FALSE,
    mark: Stream.SubSequenceType ← NULL,
    remoteString: LONG STRING ← NIL,
    host: LONG STRING ← NIL,
    serverType: ServerType ← unknown,
    plist: PList ← NIL,
    desiredProps: UnsafeSTP.DesiredProperties ← ALL[TRUE],
    info: UnsafeSTP.FileInfo ← NIL,
    remoteStream: RemoteStream ← NIL];
    
  RemoteStream: TYPE = POINTER TO RemoteObject; -- must be short
  RemoteObject: TYPE = RECORD[
    stream: Stream.Object,
    state: RemoteStreamState,
    access: UnsafeSTP.Access,
    stp: Handle,
    password: CARDINAL ← myPassword];
    
  FilenameType: TYPE = {alto, tenex};
  Operation: TYPE = {delete, directory, retrieve, store};
  ServerType: TYPE = {ifs, tenex, unknown};
  PListArray: TYPE = ARRAY UnsafeSTP.ValidProperties OF LONG STRING;
  PList: TYPE = LONG POINTER TO PListArray;
  RemoteStreamState: TYPE = {initial, confirm, data, complete, end};
  
  ValidProperties: TYPE = UnsafeSTP.ValidProperties;
    
  FileProperties: TYPE = UnsafeSTP.ValidProperties[directory..author];
  UserProperties: TYPE = UnsafeSTP.ValidProperties[userName..directory];
  
-- Procedures for doing FTP protocol operations  

  DoFiles: PROCEDURE [
    stp: Handle,
    file: LONG STRING,
    confirm: UnsafeSTP.ConfirmProcType,
    complete: UnsafeSTP.CompletionProcType,
    op: Operation];
  GetCommand: PROCEDURE [stp: Handle, ps: LONG POINTER TO LONG STRING]
    RETURNS[mark: Stream.SubSequenceType, code: CHARACTER];
  GetFile: PROCEDURE [stp: Handle, stream: Stream.Handle, file: LONG STRING]
    RETURNS [BOOLEAN];
  GetHereIsAndPList: PROCEDURE [stp: Handle, gobbleEOC: BOOLEAN ← TRUE];
  GetPList: PROCEDURE [stp: Handle, gobbleEOC: BOOLEAN ← TRUE, 
  	propertiesOk: BOOL ← FALSE];
  PutCommand: PROCEDURE [stp: Handle, mark: Stream.SubSequenceType,
    code: CHARACTER, string: LONG STRING, sendEOC: BOOLEAN ← TRUE];
  PutFile: PROCEDURE [stp: Handle, stream: Stream.Handle, file: LONG STRING, sendEOC: BOOLEAN ← TRUE];
  PutPList: PROCEDURE [stp: Handle, mark: Stream.SubSequenceType, sendEOC: BOOLEAN ← TRUE];
  
-- Utility routines

  CollectString: PROCEDURE [stp: Handle, ps: LONG POINTER TO LONG STRING];
  CollectCode: PROCEDURE [stp: Handle] RETURNS[code: CHARACTER];
  CheckConnection: PROCEDURE [stp: Handle];
  ErrorIfNextNotEOC: PROCEDURE [stp: Handle];
  ErrorIfNextNotYes: PROCEDURE [stp: Handle];
  FindFileType: PROCEDURE [stream: Stream.Handle] RETURNS[fileType: UnsafeSTP.Type];
  GetServerType: PROCEDURE [server: LONG STRING] RETURNS [serverType: ServerType];
  LookAtMark: PROCEDURE [stp: Handle] RETURNS [Stream.SubSequenceType];
  MakeRemoteName: PROCEDURE [plist: PList, type: FilenameType]
    RETURNS[name: LONG STRING];
  MyGetChar: PROCEDURE [stp: Handle] RETURNS [char: CHARACTER];
  MyGetMark: PROCEDURE [stp: Handle] RETURNS [Stream.SubSequenceType];
  MyPutString: PROCEDURE [byteStream: Stream.Handle, string: LONG STRING];
  PropertyString: PROCEDURE [prop: ValidProperties]
    RETURNS [string: LONG STRING]; -- Global string
  SelectError: PROCEDURE [
    stp: Handle, s: LONG STRING, mark: Stream.SubSequenceType];
  SetByteSize: PROCEDURE [stp: Handle, fileType: UnsafeSTP.Type];
  SetCreateTime: PROCEDURE [stp: Handle, creation: Time.Packed];
  SetFileType: PROCEDURE [stp: Handle, fileType: UnsafeSTP.Type];
  SmashClosed: PROCEDURE [stp: Handle];
  TransferTheFile: PROCEDURE [stp: Handle, from, to: Stream.Handle];
  
-- PList Utilities

  DestroyPList: PROCEDURE [plist: PList] RETURNS [PList];
  MakePList: PROCEDURE RETURNS[plist: PList];
  NameToPList: PROCEDURE [plist: PList, name: LONG STRING, type: FilenameType];
  PListToName: PROCEDURE [plist: PList, type: FilenameType]
    RETURNS[name: LONG STRING];
  PutPListItem: PROCEDURE [byteStream: Stream.Handle,
    property: ValidProperties, value: LONG STRING];
  ResetPList: PROCEDURE [plist: PList];
  SetPListItem: PROCEDURE [plist: PList, property, value: LONG STRING];
  UserStateToPList: PROCEDURE [stp: Handle];
  
-- Remote Stream routines

  DeleteRemoteStream: Stream.DeleteProcedure;
  GetBlock: Stream.GetProcedure;
  GetByte: PROCEDURE [sH: Stream.Handle] RETURNS[byte: Stream.Byte];
  GetError: Stream.GetProcedure;
  GetWord: PROCEDURE [sH: Stream.Handle] RETURNS[word: Stream.Word];
  PutBlock: Stream.PutProcedure;
  PutByte: PROCEDURE [sH: Stream.Handle, byte: Stream.Byte];
  PutError: Stream.PutProcedure;
  PutWord: PROCEDURE [sH: Stream.Handle, word: Stream.Word];
  SetSSTNop: Stream.SetSSTProcedure;
  SendAttentionNop: Stream.SendAttentionProcedure;
  WaitAttentionNop: Stream.WaitAttentionProcedure;
  
  
-- Internal ERRORs and SIGNALs

  BadProperty: ERROR;
  MarkEncountered: ERROR;
  ErrorCodeToSTPErrorCode: PROCEDURE [errorCode: UnsafeSTP.ErrorCode, code: CHARACTER]
    RETURNS[UnsafeSTP.ErrorCode];
  GenerateErrorString: PROCEDURE [
    stp: Handle, errorCode: UnsafeSTP.ErrorCode, string: LONG STRING, code: CHARACTER ← 0C];
  GenerateStreamClosingError: PROCEDURE [stp: Handle, why: PupStream.CloseReason];
  GenerateProtocolError: PROCEDURE [
    stp: Handle, type: ProtocolError, mark: Stream.SubSequenceType, code: CHARACTER ← 0C];
    
  ProtocolError: TYPE = {badVersion, badMark, badPList, eocExpected, noCode};
  
-- Registered STP Mark Byte Commands

  markRetrieve: Stream.SubSequenceType = 1B;
  markStore: Stream.SubSequenceType = 2B;
  markYes: Stream.SubSequenceType = 3B;
  markNo: Stream.SubSequenceType = 4B;
  markHereIsFile: Stream.SubSequenceType = 5B;
  markEOC: Stream.SubSequenceType = 6B;
  markComment: Stream.SubSequenceType = 7B;
  markIAmVersion: Stream.SubSequenceType = 10B;
  markNewStore: Stream.SubSequenceType = 11B;
  markDirectory: Stream.SubSequenceType = 12B;
  markHereIsPList: Stream.SubSequenceType = 13B;
  markYouAreUser: Stream.SubSequenceType = 14B;
  markNewDirectory: Stream.SubSequenceType = 14B;	-- (notice: same as markYouAreUser)
  markAbort: Stream.SubSequenceType = 15B;
  markDelete: Stream.SubSequenceType = 16B;
  markRename: Stream.SubSequenceType = 17B;
  
-- Registered Mail Mark Byte Commands

  markStoreMail: Stream.SubSequenceType = 20B;
  markRetrieveMail: Stream.SubSequenceType = 21B;
  markFlushMailBox: Stream.SubSequenceType = 22B;
  markMailBoxException: Stream.SubSequenceType = 23B;
  
  END. -- end of STPOps