copyImageFilesFrom: aStartPageName usingNaming: aNameBlock toExternalUsing: writePictureFilesAndReturnUrls reportOn: aPathString "The report may have links to the PRFiles, so consider its location (having aStartPage as a parent prevents the file from being overwritten). User is responsible to select a aStartPageName that does not have private pictures under it" | reportPage files urlContents | self guessTodoFromPath: aPathString. (reportPage := PRPathLookup start: self kernel root path: aPathString) ifNotNil: [ reportPage contents: (String streamContents: [ :outputStream | | batchesOfFiles batchesOfFilesToLinks linksToFile pictureUrls errorLinks | batchesOfFilesToLinks := Dictionary new. files := (PRPathLookup start: self kernel root path: aStartPageName) enumerator everything select: [ :e | e isFile and: [ e isImage ] ]. files isEmpty ifTrue: [ self printReportHeaderOn: outputStream fields: 'No files found' ] ifFalse: [ self printReportHeaderOn: outputStream fields: '|!File|!Comment'. files do: [ :file | ((file title reject: [ :c | '-_.:' includes: c ]) isAllAlphaNumerics and: [ file title includes: $. ]) ifFalse: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|needs a title to be used for the file name, edit it to change the title.'; cr ] ifTrue: [ file hasChildren ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|Has children, these should be removed first.'; cr ] ifFalse: [ file isRoot ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|Should not be the root, removing this would be very bad.'; cr ] ifFalse: [ ([ [ (urlContents := (aNameBlock value: file) asUrl retrieveContents) isEmpty ] on: ZnHttpUnsuccessful do: [ true ] ] on: ConnectionTimedOut do: [ true ]) ifFalse: [ urlContents = file contents asByteArray ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|Should be replaced with: <img src="'; nextPutAll: (aNameBlock value: file) asString; nextPutAll: '" />'; cr ] ifFalse: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|File does not match the contents of *'; nextPutAll: (aNameBlock value: file) asString; nextPutAll: '* - please investigate.'; cr ] ] ifTrue: [ errorLinks := (linksToFile := self kernel root incomingReferences to: file) reject: [ :link | link isEmbedded or: [ link owner = reportPage ] ]. linksToFile size = 0 ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|Has no links to it, need to wait until there is an embedded link to this.'; cr ] ifFalse: [ errorLinks isNotEmpty ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: file absolutePath; nextPutAll: '*|Has a non-embedded link on *'; nextPutAll: errorLinks anyOne owner absolutePath; nextPutAll: '* - this should be embedded.'; cr; cr ] ifFalse: [ batchesOfFilesToLinks at: file put: linksToFile ] ] ] ] ] ] ]. writePictureFilesAndReturnUrls value: (batchesOfFiles := batchesOfFilesToLinks keys). pictureUrls := batchesOfFiles collect: aNameBlock. batchesOfFiles with: pictureUrls do: [ :prFile :urlString | urlString isEmpty ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: prFile absolutePath; nextPutAll: '*|The URL is empty, unable to create the picture file.'; cr ] ifFalse: [ ([ urlString asUrl retrieveContents isEmpty ] on: ZnHttpUnsuccessful do: [ true ]) ifTrue: [ outputStream nextPutAll: '|*'; nextPutAll: prFile absolutePath; nextPutAll: '*|The URL is *'; nextPutAll: urlString; nextPutAll: '* - but has an error retrieving the contents.'; cr ] ifFalse: [ (batchesOfFilesToLinks at: prFile) do: [ :link | outputStream nextPutAll: '|*'; nextPutAll: link owner absolutePath; nextPutAll: '*|Update to have <img src="'; nextPutAll: urlString asString; nextPutAll: '" /> for =='; nextPutAll: prFile title; nextPutAll: '== and remove: *'; nextPutAll: prFile absolutePath; nextPutAll: '*.' cr ] ] ] ] ] ]) ]