<> <> <> <> <> <> <> DIRECTORY BasicTime USING [GMT], IO USING [STREAM, UnsafeBlock], Pup USING [Address, nullSocket, Socket], Rope USING [ROPE]; FTP: CEDAR DEFINITIONS = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; <> Handle: TYPE = REF Object; Object: TYPE; <> CreateFromName: PROC [hostName: ROPE, localHerald: ROPE _ NIL] RETURNS [h: Handle, remoteHerald: ROPE]; <> <> CreateFromAddress: PROC [hostAddress: Pup.Address, localHerald: ROPE _ NIL] RETURNS [h: Handle, remoteHerald: ROPE]; <> Destroy: PROC [h: Handle]; <> <> IsOpen: PROC [h: Handle] RETURNS [open: BOOLEAN]; <> <> GetClientData: PROC [h: Handle] RETURNS [data: REF ANY]; <> SetClientData: PROC [h: Handle, data: REF ANY]; <> <> <<>> <> <> <> <> <> <> <<1. Most servers require that a userName and userPassword property be supplied in every command. The connectName and connectPassword are required only when it is desired to "connect" (obtain owner-like access) to a directory different from the user's default directory.>> <<2. The name of the file to be operated on must be given either as individual components (directory, nameBody, and version, without any delimiting punctuation characters) or as a serverFileName punctuated according to server conventions (which may vary among different servers). If BOTH are provided, the individual components are used to default missing fields in the serverFileName. It should be mentioned that any file name components not specified either individually or as part of the serverFileName will be defaulted according to server conventions (which may vary among different servers). In commands that permit remote enumerations (Delete, Enumerate, and Retrieve), the file name properties may include "*" or other pattern match characters implemented by the server.>> <<3. Most other properties pertain to the files being transferred, and need be supplied only during a local-to-remote transfer (i.e., a Store from an FTP User). In particular, the type and (if binary) byteSize properties must always be specified during a Store, and the createDate and size properties are extremely desirable.>> <FTPSpec.press.>> Property: TYPE = { --Date-- createDate, readDate, writeDate, --Enumerated-- eolConvention, type, --Number-- byteSize--bits per byte--, checksum, size--bytes--, --Text-- author, connectName, connectPassword, device, directory, nameBody, serverFileName, userAccount, userName, userPassword, version, --DesiredProperties-- desiredProperty}; DateProperty: TYPE = Property [createDate..writeDate]; EnumeratedProperty: TYPE = Property [eolConvention..type]; NumberProperty: TYPE = Property [byteSize..size]; TextProperty: TYPE = Property [author..version]; BuiltInProperty: TYPE = Property [FIRST[Property]..desiredProperty); EOLConvention: TYPE = MACHINE DEPENDENT {unknown(0), cr, crlf, transparent}; Type: TYPE = MACHINE DEPENDENT {unknown(0), text, binary}; EnumPropValue: TYPE = RECORD [ SELECT OVERLAID EnumeratedProperty FROM eolConvention => [eolConvention: EOLConvention], type => [type: Type], ENDCASE]; nullEnumPropValue: EnumPropValue = [type[type: unknown]]; LocalOrRemote: TYPE = {local, remote}; GetDateProperty: PROC [h: Handle, prop: DateProperty, list: LocalOrRemote _ remote] RETURNS [value: BasicTime.GMT]; <> GetEnumeratedProperty: PROC [h: Handle, prop: EnumeratedProperty, list: LocalOrRemote _ remote] RETURNS [propValue: EnumPropValue]; <> <> <> GetNumberProperty: PROC [h: Handle, prop: NumberProperty, list: LocalOrRemote _ remote] RETURNS [value: INT]; <> GetTextProperty: PROC [h: Handle, prop: TextProperty, list: LocalOrRemote _ remote] RETURNS [value: ROPE]; <> GetUserDefinedProperty: PROC [h: Handle, prop: ATOM, list: LocalOrRemote _ remote] RETURNS [value: ROPE]; <> SetDateProperty: PROC [h: Handle, prop: DateProperty, value: BasicTime.GMT]; <> SetEnumeratedProperty: PROC [h: Handle, prop: EnumeratedProperty, value: EnumPropValue]; <> <> <> SetNumberProperty: PROC [h: Handle, prop: NumberProperty, value: INT]; <> SetTextProperty: PROC [h: Handle, prop: TextProperty, value: ROPE]; <> SetUserDefinedProperty: PROC [h: Handle, prop: ATOM, value: ROPE]; <> ResetProperties: PROC [h: Handle]; <> PropertySet: TYPE = PACKED ARRAY BuiltInProperty OF FalseBool; FalseBool: TYPE = BOOLEAN _ FALSE; GetDesiredProperties: PROC [h: Handle] RETURNS [props: PropertySet, userDefinedProps: LIST OF ATOM]; <> SetDesiredProperties: PROC [h: Handle, props: PropertySet, userDefinedProps: LIST OF ATOM _ NIL]; <> <> <<>> <> ConfirmProc: TYPE = PROC [h: Handle] RETURNS [confirm: BOOLEAN]; TransferProc: TYPE = PROC [h: Handle, stream: IO.STREAM]; CompleteProc: TYPE = PROC [h: Handle, ok: BOOLEAN]; Delete: PROC [h: Handle, confirm: ConfirmProc _ NIL]; <> <> Enumerate: PROC [h: Handle, noteFile: PROC [h: Handle]]; <> <> Rename: PROC [h: Handle, changeName: PROC [h: Handle]]; <> <> Retrieve: PROC [h: Handle, confirm: ConfirmProc _ NIL, transfer: TransferProc, complete: CompleteProc _ NIL]; <> <> <> <> <> Store: PROC [h: Handle, confirm: ConfirmProc _ NIL, transfer: TransferProc, complete: CompleteProc _ NIL]; <> <> <> <> <> <<>> <> <> <> Listener: TYPE = REF ListenerObject; ListenerObject: TYPE; AcceptProc: TYPE = PROC [requestor: Pup.Address, connections: CARDINAL] RETURNS [accept: BOOLEAN, reason: ROPE _ NIL]; FileInfoProc: TYPE = PROC [fileName: ROPE, pupAddress: Pup.Address] RETURNS [found: BOOL, return: BOOL, version: CARDINAL, create: BasicTime.GMT, bytes: LONG CARDINAL]; CreateListener: PROC [socket: Pup.Socket _ Pup.nullSocket, procs: ServerProcs, accept: AcceptProc _ NIL, timeoutSeconds: INT _ 30, fileInfo: FileInfoProc _ NIL, fileInfoSocket: Pup.Socket _ Pup.nullSocket, fileInfoProcesses: CARDINAL [1..10] _ 1] RETURNS [l: Listener]; <> <> <<"timeoutSeconds" specifies how long a stream will be kept open without activity.>> <> <> DestroyListener: PROC [l: Listener]; <> <> Server: PROC [stream: IO.STREAM, procs: ServerProcs]; <> <> <<>> <> <> ServerProcs: TYPE = REF ServerProcsRecord; ServerProcsRecord: TYPE = RECORD [ <> delete: ServerDeleteProc _ NIL, enumerate: ServerEnumerateProc _ NIL, rename: ServerRenameProc _ NIL, retrieve: ServerRetrieveProc _ NIL, store: ServerStoreProc _ NIL, version: ServerVersionProc _ NIL, -- NIL means a default version reply will be generated <> checkCredentials: CheckCredentialsProc _ NIL]; -- NIL means credentials will not be checked <<>> <> <> <> <<>> <> ConfirmTransferProc: TYPE = PROC [h: Handle] RETURNS [stream: IO.STREAM]; ServerCompleteProc: TYPE = PROC [h: Handle] RETURNS [ok: BOOLEAN]; ServerDeleteProc: TYPE = PROC [h: Handle, confirm: ConfirmProc, complete: ServerCompleteProc]; <> <> <> <> <> ServerEnumerateProc: TYPE = PROC [h: Handle, noteFile: PROC [h: Handle]]; <> <> ServerRenameProc: TYPE = PROC [h: Handle]; <> <> ServerRetrieveProc: TYPE = PROC [h: Handle, confirm: ConfirmTransferProc, complete: ServerCompleteProc]; <> <> <> <> <> ServerStoreProc: TYPE = PROC [h: Handle, confirm: ConfirmTransferProc, complete: ServerCompleteProc]; <> <> <> ServerVersionProc: TYPE = PROC [h: Handle, remoteHerald: ROPE] RETURNS [localHerald: ROPE]; <> CheckCredentialsProc: TYPE = PROC [h: Handle]; <> <> <> <<>> <> FileType: PROC [stream: STREAM] RETURNS [type: Type]; <> <> DataType: PROC [block: IO.UnsafeBlock] RETURNS [type: Type]; <> <> <> Failed: SIGNAL [h: Handle, code: FailureCode, text: ROPE _ NIL, resumable: BOOLEAN _ FALSE]; <> <> <> <> <> FailureCode: TYPE = MACHINE DEPENDENT { <> <> unspecified (0), -- unspecified reason badCommand (1), -- command undefined or unimplemented credentialsMissing (2), illegalCommand (3), -- illegal command in this context <> badPList (8), -- malformed property list (protocol error) illegalServerFileName (9), -- incorrect values of specific properties illegalDirectory (10), illegalNameBody (11), illegalVersion (12), illegalType (13), illegalByteSize (14), illegalEOLConversion (15), illegalUserName (16), illegalUserPassword (17), illegalUserAccount (18), illegalConnectName (19), illegalConnectPassword (20), illegalCreationDate (21), illegalWriteDate (22), illegalReadDate (23), illegalAuthor (24), illegalDevice (25), <> fileNotFound (64), accessDenied (65), -- e.g., due to file protection violation inconsistent (66), -- local/remote parameter mismatch fileDataError (67), -- file system reported error tooLong (68), -- file too long or storage full skipThisFile (69), -- (internal use only) notCompleted (70), -- (internal use only) transientError (71), -- unspecified transient server or file system failure (the text may give more information) permanentError (72), -- unspecified permanent server or file system failure (the text may give more information) fileBusy (73), -- open in conflicting way by some other client renameDestinationExists (74), -- attempted to change name to that of an existing file lastReplyCode (255), <<>> <> <> accessError, alreadyAConnection, connectionClosed, connectionRejected, connectionTimedOut, credentailsMissing, illegalFileName, noConnection, noNameLookupResponse, -- name lookup failed (CreateFromName) noRouteToNetwork, noSuchFile, noSuchHost, -- name lookup failed (CreateFromName) protocolError, -- probable bug in either the local or the remote FTP implementation <> requestRefused, undefinedError, aborted}; ReplyCode: TYPE = FailureCode[unspecified..lastReplyCode]; ConnectionFailure: TYPE = FailureCode[connectionClosed..noSuchHost]; ProtocolError: TYPE = {badVersion, badMark, badPList, eocExpected, noCode}; END. <<>> <> <> <> <> <> <<>>