'From Squeak6.0alpha of 6 May 2018 [latest update: #17973] on 11 June 2018 at 9:03:03 am'!


!ProjectLoading class methodsFor: 'compatibility' stamp: 'tak 9/3/2006 11:00'!
checkSecurity: aFileName preStream: preStream projStream: projStream
	"Answer true if passed"
	| trusted enterRestricted |
	trusted := SecurityManager default positionToSecureContentsOf:
projStream.
	trusted ifFalse:
		[enterRestricted := (preStream isTypeHTTP or:
[aFileName isNil])
			ifTrue: [Preferences securityChecksEnabled]
			ifFalse: [Preferences standaloneSecurityChecksEnabled].
		enterRestricted
			ifTrue: [SecurityManager default enterRestrictedMode
				ifFalse:
					[preStream close.
					^ false]]].
	^ true
! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'tak 9/3/2006 00:17'!
checkStream: aStream 
	(aStream isNil
			or: [aStream size = 0])
		ifFalse: [^ false].
	ProgressNotification signal: '9999 about to enter
project'.
	"the hard part is over"
	self inform: 'It looks like a problem occurred while
getting this project. It may be temporary,
so you may want to try again,' translated.
	^ true! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'fbs 11/28/2013 18:40'!
fileInName: aFileName archive: archive morphOrList: morphOrList  
	| baseChangeSet substituteFont numberOfFontSubstitutes exceptions anObject mgr |
	ResourceCollector current: ResourceCollector new.
	baseChangeSet := ChangeSet current.
	self useTempChangeSet.		"named zzTemp"
	"The actual reading happens here"
	substituteFont := Preferences standardEToysFont copy.
	numberOfFontSubstitutes := 0.
	exceptions := Set new.
	[[anObject := morphOrList fileInObjectAndCodeForProject]
		on: MissingFont do: [ :ex |
				exceptions add: ex.
				numberOfFontSubstitutes := numberOfFontSubstitutes + 1.
				ex resume: substituteFont ]]
			ensure: [ ChangeSet  newChanges: baseChangeSet].
	mgr := ResourceManager new initializeFrom: ResourceCollector current.
	mgr fixJISX0208Resource.
	mgr registerUnloadedResources.
	archive ifNotNil:[mgr preLoadFromArchive: archive cacheName: aFileName].
	ResourceCollector current: nil.
	^ {anObject. numberOfFontSubstitutes. substituteFont. mgr}! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'tpr 4/11/2018 16:51'!
loadFromImagePath: projectName 
	"Open the project in image path. This is used with projects in OLPC distribution.
	- The image's directory is used.
	- Squeaklets directory is ignored.
	- If there is a project named projectName, it is opened.
	"
	"self openFromImagePath: 'Welcome'"
	| directory aStream entries fileName |
	(Project named: projectName)
		ifNotNil: [:project | ^ project].
	directory := FileDirectory on: Smalltalk imagePath.
	entries := Project latestProjectVersionsFromFileEntries: directory entries.
	fileName := (entries
		detect: [:each | (Project parseProjectFileName: each name) first = projectName]
		ifNone: [^ nil]) name.
	'Loading a Project...' displaySequentialProgress: [ProgressNotification signal: '0'.
			directory := FileDirectory on: Smalltalk imagePath.
			aStream := directory readOnlyFileNamed: fileName.
			^ self
				loadName: fileName
				stream: aStream
				fromDirectory: directory
				withProjectView: nil]! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'bf 4/9/2013 16:23'!
loadImageSegment: morphOrList  fromDirectory: aDirectoryOrNil withProjectView: existingView numberOfFontSubstitutes: numberOfFontSubstitutes substituteFont: substituteFont mgr: mgr

	| proj projectsToBeDeleted ef f |
	(f := (Flaps globalFlapTabWithID: 'Navigator' translated)) ifNotNil: [f hideFlap].
	proj := morphOrList arrayOfRoots
			detect: [:mm | mm isKindOf: Project]
			ifNone: [^ nil].
	numberOfFontSubstitutes > 0 ifTrue: [
		proj projectParameterAt: #substitutedFont put: substituteFont].
	ef := proj projectParameterAt: #eToysFont.
	(ef isNil or: [ef ~= substituteFont familySizeFace]) ifTrue: [
		proj projectParameterAt: #substitutedFont put: substituteFont.
	].
	proj projectParameters at: #MultiSymbolInWrongPlace put: false.
		"Yoshiki did not put MultiSymbols into outPointers in older images!!"
	morphOrList arrayOfRoots do: [:obj |
		obj fixUponLoad: proj seg: morphOrList "imageSegment"].
	(proj projectParameters at: #MultiSymbolInWrongPlace) ifTrue: [
		morphOrList arrayOfRoots do: [:obj | (obj isKindOf: Set) ifTrue: [obj rehash]]].

	proj resourceManager: mgr.
	"proj versionFrom: preStream."
	proj lastDirectory: aDirectoryOrNil.
	proj setParent: Project current.
	projectsToBeDeleted := OrderedCollection new.
	existingView == #none ifFalse: [
		self makeExistingView: existingView project: proj projectsToBeDeleted: projectsToBeDeleted].
	ChangeSorter allChangeSets add: proj changeSet.
	Project current projectParameters
		at: #deleteWhenEnteringNewProject
		ifPresent: [ :ignored |
			projectsToBeDeleted add: Project current.
			Project current removeParameter: #deleteWhenEnteringNewProject.
		].
	projectsToBeDeleted isEmpty ifFalse: [
		proj projectParameters
			at: #projectsToBeDeleted
			put: projectsToBeDeleted.
	].
	proj removeParameter: #eToysFont.
	^ proj! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'yo 9/8/2009 13:45'!
loadName: aFileName stream: preStream fromDirectory: aDirectoryOrNil
withProjectView: existingView

	^ self loadName: aFileName stream: preStream fromDirectory: aDirectoryOrNil
withProjectView: existingView clearOriginFlag: false.
! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'nice 6/10/2017 17:35'!
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: [^ nil].
	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: [^ nil].
	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.
		project removeParameter: #sugarProperties.
		Smalltalk at: #SugarPropertiesNotification ifPresent: [:notification |
			notification signal ifNotNil: [:props | 
				project keepSugarProperties: props monitor: true]].
		clearOriginFlag ifTrue: [project forgetExistingURL].
		ProgressNotification  signal: '0.8'.
		^ project
	].! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'dtl 11/23/2017 19:35'!
loadSexpProjectDict: dict stream: preStream fromDirectory: aDirectoryOrNil withProjectView: existingView

   	| archive anObject newProj d member memberStream members newSet allNames realName oldSet s |
	(self checkStream: preStream) ifTrue: [^ nil].
	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].
	self flag: #tfel. "load all projects and save them again in the new format, then get rid of the error block!!"
	s := memberStream basicUpToEnd.
	d := [(DataStream on: memberStream) next] on: Error do: [:e |
		(Smalltalk at: #MSExpParser) parse: s with: #ksexp].
	anObject := d sissReadObjectsAsEtoysProject.
	preStream close.

	"anObject := (MSExpParser parse: (archive membersMatching: '*.sexp') first contents with: #ksexp) sissReadObjects."
	anObject ifNil: [^ nil].
	(anObject isKindOf: PasteUpMorph) ifFalse: [^ Project current world addMorph: anObject].
	ProgressNotification  signal: '0.7'.
	newProj := MorphicProject new.
	newProj installPasteUpAsWorld: 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: 'compatibility' stamp: 'dtl 6/4/2013 06:50'!
makeExistingView: existingView project: proj projectsToBeDeleted: projectsToBeDeleted
		existingView ifNil: [
			Smalltalk isMorphic ifTrue: [
				proj createViewIfAppropriate.
			] ifFalse: [
				ChangeSorter allChangeSets add: proj changeSet.
				Project current openProject:  proj.
				"Note: in MVC we get no further than the above"
			].
		] ifNotNil: [
			(existingView project isKindOf: DiskProxy) ifFalse: [
				existingView project changeSet name: 
ChangeSet defaultName.
				projectsToBeDeleted add: existingView project.
			].
			(existingView owner isSystemWindow) ifTrue: [
				existingView owner model: proj
			].
			existingView project: proj.
		].
! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'cmm 10/23/2013 16:24'!
morphOrList: aFileName stream: preStream fromDirectory: aDirectoryOrNil archive: archive
	"Answer morphOrList or nil if problem happened"
	|  projStream localDir morphOrList |
	projStream := archive
		ifNil: [preStream]
		ifNotNil: [self projectStreamFromArchive: archive].
	(self checkSecurity: aFileName preStream: preStream projStream: projStream)
		ifFalse: [^nil].
	localDir := Project squeakletDirectory.
	aFileName ifNotNil: [
		(aDirectoryOrNil isNil or: [aDirectoryOrNil pathName
~= localDir pathName]) ifTrue: [
			localDir deleteFileNamed: aFileName.
			(localDir fileNamed: aFileName) binary
				nextPutAll: preStream remainingContents;
				close.
		].
	].
	morphOrList := projStream asUnZippedStream.
	preStream sleep.		"if ftp, let the connection close"
	^ morphOrList
! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'tfel 8/11/2016 09:52'!
openFromImagePath: projectName 
	| project |
	project := self loadFromImagePath: projectName.
	project
		ifNil: [self inform: 'That didn''t work. Sorry' translated]
		ifNotNil: [project enter].! !

!ProjectLoading class methodsFor: 'compatibility' stamp: 'yo 2/5/2008 17:15'!
parseManifest: aString

	| dict line index key value aStream |
	aStream := aString readStream.
	dict := Dictionary new.
	[(line := aStream nextLine) notNil] whileTrue: [
		index := line indexOf: $:.
		index > 0 ifTrue: [
			key := line copyFrom: 1 to: index - 1.
			value := (line copyFrom: index + 1 to: line size) withBlanksTrimmed.
			dict at: key put: value.
		].
	].
	^ dict.! !
