'From Squeak3.11alpha of 13 February 2010 [latest update: #9483] on 9 March 2010 at 11:11:23 am'! !PRServerDirectory methodsFor: 'private' stamp: 'cmm 2/15/2010 16:04'! parseLine: aString "private - parse a line from a server response" | tokens | tokens := aString findTokens: '|'. "" ^ tokens first = 'D' ifTrue: [ DirectoryEntryDirectory directory: self name: tokens second creationTime: 0 modificationTime: 0 fileSize: 0 ] ifFalse: [ DirectoryEntryFile directory: self name: tokens second creationTime: tokens third asInteger modificationTime: tokens fourth asInteger fileSize: tokens fifth asInteger ]! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 3/28/2007 13:05'! createDirectory: localName "Create a new sub directory within the current one" self isTypeFile ifTrue: [ ^FileDirectory createDirectory: localName ]. client := self openFTPClient. self switchDirectory. [client makeDirectory: localName] ensure: [self quit]. ! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 4/4/2007 12:53'! deleteDirectory: localName "Delete the sub directory within the current one. Call needs to ask user to confirm." self isTypeFile ifTrue: [ ^FileDirectory deleteFileNamed: localName ]. "Is this the right command???" client := self openFTPClient. [ self switchDirectory. client deleteDirectory: localName] ensure: [self quit]. ! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 4/4/2007 17:09'! deleteFileNamed: fullName "Detete a remote file. fullName is directory path, and does include name of the server. Or it can just be a fileName." | file | file := self asServerFileNamed: fullName. file isTypeFile ifTrue: [ ^ (FileDirectory forFileName: (file fileNameRelativeTo: self)) deleteFileNamed: file fileName ]. client := self openFTPClient. [ self switchDirectory. client deleteFileNamed: fullName] ensure: [self quit]. ! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 2/15/2010 14:48'! deleteLocalFiles "Delete the local files in this directory." self switchDirectory. self fileNames do:[:fn| self deleteFileNamed: fn ifAbsent: [(CannotDeleteFileException new messageText: 'Could not delete the old version of file ' , (self fullNameFor: fn)) signal]]! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 4/4/2007 16:30'! entryAt: fileName "find the entry with local name fileName" ^ self entryAt: fileName ifAbsent: [ self error: 'file not in directory: ' , fileName ]! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 4/4/2007 16:31'! entryAt: fileName ifAbsent: aBlock "Find the entry with local name fileName and answer it. If not found, answer the result of evaluating aBlock." ^ self entries detect: [ : entry | entry name = fileName ] ifNone: aBlock! ! !ServerDirectory methodsFor: 'file directory' stamp: 'cmm 2/15/2010 16:01'! exists "It is difficult to tell if a directory exists. This is ugly, but it works for writable directories. http: will fall back on ftp for this" | probe | self isTypeFile ifTrue: [ self entries size > 0 ifTrue: [^ true]. probe := self newFileNamed: 'withNoName23'. probe ifNotNil: [ probe close. probe directory deleteFileNamed: probe localName]. ^probe notNil]. ^ [client := self openFTPClient. [self switchDirectory] ensure: [self quit]. true] on: Error do: [:ex | false]! ! !ServerDirectory methodsFor: 'initialize' stamp: 'cmm 4/5/2007 16:19'! switchDirectory client changeDirectoryTo: directory! ! !ServerDirectory methodsFor: 'up/download' stamp: 'cmm 2/15/2010 14:32'! getDirectory "Return a stream with a listing of the current server directory. (Later -- Use a proxy server if one has been registered.)" | listing | client := self openFTPClient. listing := [ self switchDirectory. client getDirectory] ensure: [self quit]. ^ReadStream on: listing! ! !ServerDirectory methodsFor: 'up/download' stamp: 'cmm 4/6/2007 16:07'! getFileNamed: fileNameOnServer into: dataStream httpRequest: requestString "Just FTP a file from a server. Return a stream. (Later -- Use a proxy server if one has been registered.)" | resp | self isTypeFile ifTrue: [ dataStream nextPutAll: (resp := FileStream oldFileNamed: server,(self serverDelimiter asString), self bareDirectory, (self serverDelimiter asString), fileNameOnServer) contentsOfEntireFile. dataStream dataIsValid. ^ resp]. self isTypeHTTP ifTrue: [ resp := HTTPSocket httpGet: (self fullNameFor: fileNameOnServer) args: nil accept: 'application/octet-stream' request: requestString. resp isString ifTrue: [^ dataStream]. "error, no data" dataStream copyFrom: resp. dataStream dataIsValid. ^ dataStream]. client := self openFTPClient. "Open passive. Do everything up to RETR or STOR" [self switchDirectory. client getFileNamed: fileNameOnServer into: dataStream] ensure: [self quit]. dataStream dataIsValid. ! ! !ServerDirectory methodsFor: 'up/download' stamp: 'cmm 4/4/2007 17:14'! putFile: fileStream named: fileNameOnServer "Just FTP a local fileStream to the server. (Later -- Use a proxy server if one has been registered.)" client := self openFTPClient. client binary. [self switchDirectory. client putFileStreamContents: fileStream as: fileNameOnServer] ensure: [self quit]! ! !ServerDirectory methodsFor: 'file-operations' stamp: 'cmm 3/23/2007 13:11'! recursiveDelete "Delete the this directory, recursing down its tree." self directoryNames do: [:dn | (self directoryNamed: dn) recursiveDelete]. self deleteLocalFiles. "should really be some exception handling for directory deletion, but no support for it yet" self containingDirectory deleteDirectory: self localName! ! !ServerDirectory class methodsFor: 'misc' stamp: 'cmm 4/17/2007 17:17'! parseFTPEntry: ftpEntry | tokens longy dateInSeconds thisYear thisMonth | thisYear := Date today year. thisMonth := Date today monthIndex. tokens := ftpEntry findTokens: ' '. tokens size = 8 ifTrue: [((tokens at: 6) size ~= 3 and: [(tokens at: 5) size = 3]) ifTrue: ["Fix for case that group is blank (relies on month being 3 chars)" tokens := tokens copyReplaceFrom: 4 to: 3 with: {'blank'}]]. tokens size >= 9 ifFalse:[^nil]. ((tokens at: 6) size ~= 3 and: [(tokens at: 5) size = 3]) ifTrue: ["Fix for case that group is blank (relies on month being 3 chars)" tokens := tokens copyReplaceFrom: 4 to: 3 with: {'blank'}]. tokens size > 9 ifTrue: [ "cmm: this approach fails for filenames containing two spaces in a row." longy := tokens at: 9. 10 to: tokens size do: [:i | longy := longy , ' ' , (tokens at: i)]. tokens at: 9 put: longy]. dateInSeconds := self secondsForDay: (tokens at: 7) month: (tokens at: 6) yearOrTime: (tokens at: 8) thisMonth: thisMonth thisYear: thisYear. ^DirectoryEntry name: (tokens at: 9) "file name" creationTime: dateInSeconds "creation date" modificationTime: dateInSeconds "modification time" isDirectory: ((tokens first first) = $d or: [tokens first first =$l]) "is-a-directory flag" fileSize: tokens fifth asNumber "file size" ! !