'From etoys4.0 of 9 October 2008 [latest update: #2296] on 11 September 2009 at 11:34:03 pm'! "Change Set: manifestAdditions-sw Date: 11 September 2009 Author: Scott Wallace Adds items to the project manifest: user The squeakland user-name of the user publishing the project, if the user is logged in; if not logged in, this will be 'unknown'. URI A URI of the form http://squeakland.org/etoys/- prev-URI The prior URI for this project, if user has changed "! !Project methodsFor: 'file in/out' stamp: 'sw 9/11/2009 23:31'! noteManifestDetailsIn: manifestInfo "The receiver is a project being loaded. From the dictionary provided, absorb and remember whether it's an 'old' (pre-olpc) project, and remember the GUID, user, and prev-GUID associated with the project when these data are available in the incoming manifest." | manifestDict oldProject | manifestInfo isEmptyOrNil ifTrue: [^ self projectParameterAt: #oldProject put: true]. manifestDict := (manifestInfo isKindOf: Dictionary) ifTrue: [manifestInfo] ifFalse: [manifestInfo first]. oldProject := ((manifestDict at: 'Squeak-Version' ifAbsent: ['']) beginsWith: 'etoys') not. self projectParameterAt: #oldProject put: oldProject. manifestDict at: 'URI' ifPresent: [:aUri | self projectParameterAt: 'URI' put: aUri]. manifestDict at: 'user' ifPresent: [:aUser | self projectParameterAt: 'user' put: aUser]. manifestDict at: 'prev-URI' ifPresent: [:aUri | self projectParameterAt: 'prev-URI' put: aUri]! ! !Project methodsFor: 'file in/out' stamp: 'sw 9/11/2009 23:30'! storeAttributesOn: aStream "For the manifest: write a series of cr-delimited records of the form : to a stream." | details loggedInAs incomingUser existingUri uri uriPrefix | self storeAttributeKey: 'Squeak-Version' value: SystemVersion current version on: aStream. self storeAttributeKey: 'Squeak-LatestUpdate' value: SystemVersion current highestUpdate printString on: aStream. self storeAttributeKey: 'File-Name-Encoding' value: LanguageEnvironment defaultFileNameConverter class encodingNames first on: aStream. self storeAttributeKey: 'Project-Language' value: Locale current localeID printString on: aStream. loggedInAs := 'unknown'. Utilities loggedIn ifTrue: [ServerDirectory servers at: 'My Squeakland' ifPresent: [:server | loggedInAs := server userPerSe ifNil: ['unknown']]]. incomingUser := self projectParameterAt: #user ifAbsent: ['unknown']. "If the project was loaded from outside, this will be the user associated with that outside version" existingUri := self projectParameterAt: #URI ifAbsent: [nil]. uriPrefix := 'http://squeakland.org/etoys/'. uri := uriPrefix, loggedInAs, '-', Time totalSeconds printString. existingUri ifNotNil: [incomingUser = loggedInAs ifTrue: [uri := existingUri. (self projectParameterAt: 'prev-URI') ifNotNilDo: [:prior | self storeAttributeKey: 'prev-URI' value: prior on: aStream]] ifFalse: [incomingUser = 'unknown' ifTrue: "saved as unknown user, now publishing as registered user; teefal wants new uri but using original epoch in this case." [uri := String streamContents: [:str | str nextPutAll: uriPrefix. str nextPutAll: loggedInAs, ':'. str nextPutAll: (existingUri copyAfterLast: $:)]]. self storeAttributeKey: 'prev-URI' value: existingUri on: aStream]]. self storeAttributeKey: 'URI' value: uri on: aStream. self storeAttributeKey: 'user' value: loggedInAs on: aStream. details _ self world valueOfProperty: #ProjectDetails ifAbsent: [Dictionary new]. Project publishInSexp ifTrue: [ self storeAttributeKey: 'Project-Format' value: 'S-Expression' on: aStream. self storeAttributeKey: 'Project-Format-Version' value: '1.0' on: aStream. ] ifFalse: [ self storeAttributeKey: 'Project-Format' value: 'ImageSegment' on: aStream. ]. details associationsDo: [:assoc | self storeAttributeKey: assoc key asString value: assoc value asString on: aStream.]! ! !ProjectLoading class methodsFor: 'private' stamp: 'sw 9/11/2009 01:45'! loadSexpProjectDict: dict stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView | archive anObject newProj d member b s memberStream members newSet allNames realName oldSet | (self checkStream: preStream) ifTrue: [^ self]. ProgressNotification signal: '0.2'. preStream reset. archive _ preStream isZipArchive ifTrue:[ZipArchive new readFrom: preStream] ifFalse:[nil]. members _ archive membersMatching: '*.cs'. members do: [:e | newSet _ ChangeSorter newChangesFromStream: e contentStream named: 'zzTemp', Time totalSeconds printString]. member _ (archive membersMatching: '*.sexp') first. memberStream _ member contentStream. (self checkSecurity: member name preStream: preStream projStream: memberStream) ifFalse: [^nil]. b _ String new: member uncompressedSize. s _ RWBinaryOrTextStream on: b. s binary. s nextPutAll: memberStream basicUpToEnd. s reset. d _ DataStream on: s. anObject _ d next sissReadObjectsAsEtoysProject. "anObject _ (MSExpParser parse: (archive membersMatching: '*.sexp') first contents with: #ksexp) sissReadObjects." anObject ifNil: [^ self]. (anObject isKindOf: PasteUpMorph) ifFalse: [^ World addMorph: anObject]. preStream close. ProgressNotification signal: '0.7'. newProj _ Project newMorphicOn: anObject. newSet ifNotNil: [oldSet _ newProj changeSet. newProj setChangeSet: newSet. ChangeSorter removeChangeSet: oldSet]. dict at: 'projectname' ifPresent: [:n | allNames _ Project allNames. realName _ Utilities keyLike: n satisfying: [:nn | (allNames includes: nn) not]. newProj renameTo: realName. ]. anObject valueOfProperty: #projectVersion ifPresentDo: [:v | newProj version: v]. newProj noteManifestDetailsIn: dict. ProgressNotification signal: '0.8'. ^ newProj. ! ! !ProjectLoading class methodsFor: 'private' stamp: 'sw 9/11/2009 01:47'! openSexpProjectDict: dict stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView | archive anObject newProj d member b s memberStream members newSet allNames realName oldSet | (self checkStream: preStream) ifTrue: [^ self]. ProgressNotification signal: '0.2'. preStream reset. archive _ preStream isZipArchive ifTrue:[ZipArchive new readFrom: preStream] ifFalse:[nil]. members _ archive membersMatching: '*.cs'. members do: [:e | newSet _ ChangeSorter newChangesFromStream: e contentStream named: 'zzTemp', Time totalSeconds printString]. member _ (archive membersMatching: '*.sexp') first. memberStream _ member contentStream. (self checkSecurity: member name preStream: preStream projStream: memberStream) ifFalse: [^nil]. b _ String new: member uncompressedSize. s _ RWBinaryOrTextStream on: b. s binary. s nextPutAll: memberStream basicUpToEnd. s reset. d _ DataStream on: s. anObject _ d next sissReadObjectsAsEtoysProject. "anObject _ (MSExpParser parse: (archive membersMatching: '*.sexp') first contents with: #ksexp) sissReadObjects." anObject ifNil: [^ self]. (anObject isKindOf: PasteUpMorph) ifFalse: [^ World addMorph: anObject]. preStream close. ProgressNotification signal: '0.7'. newProj _ Project newMorphicOn: anObject. newSet ifNotNil: [oldSet _ newProj changeSet. newProj setChangeSet: newSet. ChangeSorter removeChangeSet: oldSet]. dict at: 'projectname' ifPresent: [:n | allNames _ Project allNames. realName _ Utilities keyLike: n satisfying: [:nn | (allNames includes: nn) not]. newProj renameTo: realName. ]. anObject valueOfProperty: #projectVersion ifPresentDo: [:v | newProj version: v]. newProj noteManifestDetailsIn: dict. ProgressNotification signal: '0.8'. ^ newProj ifNil: [self inform: 'No project found in this file' translated] ifNotNil: [ProjectEntryNotification signal: newProj]. ! ! !ProjectLoading class methodsFor: 'public' stamp: 'sw 9/11/2009 01:43'! loadName: aFileName stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView clearOriginFlag: clearOriginFlag "Reconstitute a Morph from the selected file, presumed to be represent a Morph saved via the SmartRefStream mechanism, and open it in an appropriate Morphic world." | morphOrList archive mgr substituteFont numberOfFontSubstitutes resultArray anObject project manifests dict | (self checkStream: preStream) ifTrue: [^ self]. ProgressNotification signal: '0.2'. archive _ preStream isZipArchive ifTrue:[ZipArchive new readFrom: preStream] ifFalse:[nil]. manifests _ (archive membersMatching: '*manifest'). (manifests size = 1 and: [((dict _ self parseManifest: manifests first contents) at: 'Project-Format' ifAbsent: []) = 'S-Expression']) ifTrue: [^ self loadSexpProjectDict: dict stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView]. morphOrList _ self morphOrList: aFileName stream: preStream fromDirectory: aDirectoryOrNil archive: archive. morphOrList ifNil: [^ self]. ProgressNotification signal: '0.4'. resultArray _ self fileInName: aFileName archive: archive morphOrList: morphOrList. anObject _ resultArray first. numberOfFontSubstitutes _ resultArray second. substituteFont _ resultArray third. mgr _ resultArray fourth. preStream close. ProgressNotification signal: '0.7'. "the hard part is over" (anObject isKindOf: ImageSegment) ifTrue: [ project _ self loadImageSegment: anObject fromDirectory: aDirectoryOrNil withProjectView: existingView numberOfFontSubstitutes: numberOfFontSubstitutes substituteFont: substituteFont mgr: mgr. project noteManifestDetailsIn: dict. clearOriginFlag ifTrue: [project forgetExistingURL]. ProgressNotification signal: '0.8'. ^ project ].! ! !ProjectLoading class methodsFor: 'public' stamp: 'sw 9/11/2009 01:46'! openName: aFileName stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView clearOriginFlag: clearOriginFlag "Reconstitute a Morph from the selected file, presumed to represent a Morph saved via the SmartRefStream mechanism, and open it in an appropriate Morphic world." | morphOrList archive mgr substituteFont numberOfFontSubstitutes resultArray anObject project manifests dict | (self checkStream: preStream) ifTrue: [^ self]. ProgressNotification signal: '0.2'. archive _ preStream isZipArchive ifTrue:[ZipArchive new readFrom: preStream] ifFalse:[nil]. archive ifNotNil:[ manifests _ (archive membersMatching: '*manifest'). (manifests size = 1 and: [((dict _ self parseManifest: manifests first contents) at: 'Project-Format' ifAbsent: []) = 'S-Expression']) ifTrue: [^ self openSexpProjectDict: dict stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView]]. morphOrList _ self morphOrList: aFileName stream: preStream fromDirectory: aDirectoryOrNil archive: archive. morphOrList ifNil: [^ self]. ProgressNotification signal: '0.4'. resultArray _ self fileInName: aFileName archive: archive morphOrList: morphOrList. anObject _ resultArray first. numberOfFontSubstitutes _ resultArray second. substituteFont _ resultArray third. mgr _ resultArray fourth. preStream close. ProgressNotification signal: '0.7'. "the hard part is over" (anObject isKindOf: ImageSegment) ifTrue: [ project _ self loadImageSegment: anObject fromDirectory: aDirectoryOrNil withProjectView: existingView numberOfFontSubstitutes: numberOfFontSubstitutes substituteFont: substituteFont mgr: mgr.]. (anObject isKindOf: ImageSegment) ifTrue: [ project noteManifestDetailsIn: dict. clearOriginFlag ifTrue: [project forgetExistingURL]. ProgressNotification signal: '0.8'. ^ project ifNil: [self inform: 'No project found in this file' translated] ifNotNil: [ProjectEntryNotification signal: project]]. self loadSqueakPage: anObject! ! !ServerDirectory methodsFor: 'accessing' stamp: 'sw 9/10/2009 19:34'! userPerSe "Answer the user, even if nil. No interaction ensues." ^ user! !