From VisualWorks®, 7.5 of April 16, 2007 on October 30, 2007 at 8:04:50 am (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>AAADocumentation</name> <environment>Swazoo</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Seaside/Swazoo</category> <attributes> <package>Seaside/Swazoo</package> </attributes> </class> <class> <name>SeasideResource</name> <environment>Swazoo</environment> <super>Swazoo.Resource</super> <private>false</private> none <imports></imports> <category>Swazoo-Resources</category> <attributes> <package>Seaside/Swazoo</package> </attributes> </class> <class> <name>GIFImage</name> <environment>Seaside</environment> <super>Graphics.PixelArray</super> <private>false</private> none gifBytes height width bitsPerPixel palette cachedVisual <imports></imports> <category>Wave-Support-Bitmaps</category> <attributes> <package>Seaside/GIF</package> </attributes> </class> <comment> Seaside.GIFImage
GIFImage represents a bitmap image in the "Graphics Interchange Format" commonly used on the Internet. Notable features of GIFs: - use a lossless compression technique for compactness - support the idea of a "transparent" pixel value, where any backdrop shows through - support bit depths of 1, 2, 4, and 8 To display on screen, a GIFImage must go through a time-consuming conversion process, so a cached version of the native visual is kept around. Examples that read and write gif images to a file: To capture an image from the screen and write it out as a gif file, use an expression similar to: BitmapImageStorage putImage: Image fromUser onFileNamed: 'foo.gif' encoder: GIFEncoder new. To read in a .gif file and display it for testing purposes: (BitmapImageStorage imageFromFileNamed: 'foo.gif' encoder: GIFEncoder new) displayOn: ScheduledControllers activeController view graphicsContext at: 0@0. Read in a .gif file, shrink, and magnifiy it: | gifImage smallerImage | gifImage := BitmapImageStorage imageFromFileNamed: 'foo.gif' encoder: GIFEncoder new. gifImage displayOn: ScheduledControllers activeController view graphicsContext at: 0@0. smallerImage := gifImage shrunkenBy: 0.75 @ 0.75. smallerImage displayOn: ScheduledControllers activeController view graphicsContext at: 100@0. smallerImage := gifImage magnifiedBy: 2@2. smallerImage displayOn: ScheduledControllers activeController view graphicsContext at: 200@0. Instance Variables: gifBytes <ByteArray> the raw bytes of a GIF-formatted image height <Integer> width <Integer> bitsPerPixel <Integer> palette <Palette> cachedVisual <Image | OpaqueImage> an OpaqueImage is used when there is a transparent bit Class Variables: OnePixelTemplate <ByteArray> a 1@1 GIF that can easily be changed to a desired color TransparentOnePixelGIF <GIFImage> a 1@1 transparent GIF
</comment> <class> <name>BitmapImageEncoder</name> <environment>Seaside</environment> <super>Core.Object</super> <private>false</private> none stream <imports></imports> <category>Wave-Support-Bitmaps</category> <attributes> <package>Seaside/GIF</package> </attributes> </class> <comment> Seaside.BitmapImageEncoder
BitmapImageEncoder is an abstract class to provide for encoding and/or decoding an image on a stream. Subclasses must implement the following messages: accessing nextImage nextPutImage: Instance Variables: stream <ReadStream | WriteStream> stream for image storages Class Variables: ImageNotStoredSignal <Signal> image not stored error signal MagicNumberErrorSignal <Signal> magic number error signal
</comment> <class> <name>SeasideSite</name> <environment>Swazoo</environment> <super>Swazoo.Site</super> <private>false</private> none seasideResource <imports></imports> <category>Swazoo-Resources</category> <attributes> <package>Seaside/Swazoo</package> </attributes> </class> <class> <name>GUFEncoder</name> <environment>Seaside</environment> <super>Seaside.BitmapImageEncoder</super> <private>false</private> none width height bitsPerPixel colorPalette rowByteSize xpos ypos pass interlace codeSize clearCode eoiCode freeCode maxCode prefixTable suffixTable remainBitCount bufByte bufStream transparentPixel <imports></imports> <category>Wave-Support-Bitmaps</category> <attributes> <package>Seaside/GIF</package> </attributes> </class> <comment> Seaside.GUFEncoder
GUFEncoder provides for encoding and/or decoding an image on a stream using the Graphic Interchange Format. GIF and 'Graphics Interchange Format' are trademarks of CompuServe, Incorporated. GUF is the Uncompressed version of GIF. The decoder algorithm in this class uses an uncompressed GIF-compatible format that does not require the licensing of the GIF LZW compression algorithm from Unisys. These bitmaps render properly in well-implemented GIF viewers (including almost all web browsers) but are typically anywhere from 2 to 20 times as large as compressed GIFs. A subclass, GIFEncoder, should contain the LZW encoding and decoding algorithms. In Swazoo 2.0, the default encoder for a GIFImage is the GUFEncoder and the default decoder for a GIFImage is the GIFEncoder. The LZW compression capability is covered by Unisys Patent No. 4,588,302. Because of licensing restrictions, the LZW encoding algorithm is not actually used in the GIFEncoder class in Swazoo 2.0. (GIFEncoder>writeBitData: uses the uncompressed algorithm from its superclass). After signing a license agreement with UniSys for the LZW compression capability, contact ParcPlace technical support for the true GIF compressed LZW encoding implementation. Extended Aug 1995 to handle GIF89a GraphicsControlExtensionBlocks and thus to some extent transparency. Instance Variables: width <SmallInteger> width of image height <SmallInteger> height of image bitsPerPixel <SmallInteger> number of bits per pixel of image colorPalette <MappedPalette> color palette of image rowByteSize <SmallInteger> row byte size of bits of image xpos <SmallInteger> x position of bits of image ypos <SmallInteger> y position of bits of image pass <SmallInteger> pass count used at interlace mode interlace <Boolean> each image row is interlaced or sequential codeSize <SmallInteger> code bits size clearCode <SmallInteger> special clear code of GIF spec. eoiCode <SmallInteger> special end of information code of GIF spec. freeCode <SmallInteger> first available code maxCode <SmallInteger> max code value prefixTable <Array of: SmallInteger> string prefix table suffixTable <Array of: SmallInteger> string suffix table remainBitCount <SmallInteger> number of unaccessed bits for bits accessing bufByte <SmallInteger> buffer byte for bits accessing bufStream <ReadStream | WriteStream> buffer stream for packing transparentPixel <SmallInteger> pixel value that should be considered transparent Class Variables: Extension <SmallInteger> GIF Extension ImageSeparator <SmallInteger> GIF Image Separator Terminator <SmallInteger> GIF Terminator GraphicControlLabel <SmallInteger> GIF GraphicControlBlock indicator
</comment> <class> <name>GIFEncoder</name> <environment>Seaside</environment> <super>Seaside.GUFEncoder</super> <private>false</private> none <imports></imports> <category>Wave-Support-Bitmaps</category> <attributes> <package>Seaside/GIF</package> </attributes> </class> <comment> Seaside.GIFEncoder
GIFEncoder is supposed to encode and decode GIFImages with the LZW encoding and decoding GIF algorithms. GIF and 'Graphics Interchange Format' are trademarks of CompuServe, Incorporated. The LZW compression capability is covered by Unisys Patent No. 4,588,302. Because of licensing restrictions, the LZW encoding algorithm is not actually used in the default GIFEncoder class in Swazoo 2.0. (GIFEncoder>writeBitData: uses the uncompressed algorithm from its superclass). After signing a license agreement with UniSys for the LZW compression capability you may file in the true GIF compressed LZW encoding implementation from a file in the extras directory. See the superclass comment for more information.
</comment> <class> <name>HTTPCookie</name> <environment>Swazoo</environment> <super>Core.Object</super> <private>false</private> none name value expires path domain secure comment <imports></imports> <category>Wave-Net</category> <attributes> <package>Swazoo/Patches</package> </attributes> </class> <comment> Swazoo.HTTPCookie
HTTPCookies are a general mechanism that Swazoo applications can use to both store and retrieve information on the client (web browser) side of the connection. Each HTTPCookie is essentially a name=value pair that may contain additional information. This information is sent to the browser in the form of an HTTP header message and returned in the same fashion as an entity header. Instance Variables: name <String> Name of the cookie value <String> Value of the cookie expires <Timestamp> When this time is reached, the browser may discard the cookie [optional] domain <String> The browser must be speaking to this domain before it will return the cookie [optional] path <String> This must be a prefix of the URL path before the browser will return the cookie [optional] secure <Boolean> If this is true, the cookie will only be returned if we are using a secure server
</comment> <name>DispatcherVersions</name> <environment>Swazoo.SeasideResource</environment> <private>false</private> <constant>false</constant> <category>Globals</category> <initializer>nil</initializer> <attributes> <package>Seaside/Swazoo</package> </attributes> <name>DefaultDispatcherInitialized</name> <environment>Swazoo.SeasideResource</environment> <private>false</private> <constant>false</constant> <category>Globals</category> <initializer>false</initializer> <attributes> <package>Seaside/Swazoo</package> </attributes> <name>Dispatchers</name> <environment>Swazoo.SeasideResource</environment> <private>false</private> <constant>false</constant> <category>Globals</category> <initializer>nil</initializer> <attributes> <package>Seaside/Swazoo</package> </attributes> <name>ImageNotStoredSignal</name> <environment>Seaside.BitmapImageEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>MagicNumberErrorSignal</name> <environment>Seaside.BitmapImageEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>Terminator</name> <environment>Seaside.GUFEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>ImageSeparator</name> <environment>Seaside.GUFEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>GraphicControlLabel</name> <environment>Seaside.GUFEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>Extension</name> <environment>Seaside.GUFEncoder</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>PreferredDecoderClass</name> <environment>Seaside.GIFImage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>OnePixelTemplate</name> <environment>Seaside.GIFImage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>TransparentOnePixelGIF</name> <environment>Seaside.GIFImage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <name>PreferredEncoderClass</name> <environment>Seaside.GIFImage</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Seaside/GIF</package> </attributes> <methods> Swazoo.AAADocumentation <category>samples</category>
adjustTimeZone "((( AAADocumentation new adjustTimeZone )))" "1. Establish VW Time Zone as Central Europe Time" Core.TimeZone setDefaultTimeZone: (Core.TimeZone timeDifference: 1 DST: 1 start: 2 end: 3 from: 90 "on March 31" to: 304 "until October 31" startDay: #Sunday). "2. Propagate to Squeak, propagation required for cookie support" Squeak.DateAndTime.LocalTimeZone := (Squeak.TimeZone offset: (Core.TimeZone default secondsFromGMTAtLocal: Timestamp now) seconds name: 'Central Europe' abbreviation: 'CET'). Squeak.Week startDay: #Monday.
createSwazooServer "((( AAADocumentation new createSwazooServer )))" | server site | server := SwazooServer singleton. (site := server siteNamed: self demoSeasideSiteName) ifNotNil: [server removeSite: site]. server addSite: self demoSeasideSite; start
createSwazooServerFromXML "Not adequate, according to Janko Mivsek" "((( AAADocumentation new createSwazooServerFromXML )))" SwazooServer configureFromStream: ('<Site> <SiteIdentifier ip: ''127.0.0.1'' port: ' , self serverPortNumber displayString, ' host: ''localhost''> <CompositeResource uriPattern: ''/''> <CompositeResource uriPattern: ''foo''> <HelloWorldResource uriPattern: ''Howdy''> </CompositeResource> </CompositeResource> <FileResource uriPattern: ''/'' filePath: ''.''> <CompositeResource uriPattern: ''/''> <CompositeResource uriPattern: ''' , self webSiteName , '''> <SeasideResource uriPattern: ''go''> </CompositeResource> </CompositeResource> </Site>') readStream
demoSeasideSite ^(SeasideSite new) name: self demoSeasideSiteName; initialize; host: self serverHostname ip: self serverIpString port: self serverPortNumber; initializeResourceFromUriPattern: '/' , self webSiteName.
demoSeasideSiteName ^'Seaside'
removeSwazooServer "((( AAADocumentation new removeSwazooServer )))" | server site | server := SwazooServer singleton. (site := server siteNamed: self demoSeasideSiteName) ifNotNil: [server removeSite: site].
startSeasideSite "((( AAADocumentation new startSeasideSite )))" (SwazooServer singleton siteNamed: self demoSeasideSiteName) start
startSwazooServer "((( AAADocumentation new startSwazooServer )))" (SwazooServer singleton) removeAllSites; addSite: self demoSeasideSite; start
</methods> <methods> Swazoo.AAADocumentation <category>private - install</category>
basicInstall self installationOptions createServer ifTrue: [self createSwazooServer]. self installationOptions setTimeZone ifTrue: [self adjustTimeZone]. Seaside.SeasideInstallerComplete open
basicRemoval self installationOptions createServer ifTrue: [self removeSwazooServer].
browseUrl ^ self installationOptions browseUrl
checkObjectStudio "Ugly code to deal with semantic differences of + Alter the behavior only if ObjectStudio is there" 'ObjectStudio.GlobalDictionary' asQualifiedReference ifDefinedDo: [:obj | self modifySqueakBehavior]
installationOptions ^Seaside.SeasideInstallationOptions default
isUpgrade ^ Smalltalk at: #SeasideUpgrade ifAbsent: [false]
modifySqueakBehavior String compile: '+ arg "This code was dynamically created during installation of Seaside, because of the presence of ObjectStudio. See AAADocumentation >> checkObjectStudio" | env | env := thisContext sender mclass environment. env == Seaside ifTrue: [^arg adaptToString: self andSend: #+.]. env == Squeak ifTrue: [^arg adaptToString: self andSend: #+.]. ^self , arg asString. ' classified: 'Seaside+ObjectStudio'.
postInitialization "Sent by the bundle post-load" "((( AAADocumentation new postInitialization )))" self report: ''. self report: 'Seaside installation started'. self isUpgrade ifTrue: [^self report: 'Seaside upgraded to version ' , SeasidePlatformSupport seasideVersion]. SeasidePlatformSupport isConfigured ifFalse: [self basicInstall] ifTrue: [SeasidePlatformSupport install]. self checkObjectStudio. self report: ''. self report: 'Seaside installation complete, version ', SeasidePlatformSupport seasideVersion.
preUnload "Sent by the bundle pre-unload" "((( AAADocumentation new preUnload )))" self isUpgrade ifTrue: [^self]. self report: ''. self report: 'Seaside removal started'. SeasidePlatformSupport isConfigured ifFalse: [self basicRemoval] ifTrue: [SeasidePlatformSupport removeSeaside].
report: aString Transcript show: aString; cr
serverHostname ^self installationOptions serverHostname
serverIpString ^self installationOptions serverIpString
serverPortNumber ^self installationOptions portNumber
webSiteName ^self installationOptions siteName
</methods> <methods> Swazoo.AAADocumentation <category>documentation</category>
settingThingsUp " If you loaded the Seaside-Swazoo bundle succesfully, you should have Swazoo loaded as well. If you answered 'yes' to the question 'Do you want to set up a sample Swazoo/Seaside server ?', you should have a Server running already. If you answered 'no', you may need to create and start a server. Here is how you should proceed : - Execute the statement below in a Workspace SiteRegistry configureFrom: 'sites.cnf' This version of Seaside runs as a Swazoo resource, all Seaside applications reside under <your server>/<your site>/<resourcename> For instance http://localhost:8008/seaside/counter http://localhost:8008/seaside/store http://localhost:8008/seaside/config If you answered 'yes' to the question 'Do you want to set up a sample Swazoo/Seaside site ?', the defined Seaside site is named 'seaside/go', therefore you need to use the following URL's to reach the Seaside applications http://localhost:8008/seaside/go/counter http://localhost:8008/seaside/go/store http://localhost:8008/seaside/go/config Then proceed with the Seaside tutorial at the link below http://www.cincomsmalltalk.com/CincomSmalltalkWiki/Seaside+Tutorial "
</methods> <methods> Swazoo.AAADocumentation class <category>initialize-release</category>
initialize ObjectMemory removeDependent: self. ObjectMemory addDependent: self.
update: anAspect anAspect == #aboutToSnapshot ifTrue: [SwazooServer stop]. anAspect == #finishedSnapshot ifTrue: [SwazooServer start]. anAspect == #aboutToSnapshot ifTrue: [SwazooServer stop]. anAspect == #returnFromSnapshot ifTrue: [SwazooServer start].
</methods> <methods> Swazoo.SeasideResource <category>private</category>
adjustContentType: waResponse | hasCharSet isText tokens | "Seaside does not always supplies the charset=" hasCharSet := false. isText := false. tokens := waResponse contentType findTokens: ';'. tokens do: [ :ea | isText := isText or: [(ea trimBlanks asLowercase copyFrom: 1 to: 4) = 'text']. hasCharSet := hasCharSet or: [(ea trimBlanks asLowercase copyFrom: 1 to: 8) = 'charset=']]. (isText and: [ hasCharSet not ]) ifTrue: ["Add the missing charset spec" waResponse contentType: waResponse contentType , '; charset=utf-8'].
convertRequest: aSwazooRequest "See WAKom >> convertRequest:" | waRequest | waRequest := self waRequestClass method: aSwazooRequest method url: aSwazooRequest uriString headers: (self unwrapHeaders: aSwazooRequest) fields: (self unwrapFields: aSwazooRequest) cookies: (self unwrapCookies: aSwazooRequest). aSwazooRequest isPut ifTrue: [self error: 'Unsupported HTTP method PUT'. waRequest fields at: 'PUTData' put: String new]. ^ waRequest.
convertResponse: waResponse | swazooResponse hasExpire | "See WAKom >> convertResponse:" swazooResponse := Swazoo.HTTPResponse new code: waResponse status asNumber. hasExpire := false. waResponse headers associationsDo: [:eachHeader | swazooResponse addHeaderName: eachHeader key value: eachHeader value. "Seaside sets the 'expires' HTTP header for the cachable items We add the 'cachecontrol' header" eachHeader key asLowercase = 'expires' ifTrue: [hasExpire := true. swazooResponse addHeaderName: 'cache-control' value: 'public']]. "We add the cache control headers for the non-cachable items" hasExpire ifFalse: [swazooResponse addHeaderName: 'cachecontrol' value: 'private'; addHeaderName: 'cachecontrol' value: 'no-cache'; addHeaderName: 'expires' value: '-1'; addHeaderName: 'pragma' value: 'no-cache'; addHeaderName: 'expiresabsolute' value: swazooResponse class dateString]. swazooResponse addHeaderName: 'mime-version' value: '1.0'. waResponse cookies do: [:eachCookie | | cookie | cookie := Swazoo.HTTPCookie named: eachCookie key value: eachCookie value. "The cookie object expects local time" [cookie expires: eachCookie expiry asLocal] on: Error do: [:ex | ]. cookie path: eachCookie path. "Swazoo has no support for outbound cookies, I plug it into the header myself" cookie path: eachCookie path. swazooResponse addHeaderName: 'Set-Cookie' value: cookie valueString]. "Seaside does not always supplies the charset=" self adjustContentType: waResponse. swazooResponse contentType: waResponse contentType. swazooResponse entity: waResponse contents contents. ^ swazooResponse
internalServerMalfunction: anException | swazooResponse | swazooResponse := Swazoo.HTTPResponse new code: 500. swazooResponse entity: '<html><head><title>Internal server malfunction</title></head>', '<body><h1>Internal server malfunction</h1><h2 style="color: blue">' , anException errorString , '</h2><div style="font-family: sans-serif">You should contact the system administrator</div></body></html>'. ^ swazooResponse
log: aString Transcript cr; show: aString; flush.
unwrapCookies: aSwazooRequest | cookies | "Seaside expects a dictionary where values are strings Swazoo provides the complete HTTP cookie string We need to parse the HTTP cookie string to extract cookie names and values" cookies := Dictionary new. aSwazooRequest cookie notNil ifTrue: [(aSwazooRequest cookie findTokens: ';') do: [:each | | cookie | cookie := each findTokens: '='. cookies at: cookie first trimBlanks put: cookie last] ]. ^ cookies
unwrapFields: aSwazooRequest "Seaside expects a dictionary where values are either strings or WAFile objects for uploaded MIME entities Swazoo supplies exactly that for HTTP get requests, we answer of copy of it. For post requests we navigate the data structure and add to the dictionary for Seaside" | waFields | waFields := aSwazooRequest uri queryData copy. aSwazooRequest isPost ifTrue: [waFields := Dictionary new. aSwazooRequest postData keysAndValuesDo: [:key :field | | value | field filename isNil ifTrue: [value := field value] ifFalse: [value := self waFileClass new. value fileName: field filename. value contentType: field contentType. value contents: field value first]. (waFields includesKey: key) ifTrue: [(waFields at: key) addAll: value] ifFalse: [waFields at: key put: value]]]. ^waFields
unwrapHeaders: aSwazooRequest "Seaside needs lower case for AUTHORIZATION (would be good if Seaside was not case sensitive Swazoo supplies all upper case, WebToolkit supplies all lower case We adopt the WebToolkit approach" | waHeaders | waHeaders := Dictionary new. aSwazooRequest headers keysAndValuesDo: [:k :field | waHeaders at: k asLowercase put: field value]. ^ waHeaders.
waFileClass ^#'Seaside.WAFile' asQualifiedReference value
</methods> <methods> Swazoo.SeasideResource <category>private-dispatchers</category>
defaultDispatcher ^self waDispatcherClass default
dispatcherForRequest: aSwazooRequest | basePath dispatcher reason | self initializeDefaultDispatcherFrom: aSwazooRequest. basePath := self urlPrefixFromRequest: aSwazooRequest. dispatcher := self dispatchers at: basePath ifAbsent: [nil]. dispatcher isNil ifTrue: [reason := 'New'] ifFalse: [dispatcher := self verifiedDispatcher: dispatcher. dispatcher isNil ifTrue: [reason := 'Updated']]. dispatcher isNil ifTrue: [dispatcher := self defaultDispatcher copy. self installDispatcher: dispatcher atBasePath: basePath. self log: reason , ' Seaside dispatcher activated for path ' , dispatcher basePath , '/']. ^dispatcher
initializeDefaultDispatcherFrom: aWaveRequest "The first servlet instantiated comes here, initializes the default dispatcher" | defaultDispatcher basePath | DefaultDispatcherInitialized == true ifFalse: [defaultDispatcher := self defaultDispatcher. basePath := self urlPrefixFromRequest: aWaveRequest. self installDispatcher: defaultDispatcher atBasePath: basePath. self log: 'Seaside default dispatcher activated for path ' , defaultDispatcher basePath , '/']. DefaultDispatcherInitialized := true
installDispatcher: aDispatcher atBasePath: basePath aDispatcher setName: basePath allButFirst. self dispatchers at: basePath put: aDispatcher. aDispatcher == self defaultDispatcher ifTrue: [^self]. " We remember what the version of the default dispatcher was at the point in time when a dynamic dispatcher is installed. The dynamic dispatcher is allowed to be modified from then on, i.e. its version may change. However as soon as the version of the default dispatcher changes, the dynamic dispatcher becomes invalid, will be thrown away and refreshed with a new copy " self dispatcherVersions at: aDispatcher put: aDispatcher version.
optionKeepDispatchersSimilar " Dispatchers are initialized with a copy of the default dispatcher WADispatcher default. As the default dispatcher changes, it may be necessary to keep all dispatchers consistent with the default dispatcher. Answer true if all dispatchers should be kept consistent with the default dispatcher. Answer false if all dispatchers should be allowed to have their own life. " ^true
verifiedDispatcher: aDispatcher " In a pure development system, the default dispatcher is frequently modified with new applications. Therefore we need to check the dynamic dispatchers so that they remain up-to-date. When a dynamic dispatcher is out of date, answer nil. This behavior can be disabled (#optionKeepDispatchersSimilar) " self optionKeepDispatchersSimilar ifFalse: [^aDispatcher]. aDispatcher isNil ifTrue: [^nil]. (self versionOf: aDispatcher) = self defaultDispatcher version ifTrue: [^aDispatcher]. self dispatcherVersions removeKey: aDispatcher. ^nil
versionOf: aDispatcher " Answer with the version of the default dispatcher as it was when the dynamic dispatcher was installed. The dynamic dispatcher itself may have a different version it has been modified. However if the default dispatcher has been changed, the dynamic dispatcher becomes invalid " aDispatcher == self defaultDispatcher ifTrue: [^aDispatcher version]. ^self dispatcherVersions at: aDispatcher
</methods> <methods> Swazoo.SeasideResource <category>private-dispatching</category>
handlerForRequest: waRequest | swazooRequest | swazooRequest := waRequest nativeRequest. ^ (self dispatcherForRequest: swazooRequest) handlerForRequest: waRequest.
urlPrefixFromRequest: aRequest | path root prefix | path := aRequest tailPath. root := aRequest uri identifier. prefix := path isEmpty ifTrue: [root] ifFalse: ["Get rid of all leading '/'" [path first isEmpty] whileTrue: [path removeFirst]. root readStream upToAll: path first]. "Get rid of all trailing '/'" [prefix notEmpty and: [prefix last = $/]] whileTrue: [prefix := prefix allButLast]. ^prefix
waDispatcherClass ^#'Seaside.WADispatcher' asQualifiedReference value
waRequestClass ^#'Seaside.WARequest' asQualifiedReference value
</methods> <methods> Swazoo.SeasideResource <category>accessing</category>
dispatchers ^self class dispatchers
dispatcherVersions ^self class dispatcherVersions
</methods> <methods> Swazoo.SeasideResource <category>request handling</category>
answerTo: aRequest | waRequest waResponse handler swazooResponse | [waRequest := self convertRequest: aRequest] on: Error do: [:e | ^self internalServerMalfunction: e]. "Establish relationships between objects Seaside Request -> Swazoo Request" waRequest nativeRequest: aRequest. handler := self handlerForRequest: waRequest. waResponse := handler handleRequest: waRequest. "This happens sometimes, no response object" waResponse isNil ifTrue: [waResponse := Seaside.WAResponse internalError: 'Response is missing']. swazooResponse := self convertResponse: waResponse. ^ swazooResponse.
</methods> <methods> Swazoo.SeasideResource class <category>accessing</category>
dispatchers Dispatchers isNil ifTrue: [ self dispatchers: Dictionary new]. ^Dispatchers
dispatchers: aCollection self == SeasideResource ifFalse: [^SeasideResource dispatchers: aCollection]. aCollection isNil ifFalse: ["This resource will need some clean-up when Swazoo is started/restarted" ObjectMemory addDependent: self. "Do something" ] ifTrue: ["Clean-up no longer needed" DispatcherVersions := nil. ObjectMemory removeDependent: self. "Do something"]. Dispatchers := aCollection.
dispatcherVersions ^DispatcherVersions ifNil: [ DispatcherVersions := Dictionary new].
</methods> <methods> Swazoo.SeasideResource class <category>admin</category>
reset DefaultDispatcherInitialized := false. Dispatchers := nil. DispatcherVersions := nil.
</methods> <methods> Seaside.GIFImage <category>accessing</category>
bitsPerPixel " Answer the bitsPerPixel of the receiver. " bitsPerPixel isNil ifTrue: [self refreshProperties]. ^bitsPerPixel
height " Answer the height of the receiver. " height isNil ifTrue: [self refreshProperties]. ^height
width " Answer the width of the receiver. " width isNil ifTrue: [self refreshProperties]. ^width
</methods> <methods> Seaside.GIFImage <category>seaside</category>
asMIMEDocument ^ Seaside.MIMEDocument contentType: self mediaType content: gifBytes.
asMIMEDocumentType: mimeTypeString ^ self asMIMEDocument
</methods> <methods> Seaside.GIFImage <category>converting</category>
asGIF ^self
asImage "Answer an Image that is like the receiver." | decoder | cachedVisual isNil ifTrue: [ decoder := (GIFImage preferredDecoderClass) on: (ReadStream on: gifBytes). cachedVisual := decoder nextImage ]. ^cachedVisual
asInternetMedia ^self
asRetainedMedium "Answer a retained medium (pixmap or mask) with my contents." ^self asImage asRetainedMedium
coercibleMediaType ^self mediaType
</methods> <methods> Seaside.GIFImage <category>internet media support</category>
mediaType ^'image/gif'
sendEntityOver: aStream aStream binary. aStream nextPutAll: gifBytes
sendHeadersOver: aStream "Only absolutely necessary header is Content-type" aStream nextPutAll: 'Content-Type: image/gif'; crlf. aStream nextPutAll: 'Content-Length: '; nextPutAll: gifBytes size printString; crlf.
sendOver: aStream self sendHeadersOver: aStream. aStream crlf. self sendEntityOver: aStream.
</methods> <methods> Seaside.GIFImage <category>private</category>
clearProperties height := width := palette := bitsPerPixel := nil.
gifBytes ^gifBytes
gifBytes: bytes gifBytes := bytes. self clearProperties.
refreshProperties | decoder | decoder := (GIFImage preferredDecoderClass) on: (ReadStream on: gifBytes). decoder readHeader. height := decoder height. width := decoder width. palette := decoder colorPalette. bitsPerPixel := decoder bitsPerPixel.
</methods> <methods> Seaside.GIFImage <category>displaying</category>
displayOn: aGraphicsContext "Display the receiver on aGraphicsContext." ^self asImage displayOn: aGraphicsContext
displayOn: aGraphicsContext at: aPoint "Display the receiver on aGraphicsContext." ^self asImage displayOn: aGraphicsContext at: aPoint
</methods> <methods> Seaside.GIFImage class <category>accessing</category>
preferredDecoderClass ^PreferredDecoderClass
preferredDecoderClass: aClass PreferredDecoderClass := aClass
preferredEncoderClass | theClass inlinedVisualClass | inlinedVisualClass := #{Swazoo.WebInlinedVisual} bindingOrNil. theClass := inlinedVisualClass ifNotNil: [:cls | cls imageEncodingMechanism]. ^(theClass = GIFEncoder or: [theClass = GUFEncoder]) ifTrue: [theClass] ifFalse: [GIFEncoder].
preferredEncoderClassName ^PreferredEncoderClass name
preferredEncoderClassName: aSymbol | newClass | newClass := aSymbol asQualifiedReference valueOrDo: [PreferredEncoderClass]. self preferredEncoderClass: newClass.
</methods> <methods> Seaside.GIFImage class <category>utility</category>
singlePixelOfColor: aColorValue | bytes | bytes := self singlePixelTemplate. bytes at: 17 put: (aColorValue red * 255) asInteger. bytes at: 18 put: (aColorValue green * 255) asInteger. bytes at: 19 put: (aColorValue blue * 255) asInteger. ^self from: bytes.
singlePixelTemplate ^OnePixelTemplate copy
singlePixelTransparent ^TransparentOnePixelGIF
</methods> <methods> Seaside.GIFImage class <category>instance creation</category>
from: bytes ^self new gifBytes: bytes.
fromSmalltalkBitmap: image ^image asGIF
</methods> <methods> Seaside.GIFImage class <category>class initialization</category>
initialize "GIFImage initialize" GUFEncoder initialize. GIFEncoder initialize. PreferredEncoderClass := GIFEncoder. PreferredDecoderClass := GIFEncoder. TransparentOnePixelGIF := (self from: #[71 73 70 56 57 97 1 0 1 0 128 0 0 255 255 255 0 0 0 33 249 4 1 0 0 0 0 44 0 0 0 0 1 0 1 0 0 2 2 68 1 0 59]) refreshProperties. OnePixelTemplate := #[71 73 70 56 55 97 1 0 1 0 145 0 0 255 255 255 36 201 38 0 0 0 0 0 0 44 0 0 0 0 1 0 1 0 1 2 2 76 1 0 59].
uninitialize "GIFImage uninitialize" PreferredEncoderClass := GUFEncoder. PreferredDecoderClass := GIFEncoder. TransparentOnePixelGIF := nil. OnePixelTemplate := nil
</methods> <methods> Seaside.BitmapImageEncoder <category>private</category>
changePadOfBits: bits width: width height: height depth: depth from: oldPad to: newPad "Change padding size of bits." | srcRowByteSize dstRowByteSize newBits srcRowBase rowEndOffset | (#(8 16 32) includes: oldPad) ifFalse: [^self error: ((#InvalidPad1s << #WaveServerDialogs >> 'Invalid pad: <1s>') expandMacrosWith: oldPad printString)]. (#(8 16 32) includes: newPad) ifFalse: [^self error: ((#InvalidPad1s << #WaveServerDialogs >> 'Invalid pad: <1s>') expandMacrosWith: newPad printString)]. srcRowByteSize := width * depth + oldPad - 1 // oldPad * (oldPad / 8). srcRowByteSize * height = bits size ifFalse: [^self error: (#IncorrectBitmapArraySize << #WaveServerDialogs >> 'Incorrect bitmap array size.')]. dstRowByteSize := width * depth + newPad - 1 // newPad * (newPad / 8). newBits := ByteArray new: dstRowByteSize * height. srcRowBase := 1. rowEndOffset := dstRowByteSize - 1. 1 to: newBits size by: dstRowByteSize do: [:dstRowBase | newBits replaceFrom: dstRowBase to: dstRowBase + rowEndOffset with: bits startingAt: srcRowBase. srcRowBase := srcRowBase + srcRowByteSize]. ^newBits
colorValueFrom: rgbInteger "Answer a colorValue from a 3 byte integer that represents RGB." | scalingValue | scalingValue := ColorValue scalingValue. ^ColorValue scaledRed: (self scalingValue: ((rgbInteger bitShift: -16) bitAnd: 255) from: 255 to: scalingValue) scaledGreen: (self scalingValue: ((rgbInteger bitShift: -8) bitAnd: 255) from: 255 to: scalingValue) scaledBlue: (self scalingValue: (rgbInteger bitAnd: 255) from: 255 to: scalingValue)
hasMagicNumber: aByteArray | position | position := stream position. ((stream size - position) >= aByteArray size and: [(stream next: aByteArray size) = aByteArray]) ifTrue: [^true]. stream position: position. ^false
imageNotStoredError ^self class imageNotStoredSignal raise
magicNumberError ^self class magicNumberErrorSignal raise
packBits: bits "Macintosh PackBits scheme' Best to encode a 3 byte repeat run as a replicate run. See unPackBits: method." | packStream prev writeBlock bitSize bitPos start code replicateSize literalSize | packStream := WriteStream on: (ByteArray new: bits size). prev := nil. writeBlock := [:asc | asc key < 0 ifTrue: "replicate" [packStream nextPut: asc key negated. packStream nextPut: asc value] ifFalse: "literal" [| litStart litStop | litStart := asc value first. litStop := asc value last. asc key = (litStop - litStart) ifFalse: [self error: (#cantHappen << #WaveServerDialogs >> 'can''t happen')]. [litStop - litStart + 1 > 128] whileTrue: [packStream nextPut: 127. litStart to: litStart + 127 do: [:litIndex | packStream nextPut: (bits at: litIndex)]. litStart := litStart + 128]. litStart <= litStop ifTrue: [packStream nextPut: litStop - litStart + 1 - 1. litStart to: litStop do: [:litIndex | packStream nextPut: (bits at: litIndex)]]]]. bitSize := bits size. bitPos := 1. [bitPos <= bitSize] whileTrue: [start := bitPos. code := bits at: start. [(bitPos := bitPos + 1) <= bitSize and: [(bits at: bitPos) = code]] whileTrue: []. replicateSize := bitPos - start. replicateSize > 128 ifTrue: [prev == nil ifFalse: [writeBlock value: prev. prev := nil]. [replicateSize > 128] whileTrue: [writeBlock value: -129 -> code. start := start + 128. replicateSize := replicateSize - 128]]. replicateSize = 2 "treat as literal" ifTrue: [literalSize := 2. prev ~~ nil ifTrue: [prev key >= 0 "prev is literal" ifTrue: [literalSize := literalSize + prev value size. start := prev value first] ifFalse: [writeBlock value: prev. prev := nil]]. prev := (literalSize - 1) -> (start to: start + literalSize - 1)] ifFalse: [replicateSize > 2 ifTrue: [prev == nil ifFalse: [writeBlock value: prev. prev := nil]. prev := (256 - (replicateSize - 1)) negated -> code] ifFalse: "replicateSize < 2" [bitPos := bitPos - 1]]. (start := bitPos) <= bitSize ifTrue: [code := bits at: start. [(bitPos := bitPos + 1) <= bitSize and: [(bits at: bitPos) ~= code]] whileTrue: [code := bits at: bitPos]. bitPos <= bitSize ifTrue: [bitPos := bitPos - 1]. literalSize := bitPos - start. literalSize > 0 ifTrue: [prev ~~ nil ifTrue: [prev key >= 0 "prev is literal" ifTrue: [literalSize := literalSize + prev value size. start := prev value first] ifFalse: [writeBlock value: prev. prev := nil]]. prev := (literalSize - 1) -> (start to: start + literalSize - 1)]]]. prev == nil ifFalse: [writeBlock value: prev. prev := nil]. ^packStream contents
packBits: bits depthFrom8To: depth with: width height: height pad: pad "Pack bits of depth 8 image to it of depth 1, 2, or 4 image." | maxPixelVal pixelInByte bitsWidth pBitsWidth pBits | (#(1 2 4) includes: depth) ifFalse: [^self error: (#depthMustBe12Or4 << #WaveServerDialogs >> 'depth must be 1, 2, or 4')]. (#(8 16 32) includes: pad) ifFalse: [^self error: (#padMustBe816Or32 << #WaveServerDialogs >> 'pad must be 8, 16, or 32')]. maxPixelVal := (1 bitShift: depth) - 1. pixelInByte := 8 / depth. bitsWidth := width * 8 + pad - 1 // pad * (pad / 8). pBitsWidth := width * depth + pad - 1 // pad * (pad / 8). pBits := ByteArray new: pBitsWidth * height. 1 to: height do: [:i | | bitIndex pBitIndex pixelVal count | bitIndex := i - 1 * bitsWidth. pBitIndex := i - 1 * pBitsWidth. pixelVal := 0. count := 0. 1 to: width do: [:j | | val | val := bits at: (bitIndex := bitIndex + 1). val > maxPixelVal ifTrue: [^self error: (#cantPackBits << #WaveServerDialogs >> 'can''t pack bits')]. pixelVal := (pixelVal bitShift: depth) + val. (count := count + 1) >= pixelInByte ifTrue: [pBits at: (pBitIndex := pBitIndex + 1) put: pixelVal. pixelVal := 0. count := 0]]. count > 0 ifTrue: [pBits at: (pBitIndex := pBitIndex + 1) put: (pixelVal bitShift: depth * (pixelInByte - count))]]. ^pBits
rgbIntegerArrayFor: aPalette | colors | colors := Array new: aPalette maxIndex + 1. 1 to: colors size do: [:i | colors at: i put: (self rgbIntegerFrom: (aPalette at: i - 1 ifAbsent: [ColorValue white]))]. ^colors
rgbIntegerFrom: aColorValue "Answer a 3 byte integer that represents RGB from a colorValue." | scalingValue | scalingValue := ColorValue scalingValue. ^((self scalingValue: aColorValue scaledRed from: scalingValue to: 255) bitShift: 16) + ((self scalingValue: aColorValue scaledGreen from: scalingValue to: 255) bitShift: 8) + (self scalingValue: aColorValue scaledBlue from: scalingValue to: 255)
runLengthCompressBits: bits "'Run-length compression scheme' Run-length compression algorithm is: Loop until you get the number of unpacked bytes you are expecting: Read the next source byte into n. If n is not 128, copy n as 1 byte. Else if n is 128: Read the next source byte into n. If n is 0, copy 128 as 1 byte. Else if n is not 0, copy the next byte n+1 times. Endloop" | bitsStream compressStream count code prevCode | bitsStream := ReadStream on: bits. compressStream := WriteStream on: (ByteArray new: bits size). count := 0. prevCode := nil. [bitsStream atEnd] whileFalse: [code := bitsStream next. (count > 0 and: [prevCode ~= code]) ifTrue: [(count = 1 and: [prevCode = 128]) ifTrue: [compressStream nextPut: 128; nextPut: 0] ifFalse: [(count > 2 or: [prevCode = 128]) ifTrue: [compressStream nextPut: 128; nextPut: count - 1; nextPut: prevCode] ifFalse: [1 to: count do: [:i | compressStream nextPut: prevCode]]]. count := 0]. prevCode := code. (count := count + 1) == 256 ifTrue: [compressStream nextPut: 128; nextPut: count - 1; nextPut: code. count := 0]]. count > 0 ifTrue: [(count = 1 and: [code = 128]) ifTrue: [compressStream nextPut: 128; nextPut: 0] ifFalse: [(count > 2 or: [code = 128]) ifTrue: [compressStream nextPut: 128; nextPut: count - 1; nextPut: code] ifFalse: [1 to: count do: [:i | compressStream nextPut: code]]]]. ^compressStream contents
runLengthDecompressBits: bits "'Run-length compression scheme' Run-length compression algorithm is: Loop until you get the number of unpacked bytes you are expecting: Read the next source byte into n. If n is not 128, copy n as 1 byte. Else if n is 128: Read the next source byte into n. If n is 0, copy 128 as 1 byte. Else if n is not 0, copy the next byte n+1 times. Endloop" | bitsStream uncompressStream | bitsStream := ReadStream on: bits. uncompressStream := WriteStream on: (ByteArray new: bits size * 3 // 2). [bitsStream atEnd] whileFalse: [| code | (code := bitsStream next) ~= 128 ifTrue: [uncompressStream nextPut: code] ifFalse: [(code := bitsStream next) = 0 ifTrue: [uncompressStream nextPut: 128] ifFalse: [| byte | byte := bitsStream next. 1 to: code + 1 do: [:i | uncompressStream nextPut: byte]]]]. ^uncompressStream contents
scalingValue: value from: fromScale to: toScale ^value = 0 ifTrue: [0] ifFalse: [value = fromScale ifTrue: [toScale] ifFalse: [(value + 1 * (toScale + 1) / (fromScale + 1)) rounded - 1 max: 0]]
unPackBits: bits "'Macintosh PackBits scheme' Unpack algorithm is: Loop until you get the number of unpacked bytes you are expecting: Read the next source byte into n. If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. Else if n is 128, noop. Endloop" | unpackStream bitSize bitPos code | unpackStream := WriteStream on: (ByteArray new: bits size). bitSize := bits size. bitPos := 0. [(bitPos := bitPos + 1) <= bitSize] whileTrue: [code := bits at: bitPos. code < 128 ifTrue: [1 to: code + 1 do: [:i | unpackStream nextPut: (bits at: (bitPos := bitPos + 1))]] ifFalse: [code > 128 ifTrue: [bitPos := bitPos + 1. 1 to: 256 - code + 1 do: [:i | unpackStream nextPut: (bits at: bitPos)]]]]. ^unpackStream contents
unpackBits: bits depthTo8From: depth with: width height: height pad: pad "Unpack bits of depth 1, 2, or 4 image to it of depth 8 image." | bitMask pixelInByte bitsWidth upBitsWidth stopWidth trailingSize upBits | (#(1 2 4) includes: depth) ifFalse: [^self error: (#depthMustBe12Or4 << #WaveServerDialogs >> 'depth must be 1, 2, or 4')]. (#(8 16 32) includes: pad) ifFalse: [^self error: (#padMustBe816Or32 << #WaveServerDialogs >> 'pad must be 8, 16, or 32')]. bitMask := (1 bitShift: depth) - 1. pixelInByte := 8 / depth. bitsWidth := width * depth + pad - 1 // pad * (pad / 8). upBitsWidth := width * 8 + pad - 1 // pad * (pad / 8). stopWidth := width * depth + 7 // 8. trailingSize := width - (stopWidth - 1 * pixelInByte). upBits := ByteArray new: upBitsWidth * height. 1 to: height do: [:i | | bitIndex upBitIndex val | bitIndex := i - 1 * bitsWidth. upBitIndex := i - 1 * upBitsWidth. 1 to: stopWidth - 1 do: [:j | val := bits at: (bitIndex := bitIndex + 1). upBitIndex := upBitIndex + pixelInByte. 1 to: pixelInByte do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val := val bitShift: depth negated]]. val := (bits at: (bitIndex := bitIndex + 1)) bitShift: depth negated * (pixelInByte - trailingSize). upBitIndex := upBitIndex + trailingSize. 1 to: trailingSize do: [:k | upBits at: (upBitIndex - k + 1) put: (val bitAnd: bitMask). val := val bitShift: depth negated]]. ^upBits
</methods> <methods> Seaside.BitmapImageEncoder <category>stream access</category>
atEnd ^stream atEnd
close stream close
contents ^stream contents
cr ^stream nextPut: Character cr asInteger
lf "PPM and PBM are used LF as CR." ^stream nextPut: Character lf asInteger
next ^stream next
next: size ^stream next: size
nextLong "Read a 32-bit quantity from the input stream." ^(stream next bitShift: 24) + (stream next bitShift: 16) + (stream next bitShift: 8) + stream next
nextLongPut: a32BitW "Write out a 32-bit integer as 32 bits." stream nextPut: ((a32BitW bitShift: -24) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -16) bitAnd: 16rFF). stream nextPut: ((a32BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a32BitW bitAnd: 16rFF). ^a32BitW
nextPut: aByte ^stream nextPut: aByte
nextPutAll: aByteArray ^stream nextPutAll: aByteArray
nextWord "Read a 16-bit quantity from the input stream." ^(stream next bitShift: 8) + stream next
nextWordPut: a16BitW "Write out a 16-bit integer as 16 bits." stream nextPut: ((a16BitW bitShift: -8) bitAnd: 16rFF). stream nextPut: (a16BitW bitAnd: 16rFF). ^a16BitW
position ^stream position
position: anInteger ^stream position: anInteger
size ^stream size
skip: anInteger ^stream skip: anInteger
space ^stream nextPut: Character space asInteger
tab ^stream nextPut: Character tab asInteger
</methods> <methods> Seaside.BitmapImageEncoder <category>accessing</category>
nextImage "Dencoding an image on stream and answer the image." ^self subclassResponsibility
nextPutImage: anImage "Encoding anImage on stream." ^self subclassResponsibility
</methods> <methods> Seaside.BitmapImageEncoder <category>initialize-release</category>
on: aStream stream := aStream. (stream respondsTo: #binary) ifTrue: [stream binary]
</methods> <methods> Seaside.BitmapImageEncoder class <category>class initialization</category>
initialize self initializeSignals
initializeSignals "BitmapImageEncoder initializeSignals" MagicNumberErrorSignal := Object errorSignal newSignal notifierString: (#InvalidMagicNumber << #WaveServerDialogs >> 'Invalid magic number'); nameClass: self message: #magicNumberErrorSignal. ImageNotStoredSignal := Object errorSignal newSignal notifierString: (#ImageNotStored << #WaveServerDialogs >> 'Image not stored'); nameClass: self message: #imageNotStoredSignal.
</methods> <methods> Seaside.BitmapImageEncoder class <category>signal constants</category>
imageNotStoredSignal ^ImageNotStoredSignal
magicNumberErrorSignal ^MagicNumberErrorSignal
</methods> <methods> Seaside.BitmapImageEncoder class <category>instance creation</category>
on: aStream "Answer an instance of the receiver for encoding and/or decoding images on aStream." ^self new on: aStream
</methods> <methods> Swazoo.SeasideSite <category>initialize-release</category>
defaultUriPattern ^'/seaside/go'
initializeResourceFromUriPattern: aString | path tempResource | path := aString findTokens: '/'. path isEmpty ifTrue: [seasideResource := SeasideResource uriPattern: '/'] ifFalse: [seasideResource := SeasideResource uriPattern: path last. path allButLast reverse do: [:each | tempResource := CompositeResource uriPattern: each. tempResource addResource: seasideResource. seasideResource := tempResource]. tempResource := CompositeResource uriPattern: '/'. tempResource addResource: seasideResource. seasideResource := tempResource]
</methods> <methods> Swazoo.SeasideSite <category>accessing</category>
seasideResource seasideResource isNil ifTrue: [self initializeResourceFromUriPattern: self defaultUriPattern]. ^seasideResource
</methods> <methods> Swazoo.SeasideSite <category>responding</category>
helpResolve: aResolution "Suggested by Janko Mivsek" (self canAnswer and: [aResolution siteMatch: self]) ifFalse: [^nil]. ^self seasideResource helpResolve: aResolution
</methods> <methods> Seaside.GUFEncoder <category>accessing</category>
bitsPerPixel ^bitsPerPixel
colorPalette ^colorPalette
height ^height
nextImage | bits depth image | [self readHeader. bits := self readBitData. ] ensure: [self close]. depth := bitsPerPixel > 8 ifTrue: [^self error: (#cantHappen << #WaveServerDialogs >> 'can''t happen')] ifFalse: [bitsPerPixel = 1 ifTrue: [1] ifFalse: [bitsPerPixel = 2 ifTrue: [2] ifFalse: [bitsPerPixel <= 4 ifTrue: [4] ifFalse: [8]]]]. depth < 8 ifTrue: [bits := self packBits: bits depthFrom8To: depth with: width height: height pad: 8]. image := Image extent: width@height depth: depth palette: colorPalette bits: bits pad: 8. transparentPixel notNil ifTrue: [ image := OpaqueImage figure: image shape: (CachedImage on: (image convertToCoverageWithTransparentPixel: transparentPixel) asRetainedMedium)]. ^ image.
nextPutImage: anImage | bits trueBitsPerPixel achievableBitsPerPixel | anImage bitsPerPixel > 8 ifTrue: [^self imageNotStoredError]. width := anImage width. height := anImage height. colorPalette := anImage palette. trueBitsPerPixel := anImage bitsPerPixel. achievableBitsPerPixel := (2 raisedTo: ((((colorPalette size - 1) highBit -1) highBit))). bitsPerPixel := achievableBitsPerPixel. colorPalette := anImage palette. colorPalette paintBasis == CoverageValue ifTrue: [ transparentPixel := 0. colorPalette := colorPalette asMappedPalette. ]. bits := anImage bits. trueBitsPerPixel < 8 ifTrue: [bits := self unpackBits: bits depthTo8From: bitsPerPixel with: anImage width height: anImage height pad: 32]. interlace := true. [self writeHeader. self writeBitData: bits. ] ensure: [self close]. ^anImage "| bits | anImage bitsPerPixel > 8 ifTrue: [^self imageNotStoredError]. width := anImage width. height := anImage height. bitsPerPixel := anImage bitsPerPixel. colorPalette := anImage palette. bits := anImage bits. bitsPerPixel < 8 ifTrue: [bits := self unpackBits: bits depthTo8From: bitsPerPixel with: anImage width height: anImage height pad: 32]. interlace := true. [self writeHeader. self writeBitData: bits. ] valueNowOrOnUnwindDo: [self close]. ^anImage"
width ^width
</methods> <methods> Seaside.GUFEncoder <category>private-encoding</category>
flushCode self flushBits
readPixelFrom: bits | pixel | ypos >= height ifTrue: [^nil]. pixel := bits at: (ypos * rowByteSize + xpos + 1). self updatePixelPosition. ^pixel
writeBitData: bits "avoiding Lempel-Ziv Welch algorithm." | initCodeSize pixel | pass := 0. xpos := 0. ypos := 0. rowByteSize := width * 8 + 31 // 32 * 4. remainBitCount := 0. bufByte := 0. bufStream := WriteStream on: (ByteArray new: 256). initCodeSize := bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. self nextPut: initCodeSize. self setParameters: initCodeSize. self writeCode: clearCode. [(pixel := self readPixelFrom: bits) == nil] whileFalse:[ self writeCode: pixel. freeCode := freeCode + 1. freeCode > maxCode ifTrue: [ self writeCode: clearCode. self setParameters: initCodeSize. ]. ]. self writeCode: eoiCode. self flushCode. self nextPut: 0. "zero-length packet" self nextPut: Terminator
writeCode: aCode self nextBitsPut: aCode
writeCodeAndCheckCodeSize: aCode self writeCode: aCode. self checkCodeSize
writeHeader | byte array | self nextPutAll: 'GIF89a' asByteArray. self writeWord: width. "Screen Width" self writeWord: height. "Screen Height" byte := 16r80. "has color map" byte := byte bitOr: ((bitsPerPixel - 1) bitShift: 5). "color resolution" byte := byte bitOr: bitsPerPixel - 1. "bits per pixel" self nextPut: byte. self nextPut: 0. "background color." self nextPut: 0. "null (future expansion)" array := self rgbIntegerArrayFor: colorPalette. array do: [:rgb | self nextPut: ((rgb bitShift: -16) bitAnd: 255); nextPut: ((rgb bitShift: -8) bitAnd: 255); nextPut: (rgb bitAnd: 255)]. array size + 1 to: (1 bitShift: bitsPerPixel) do: [:i | self nextPut: 0; nextPut: 0; nextPut: 0]. transparentPixel notNil ifTrue: [self writeGraphicControlExtensionBlock]. self nextPut: ImageSeparator. self writeWord: 0. "Image Left" self writeWord: 0. "Image Top" self writeWord: width. "Image Width" self writeWord: height. "Image Height" byte := interlace ifTrue: [16r40] ifFalse: [0]. self nextPut: byte.
writeWord: aWord self nextPut: (aWord bitAnd: 255). self nextPut: ((aWord bitShift: -8) bitAnd: 255). ^aWord
</methods> <methods> Seaside.GUFEncoder <category>private-GIF89a</category>
readExtension | label | label := self next. label == GraphicControlLabel ifTrue: [self readGraphicControlExtensionBlock] ifFalse: [self skipExtensionBlock].
readGraphicControlExtensionBlock | isTransparent | self next. "skip size" isTransparent := ((self next bitAnd: 1) = 1). self next: 2. "skip delay" isTransparent ifTrue: [transparentPixel := self next] ifFalse: [self next]. self next "skip zero terminator"
skipExtensionBlock | sz | sz := self next. self next: sz. self next.
transparentPixel ^transparentPixel
transparentPixel: aPixelValueOrNil "Ideally, the GIF encoder would realize when an OpaqueImage were passed in, set all the pixels covered by the OpaqueImage's shape to a previously unused pixel value (expanding the palette if necessary), and set that pixel value to be transparent, all automatically. In the meantime, we set transparent pixels manually. :-( " transparentPixel := aPixelValueOrNil.
writeGraphicControlExtensionBlock self nextPut: Extension. self nextPut: GraphicControlLabel. self nextPut: 4. transparentPixel notNil ifTrue: [self nextPut: 1] ifFalse: [self nextPut: 0]. self nextPut: 0. "write null delay" self nextPut: 0. transparentPixel notNil ifTrue: [self nextPut: transparentPixel] ifFalse: [self nextPut: 0]. self nextPut: 0. "terminator"
</methods> <methods> Seaside.GUFEncoder <category>private-bits access</category>
flushBits remainBitCount = 0 ifFalse: [self nextBytePut: bufByte. remainBitCount := 0]. self flushBuffer
nextBits | integer readBitCount shiftCount | integer := 0. remainBitCount = 0 ifTrue: [readBitCount := 8. shiftCount := 0] ifFalse: [readBitCount := remainBitCount. shiftCount := remainBitCount - 8]. [readBitCount < codeSize] whileTrue: [self peekByte isNil ifTrue: [^eoiCode]. integer := integer + (self nextByte bitShift: shiftCount). shiftCount := shiftCount + 8. readBitCount := readBitCount + 8]. self peekByte isNil ifTrue: [^eoiCode]. (remainBitCount := readBitCount - codeSize) = 0 ifTrue: [integer := integer + (self nextByte bitShift: shiftCount)] ifFalse: [integer := integer + (self peekByte bitShift: shiftCount)]. ^integer bitAnd: maxCode
nextBitsPut: anInteger | integer writeBitCount shiftCount | shiftCount := 0. remainBitCount = 0 ifTrue: [writeBitCount := 8. integer := anInteger] ifFalse: [writeBitCount := remainBitCount. integer := bufByte + (anInteger bitShift: 8 - remainBitCount)]. [writeBitCount < codeSize] whileTrue: [self nextBytePut: ((integer bitShift: shiftCount) bitAnd: 255). shiftCount := shiftCount - 8. writeBitCount := writeBitCount + 8]. (remainBitCount := writeBitCount - codeSize) = 0 ifTrue: [self nextBytePut: (integer bitShift: shiftCount)] ifFalse: [bufByte := integer bitShift: shiftCount]. ^anInteger
</methods> <methods> Seaside.GUFEncoder <category>private</category>
checkCodeSize (freeCode > maxCode and: [codeSize < 12]) ifTrue: [codeSize := codeSize + 1. maxCode := (1 bitShift: codeSize) - 1]
setParameters: initCodeSize clearCode := 1 bitShift: initCodeSize. eoiCode := clearCode + 1. freeCode := clearCode + 2. codeSize := initCodeSize + 1. maxCode := (1 bitShift: codeSize) - 1
updatePixelPosition (xpos := xpos + 1) >= width ifFalse: [^self]. xpos := 0. interlace ifFalse: [ypos := ypos + 1. ^self]. pass = 0 ifTrue: [(ypos := ypos + 8) >= height ifTrue: [pass := pass + 1. ypos := 4]. ^self]. pass = 1 ifTrue: [(ypos := ypos + 8) >= height ifTrue: [pass := pass + 1. ypos := 2]. ^self]. pass = 2 ifTrue: [(ypos := ypos + 4) >= height ifTrue: [pass := pass + 1. ypos := 1]. ^self]. pass = 3 ifTrue: [ypos := ypos + 2. ^self]. ^self error: (#cantHappen << #WaveServerDialogs >> 'can''t happen')
</methods> <methods> Seaside.GUFEncoder <category>private-packing</category>
fillBuffer | packSize | packSize := self next. bufStream := ReadStream on: (self next: packSize)
flushBuffer bufStream isEmpty ifTrue: [^self]. self nextPut: bufStream size. self nextPutAll: bufStream contents. bufStream := WriteStream on: (ByteArray new: 256)
nextByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream next
nextBytePut: aByte bufStream nextPut: aByte. bufStream size >= 254 ifTrue: [self flushBuffer]
peekByte bufStream atEnd ifTrue: [self atEnd ifTrue: [^nil]. self fillBuffer]. ^bufStream peek
</methods> <methods> Seaside.GUFEncoder <category>private-decoding</category>
readBitData "Not yet supported" self error: (#GUFEncoderCantReadGIFs << #WaveServerDialogs >> 'GUFEncoder can''t read GIFs')
readCode ^self nextBits
readHeader | byte hasColorMap | ((self hasMagicNumber: 'GIF89a' asByteArray) or: [self hasMagicNumber: 'GIF87a' asByteArray]) ifFalse: [^self magicNumberError]. self readWord. "skip Screen Width" self readWord. "skip Screen Height" byte := self next. hasColorMap := (byte bitAnd: 16r80) ~= 0. bitsPerPixel := (byte bitAnd: 7) + 1. byte := self next. "skip background color." byte := self next. "skip gif87 0 or gif89a pixel aspect ratio." hasColorMap ifTrue: [| array | array := Array new: (1 bitShift: bitsPerPixel). 1 to: array size do: [:i | array at: i put: (self colorValueFrom: (self next bitShift: 16) + (self next bitShift: 8) + self next)]. colorPalette := MappedPalette withColors: array] ifFalse: [Transcript cr; show: 'GIF file does not have a colormap.'. colorPalette := MappedPalette monochromeDefault]. [byte := self next. byte == Extension] whileTrue: [self readExtension]. byte = ImageSeparator ifFalse: [^self error: 'corrupt GIF file (nosep)']. self readWord. "skip Image Left" self readWord. "skip Image Top" width := self readWord. height := self readWord. interlace := (self next bitAnd: 16r40) ~= 0. "I ignore the possible existence of a local color map."
readWord ^self next + (self next bitShift: 8)
writePixel: pixel to: bits bits at: (ypos * rowByteSize + xpos + 1) put: pixel. self updatePixelPosition
</methods> <methods> Seaside.GUFEncoder class <category>class initialization</category>
initialize "GUFEncoder initialize." ImageSeparator := $, asInteger. Extension := $! asInteger. Terminator := $; asInteger. GraphicControlLabel := 16rF9.
</methods> <methods> Seaside.GIFEncoder <category>As yet unclassified</category>
writeBitData: bits "using modified Lempel-Ziv Welch algorithm." | maxBits maxMaxCode tSize initCodeSize ent tShift fCode pixel | pass := 0. xpos := 0. ypos := 0. rowByteSize := width * 8 + 31 // 32 * 4. remainBitCount := 0. bufByte := 0. bufStream := WriteStream on: (ByteArray new: 256). maxBits := 12. maxMaxCode := 1 bitShift: maxBits. tSize := 5003. prefixTable := Array new: tSize. suffixTable := Array new: tSize. initCodeSize := bitsPerPixel <= 1 ifTrue: [2] ifFalse: [bitsPerPixel]. self nextPut: initCodeSize. self setParameters: initCodeSize. tShift := 0. fCode := tSize. [fCode < 65536] whileTrue: [tShift := tShift + 1. fCode := fCode * 2]. tShift := 8 - tShift. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self writeCodeAndCheckCodeSize: clearCode. ent := self readPixelFrom: bits. [(pixel := self readPixelFrom: bits) == nil] whileFalse: [| index disp nomatch | fCode := (pixel bitShift: maxBits) + ent. index := ((pixel bitShift: tShift) bitXor: ent) + 1. (suffixTable at: index) = fCode ifTrue: [ent := prefixTable at: index] ifFalse: [nomatch := true. (suffixTable at: index) >= 0 ifTrue: [disp := tSize - index + 1. index = 1 ifTrue: [disp := 1]. "probe" [(index := index - disp) < 1 ifTrue: [index := index + tSize]. (suffixTable at: index) = fCode ifTrue: [ent := prefixTable at: index. nomatch := false. "continue whileFalse:"]. nomatch and: [(suffixTable at: index) > 0]] whileTrue: ["probe"]]. "nomatch" nomatch ifTrue: [self writeCodeAndCheckCodeSize: ent. ent := pixel. freeCode < maxMaxCode ifTrue: [prefixTable at: index put: freeCode. suffixTable at: index put: fCode. freeCode := freeCode + 1] ifFalse: [self writeCodeAndCheckCodeSize: clearCode. 1 to: tSize do: [:i | suffixTable at: i put: -1]. self setParameters: initCodeSize]]]]. prefixTable := suffixTable := nil. self writeCodeAndCheckCodeSize: ent. self writeCodeAndCheckCodeSize: eoiCode. self flushCode. self nextPut: 0. "zero-length packet" self nextPut: Terminator
</methods> <methods> Seaside.GIFEncoder <category>private-decoding</category>
readBitData "using modified Lempel-Ziv Welch algorithm." | bits outCodes outCount bitMask initCodeSize code curCode oldCode inCode finChar | pass := 0. xpos := 0. ypos := 0. rowByteSize := width * 8 + 7 // 8. remainBitCount := 0. bufByte := 0. bufStream := ReadStream on: ByteArray new. bits := ByteArray new: width * height. outCodes := ByteArray new: 1025. outCount := 0. bitMask := (1 bitShift: bitsPerPixel) - 1. prefixTable := Array new: 4096. suffixTable := Array new: 4096. initCodeSize := self next. self setParameters: initCodeSize. [(code := self readCode) = eoiCode] whileFalse: [code = clearCode ifTrue: [self setParameters: initCodeSize. curCode := oldCode := code := self readCode. finChar := curCode bitAnd: bitMask. self writePixel: finChar to: bits] ifFalse: [curCode := inCode := code. curCode >= freeCode ifTrue: [curCode := oldCode. outCodes at: (outCount := outCount + 1) put: finChar]. [curCode > bitMask] whileTrue: [outCount > 1024 ifTrue: [^self error: (#corruptGIFFileOutCount << #WaveServerDialogs >> 'corrupt GIF file (OutCount)')]. outCodes at: (outCount := outCount + 1) put: (suffixTable at: curCode + 1). curCode := prefixTable at: curCode + 1]. finChar := curCode bitAnd: bitMask. outCodes at: (outCount := outCount + 1) put: finChar. outCount to: 1 by: -1 do: [:i | self writePixel: (outCodes at: i) to: bits]. outCount := 0. prefixTable at: freeCode + 1 put: oldCode. suffixTable at: freeCode + 1 put: finChar. oldCode := inCode. freeCode := freeCode + 1. self checkCodeSize]]. prefixTable := suffixTable := nil. ^bits
</methods> <methods> Swazoo.HTTPCookie <category>custom comparing</category>
= anHttpCookie "Return true if this cookie be returned by the browser at the same point tother cookie would" ^self name = anHttpCookie name and: [ self domain = anHttpCookie domain and: [ self path =anHttpCookie path] ]
</methods> <methods> Swazoo.HTTPCookie <category>converting</category>
addHeader: messageHeaders "Convert this cookie into a message header and add it to the header collection messageHeaders." messageHeaders addHeader: 'Set-Cookie' -> self valueString
valueString "Return a string describing the value part of this cookie header" | valueStream | (self name isNil or: [self value isNil]) ifTrue: [^String new]. valueStream := WriteStream on: (String new: 128). valueStream nextPutAll: self name asString; nextPut: $=; nextPutAll: self value. self expires isNil ifFalse: [valueStream nextPutAll: '; '; nextPutAll: 'expires='; nextPutAll: self expiresDateString]. self path isNil ifFalse: [valueStream nextPutAll: '; '; nextPutAll: 'path='; nextPutAll: self path]. self domain isNil ifFalse: [valueStream nextPutAll: '; '; nextPutAll: 'domain='; nextPutAll: self domain]. self comment isNil ifFalse: [ valueStream nextPutAll: '; '; nextPutAll: 'comment='; nextPutAll: self comment]. self secure ifTrue: [valueStream nextPutAll: '; secure']. ^valueStream contents
</methods> <methods> Swazoo.HTTPCookie <category>accessing</category>
comment ^comment.
comment: aString comment := aString.
domain ^domain
domain: aValue domain := aValue
expires ^expires
expires: aTimeStamp "Note: aTimeStamp should be in local time." expires := aTimeStamp
name ^name
name: aValue name := aValue
path ^path
path: aValue path := aValue
secure ^secure
secure: aValue secure := aValue
value ^value
value: aValue value := aValue isString ifTrue: [aValue] ifFalse: [aValue printString]
</methods> <methods> Swazoo.HTTPCookie <category>expiring</category>
expireAfterDays: aNumber "Mark this cookie for expiration after aNumber of days from now." | now | now := Time dateAndTimeNow. self expires: (Timestamp fromDate: ((now at: 1) addDays: aNumber) andTime: (now at: 2))
expireAfterHours: aNumber "Mark this cookie for expiration after aNumber of hours from now." | now increment | now := Time dateAndTimeNow. increment := Time new hours: aNumber minutes: 0 seconds: 0. self expires: (Timestamp fromDate: (now at: 1) andTime: ((now at: 2) addTime: increment))
expireImmediately "Mark this cookie for immediate expiration." | now | now := Time dateAndTimeNow. self expires: (Timestamp fromDate: ((now at: 1) addDays: -1) andTime: (now at: 2))
expireNever "Mark this cookie for expiration as long as cookies will stand from now." self expires: (Timestamp fromDate: (Date newDay: 365 year: 2037) andTime: (Time fromSeconds: 0)).
</methods> <methods> Swazoo.HTTPCookie <category>private</category>
expiresDateString "Return a properly formatted date string using GMT." | GMTSeconds | GMTSeconds := Timestamp fromSeconds: (TimeZone default convertLocalSecondsToGMT: self expires asSeconds). ^HTTPMessage dateString: GMTSeconds
</methods> <methods> Swazoo.HTTPCookie <category>initialize-release</category>
initialize secure := false.
</methods> <methods> Swazoo.HTTPCookie class <category>instance creation</category>
named: nameString value: value "Create and return a new cookie with the given name and value" ^self new name: nameString; value: value.
new ^super new initialize
</methods> <methods> Swazoo.HTTPResponse <category>private-initialize</category>
addDateHeader "This code overrides either version of Swazoo (parcel in goodies or bundle in public store) The date is UTC, formatted according to HTTP rules" self addHeaderName: 'Date' value: self class dateString.
</methods> <methods> Swazoo.HTTPRequest <category>accessing</category>
remoteAddress ^self peer
</methods> <methods> Swazoo.FileResponse <category>private-printing</category>
printEntityOn: aStream | rs | self entity isNil ifFalse: [rs := self entity value readStream. rs lineEndTransparent. rs binary. [[[rs atEnd] whileFalse: [aStream nextPutAll: (rs nextAvailable: 2000)]] ensure: [rs close]] on: OsError do: [:ex | ex return]]
</methods> <methods> Swazoo.HTTPMessage class <category>utility</category>
dateString "This code is borrowed from WebToolkit" "Today's date and time, in HTTP format: DayOfWeek, DD-Mon-YY nn:nn:nn GMT" "((( HTTPMessage dateString )))" ^self dateString: Timestamp nowGMT.
dateString: aTimeStampGMT "This code is borrowed from WebToolkit" "Convert aTimeStampGMT to HTTP format: DayOfWeek, DD-Mon-YY nn:nn:nn GMT" "((( HTTPMessage dateString: (Timestamp nowGMT). )))" "Equivalent to format ddd, dd mmm yyyy hh:mm:ss GMT but hard-code for performance rather than using the policy and parsing tokens" | stream date | stream := WriteStream on: (String new: 20). date := aTimeStampGMT asDate. stream nextPutAll: (#('Mon' 'Tue' 'Wed' 'Thu' 'Fri' 'Sat' 'Sun') at: date weekdayIndex). stream nextPutAll: ', '. aTimeStampGMT day printOn: stream paddedWith: $0 to: 2 base: 10. stream space; nextPutAll: (#('Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov' 'Dec') at: aTimeStampGMT month); space; print: aTimeStampGMT year; space. aTimeStampGMT hour printOn: stream paddedWith: $0 to: 2 base: 10. stream nextPut: $:. aTimeStampGMT minute printOn: stream paddedWith: $0 to: 2 base: 10. stream nextPut: $:. aTimeStampGMT second printOn: stream paddedWith: $0 to: 2 base: 10. stream nextPutAll: ' GMT'. ^stream contents.
</methods> <methods> Swazoo.HTTPMessage <category>testing</category>
isHttp ^ true
</methods> <methods> Core.Timestamp class <category>swazoo</category>
nowGMT ^ self now asGMT
</methods> <methods> Core.Timestamp <category>swazoo</category>
asGMT "Convert the receiver to UTC" ^ self class fromSeconds: (Core.TimeZone default convertLocalSecondsToGMT: self asSeconds).
</methods> <methods> Swazoo.HTTPPostDatum <category>accessing</category>
value: anObject value isNil ifTrue: [value := OrderedCollection new]. value add: anObject
</methods> <methods> Swazoo.HTTPPost <category>private</category>
urlencodedDataFrom: aStream | e tokens | (self includesHeader: 'Content-Length') ifFalse: [^self]. e := aStream nextBytes: self contentLength. tokens := e asString tokensBasedOn: $&. (tokens collect: [:each | each tokensBasedOn: $=]) do: [:keyVal | | datum | datum := self postDataAt: keyVal first ifAbsent: [self postDataAt: keyVal first put: HTTPPostDatum new]. datum := self postDataAt: keyVal first. datum value: (keyVal last collect: [:char | char = $+ ifTrue: [Character space] ifFalse: [char]]) decodedHTTP].
</methods> <methods> Graphics.Image <category>converting</category>
asGIFWithTransparentPaint: aColorValue | encoder image | image := self bitsPerPixel <= 8 ifTrue: [self] ifFalse: [self collapsedTo8BitsOrLess]. encoder := Seaside.GIFImage preferredEncoderClass on: (WriteStream on: (ByteArray new: 1000)). encoder transparentPixel: (image palette indexOfPaintNearest: aColorValue). encoder nextPutImage: image. ^Seaside.GIFImage from: encoder contents
</methods> <methods> Core.Number <category>squeak-converting</category>
asString "Needed for some versions of Swazoo, We prefer the Squeak implementation" ^ super asString
</methods> <methods> Core.WriteStream <category>templating</category>
binary "For compatibility" ^self.
isBinary "For compatibility" ^collection isString not.
text "For compatibility" ^self.
</methods> <methods> Core.PositionableStream <category>squeak-templating</category>
nextPutBytes: bytes self nextPutAll: bytes asByteString.
</methods> <methods> SeasidePlatformSupport class <category>testing</category>
isSwazoo ^ true
</methods> <methods> Core.Stream <category>accessing</category>
nextLine "Needed when WebToolkit is not loaded This implementation is borrowed from NetClientBase" ^self upTo: Character cr
</methods> <methods> Core.Object <category>*seaside2</category>
_isProxy "Needed when WebToolkit is not loaded This implementation is borrowed from Opentalk-Core-Support" ^false
</methods> <initialize> Swazoo.AAADocumentation </initialize> <initialize> Seaside.GIFImage </initialize> <initialize> Seaside.BitmapImageEncoder </initialize> <initialize> Seaside.GUFEncoder </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>HTTPMessage</name> <environment>Swazoo</environment> <super>Core.Object</super> <private>false</private> none parent headers <imports></imports> <category>Swazoo-Messages</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>HTTPResponse</name> <environment>Swazoo</environment> <super>Swazoo.HTTPMessage</super> <private>false</private> none code entity <imports></imports> <category>Swazoo-Messages</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>Resource</name> <environment>Swazoo</environment> <super>Core.Object</super> <private>false</private> none enabled uriPattern parent <imports></imports> <category>Swazoo-Resources</category> <attributes> <package>Swazoo-Core</package> </attributes> </class> <class> <name>Stream</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports> private IOConstants.* </imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class> <class> <name>Site</name> <environment>Swazoo</environment> <super>Swazoo.CompositeResource</super> <private>false</private> none name serving <imports></imports> <category>Swazoo-Resources</category> <attributes> <package>Swazoo-Core</package> </attributes> </class> <class> <name>PixelArray</name> <environment>Graphics</environment> <super>Graphics.VisualComponent</super> <private>false</private> none <imports></imports> <category>Graphics-Images</category> <attributes> <package>Graphics-Images</package> </attributes> </class> <class> <name>Image</name> <environment>Graphics</environment> <super>Graphics.PixelArray</super> <private>false</private> none bits width height depth bitsPerPixel palette maxPixelValue rowByteSize <imports></imports> <category>Graphics-Images</category> <attributes> <package>Graphics-Images</package> </attributes> </class> <class> <name>HTTPRequest</name> <environment>Swazoo</environment> <super>Swazoo.HTTPMessage</super> <private>false</private> none httpVersion peer timestamp ip environmentData uri resolution encrypted authenticated contents <imports></imports> <category>Swazoo-Messages</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>HTTPPost</name> <environment>Swazoo</environment> <super>Swazoo.HTTPRequest</super> <private>false</private> none postData <imports></imports> <category>Swazoo-Messages</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>FileResponse</name> <environment>Swazoo</environment> <super>Swazoo.HTTPResponse</super> <private>false</private> none <imports></imports> <category>Swazoo-Messages</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>PositionableStream</name> <environment>Core</environment> <super>Core.PeekableStream</super> <private>false</private> none collection position readLimit writeLimit policy <imports></imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class> <class> <name>Timestamp</name> <environment>Core</environment> <super>Core.Magnitude</super> <private>false</private> none year month day hour minute second millisecond <imports></imports> <category>UIBasics-Support</category> <attributes> <package>UIBasics-Support</package> </attributes> </class> <class> <name>Number</name> <environment>Core</environment> <super>Core.ArithmeticValue</super> <private>false</private> none <imports></imports> <category>Magnitude-Numbers</category> <attributes> <package>Magnitude-Numbers</package> </attributes> </class> <class> <name>HTTPPostDatum</name> <environment>Swazoo</environment> <super>Swazoo.MimeObject</super> <private>false</private> none filename <imports></imports> <category>Swazoo-Support</category> <attributes> <package>Swazoo-HTTP</package> </attributes> </class> <class> <name>WriteStream</name> <environment>Core</environment> <super>Core.InternalStream</super> <private>false</private> none <imports></imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class>