[squeak-dev] The Inbox: WebClient-Core-ct.125.mcz

commits at source.squeak.org commits at source.squeak.org
Tue Sep 8 08:09:05 UTC 2020


Christoph Thiede uploaded a new version of WebClient-Core to project The Inbox:
http://source.squeak.org/inbox/WebClient-Core-ct.125.mcz

==================== Summary ====================

Name: WebClient-Core-ct.125
Author: ct
Time: 8 September 2020, 10:09:01.217336 am
UUID: b5a5321e-904d-ca40-aa6a-8ae3236fe629
Ancestors: WebClient-Core-ct.124

Adds UTF-8 conversion to multipart/form-data encoding & decoding in WebUtils. Also includes overall refactoring of the relevant methods. Last but not least, makes the filename parameter optional as specified in RFC7578 Sec. 4.2.

NOTE that this is a breaking change for any users of the multipart/form-data protocol provided by the WebClient package! If you manually converted (file)names or plain-text fields to UTF-8 via #squeakToUtf8 before passing them to the WebClient, you should stop doing so now. Vice versa, as a user of WebRequest >> #fields or #multipartFields, you should no longer call #utf8ToSqueak on the output.

For more information, please refer to [2]. Thanks to Levente (ul) for the help!

Depends indeed on WebClient-Core-ct.124.

[1] https://tools.ietf.org/html/rfc7578#section-4.2
[2] http://forum.world.st/Are-we-missing-some-string-encoding-in-SqueakSSL-WebClient-td5121341.html

=============== Diff against WebClient-Core-ct.124 ===============

Item was changed:
  ----- Method: WebUtils class>>decodeMultipartForm:boundary:do: (in category 'decoding') -----
  decodeMultipartForm: aStream boundary: boundary do: aBlock
  	"Parse the contents of a multipart/form-data submission.
+ 	
+ 	Evaluate aBlock with three parts: The headers, the (parsed) form-data arguments and the (undecoded) contents of the part. The sender is expected to take care of other issues such as content-transfer-encoding and similar headers."
  
- 	Evaluate aBlock with three parts: The headers, the (parsed) form-data
- 	arguments and the (undecoded) contents of the part. The sender is
- 	expected to take care of other issues such as content-transfer-encoding
- 	and similar headers."
- 
  	| skip headers content disposition index params |
  	aStream upToAll: '--', boundary.
+ 	[aStream atEnd or: [(skip := aStream next: 2) = '--']] whileFalse: [
+ 		self assert: skip = String crlf description: 'Error decoding multipart/form-data fields'.
+ 		
+ 		headers := Dictionary newFrom: (WebUtils readHeadersFrom: aStream).
- 	[aStream atEnd or:[(skip := aStream next: 2) = '--']] whileFalse:[
- 		skip = String crlf ifFalse:[self error: 'Error decoding multipart/form-data fields'].
- 		headers := Dictionary new.
- 		(WebUtils readHeadersFrom: aStream) do:[:hdr| headers add: hdr].
- 		content := aStream upToAll: String crlf, '--', boundary.
  		params := Dictionary new.
+ 		content := aStream upToAll: String crlf, '--', boundary.
+ 		
+ 		disposition := (headers at: 'content-disposition' ifAbsent: ['']) utf8ToSqueak.
+ 		self flag: #todo. "Support content-type and charset as described in RFC7578."
+ 		#(name filename) do: [:arg |
+ 			| len |
- 		disposition := headers at: 'content-disposition' ifAbsent:[''].
- 		#(name filename) do:[:arg| | len val |
  			len := arg size + 2.
+ 			index := disposition findString: arg, '='.
+ 			index > 0 ifTrue: [
+ 				params at: arg put: (disposition
+ 					copyFrom: index + len
+ 					to: (disposition indexOf: $" startingAt: index + len) - 1) utf8ToSqueak]].
+ 		aBlock value: headers value: params value: content].!
- 			index := disposition findString: arg,'='.
- 			index > 0 ifTrue:[
- 				val := disposition copyFrom: index + len to: (disposition indexOf: $" startingAt: index+len) - 1.
- 				params at: arg put: val.
- 			].
- 		].
- 		aBlock value: headers value: params value: content.
- 	].!

Item was changed:
  ----- Method: WebUtils class>>encodeMultipartForm:boundary: (in category 'decoding') -----
  encodeMultipartForm: fieldMap boundary: boundary
+ 	"Encode the fieldMap as multipart/form-data.
+ 	
+ 	The fieldMap may contain MIMEDocument instances to indicate the presence of a file to upload to the server. If the MIMEDocument is present, its content type and file name will be used for the upload.
+ 	
+ 	The fieldMap can be EITHER an array of associations OR a Dictionary of key value pairs (the former is useful for providing multiple fields and/or specifying the order of fields)."
- 	"Encodes the fieldMap as multipart/form-data.
  
+ 	^ String streamContents: [:stream |
+ 		(fieldMap as: OrderedDictionary) keysAndValuesDo: [:fieldName :fieldValue |
+ 			| fieldContent |
- 	The fieldMap may contain MIMEDocument instances to indicate the presence
- 	of a file to upload to the server. If the MIMEDocument is present, its
- 	content type and file name will be used for the upload.
- 
- 	The fieldMap can be EITHER an array of associations OR a Dictionary of 
- 	key value pairs (the former is useful for providing multiple fields and/or 
- 	specifying the order of fields)."
- 
- 	^String streamContents:[:stream|
- 		(fieldMap as: Dictionary) keysAndValuesDo:[:fieldName :fieldValue | | fieldContent |
  			"Write multipart boundary and common headers"
  			stream nextPutAll: '--', boundary; crlf.
+ 			stream nextPutAll: 'Content-Disposition: form-data; name="'
+ 				, fieldName squeakToUtf8
+ 				, '"'.
+ 			self flag: #todo. "Support Content-Type and charset as described in RFC7578."
+ 			
+ 			"Write field content - either a file or a string"
+ 			fieldContent := (fieldValue isKindOf: MIMEDocument)
+ 				ifTrue: [
+ 					fieldValue url ifNotNil: [:url |
+ 						stream nextPutAll: '; filename="', url pathForFile squeakToUtf8, '"'].
+ 					stream crlf.
+ 					stream
+ 						nextPutAll: 'Content-Type: ';
+ 						nextPutAll: fieldValue contentType squeakToUtf8.
+ 					(fieldValue content ifNil: [
+ 						(FileStream readOnlyFileNamed: fieldValue url pathForFile) contentsOfEntireFile]) asString]
+ 				ifFalse: [fieldValue asString squeakToUtf8].
- 			stream nextPutAll: 'Content-Disposition: form-data; name="', fieldName, '"'.
- 			"Figure out if this is a file upload"
- 			(fieldValue isKindOf: MIMEDocument) ifTrue:[
- 				stream nextPutAll: '; filename="', fieldValue url pathForFile, '"'; crlf.
- 				stream nextPutAll: 'Content-Type: ', fieldValue contentType.
- 				fieldContent := (fieldValue content ifNil:[
- 					(FileStream readOnlyFileNamed: fieldValue url pathForFile) contentsOfEntireFile.
- 				]) asString.
- 			] ifFalse: [fieldContent := fieldValue].
  			stream crlf; crlf.
+ 			stream nextPutAll: fieldContent.
+ 			
+ 			stream crlf].
+ 		stream nextPutAll: '--', boundary, '--', String crlf]!
- 			stream nextPutAll: fieldContent asString.
- 			stream crlf.
- 		].
- 		stream nextPutAll: '--', boundary, '--', String crlf.
- 	].
- !



More information about the Squeak-dev mailing list