Monday, November 08, 2010 at 12:04 AM.

system.verbs.builtins.mainResponder.parseMultipart

on parseMultipart (adrparamtable) {
	<<Change Notes
		<<1/17/99; 1:39:20 PM by DW
			<<Thanks to Kurt Egger for prodding me to do this code, and to Jeff Willden for a great example to work with. I rewrote the code to make better use of Frontier, to perform better and have a flatter interface for the application. 
			<<Our goal is to fill the postArgs table with info from the request
		<<12/02/1999; 5:18:51 PM by AR
			<<Disabled debugging code: No longer write to scratchpad.headers.
		<<08/28/01; 12:31:27 AM by JES
			<<Added support for <select multiple> form elements, per feedback from Seth Dillingham.
	local (boundaryString);
	bundle { //get the boundary string that separates each form element
		local (s = adrparamtable^.requestHeaders.["Content-Type"]);
		<<multipart/form-data; boundary=---------------------------7cf1873b3e070a
		boundaryString = string.popLeading (string.nthField (s, '=', 2), '-')};
	
	local (body);
	bundle { //initialize body, pop off leading dashes followed by boundary string
		body = string (adrparamtable^.requestBody);
		body = string.popLeading (body, '-');
		body = string.delete (body, 1, sizeof (boundaryString))};
	
	local (adrtable = @adrparamtable^.postArgs);
	new (tabletype, adrtable); //fill this table with info from the request
	
	loop { //get each form element, delimited by the boundary string
		local (ix = string.patternMatch (boundaryString, body));
		if ix == 0 { //no more encoded elements
			break};
		local (s = string.popTrailing (string.mid (body, 1, ix - 1), '-'));
		bundle { //digest the element
			local (headers, elementBody, contentDisposition, argName);
			if not (s beginswith "\r\n") {
				s = "\r\n" + s};
			elementBody = string.httpResultSplit (s, @headers);
			if elementBody endswith "\r\n" {
				elementBody = string.delete (elementBody, sizeof (elementBody) - 1, 2)};
			headers.data = elementBody;
			contentDisposition = headers.["Content-Disposition"];
			delete (@headers.["Content-Disposition"]);
			<<name="file"; filename="D:\frontierStartupCommands.txt"
			loop {
				s = string.nthField (contentDisposition, ';', 1);
				if s == "" {
					break};
				contentDisposition = string.delete (contentDisposition, 1, sizeof (s) + 1);
				if s contains '=' {
					local (name = string.trimWhitespace (string.urlDecode (string.nthField (s, '=', 1))));
					local (value = string.trimWhitespace (string.urlDecode (string.nthField (s, '=', 2))));
					value = string.mid (value, 2, sizeof (value) - 2); //pop off enclosing double-quotes
					if string.lower (name) == "name" {
						argName = value}
					else {
						<<bundle //08/28/01 JES: original code
							<<headers.[name] = value
						if defined (headers.[name]) { //08/28/01 JES: support <select multiple> form elements
							if typeOf (headers.[name]) != listType {
								headers.[name] = {headers.[name]}};
							headers.[name] = headers.[name] + {value}}
						else {
							headers.[name] = value}}}};
			<<scratchpad.headers = headers
			if sizeof (headers) == 1 {
				if defined (adrtable^.[argName]) { //08/28/01 JES: support <select multiple> form elements
					if typeOf (adrtable^.[argName]) != listType {
						adrtable^.[argName] = {adrtable^.[argName]}};
					adrtable^.[argName] = adrtable^.[argName] + {elementBody}}
				else {
					adrtable^.[argName] = elementBody}}
			else {
				adrtable^.[argName] = headers}};
		body = string.delete (body, 1, ix + sizeof (boundaryString));
		body = string.popLeading (body, '\n')}};
bundle { //test code
	parseMultipart (@scratchpad.offparams)}



This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.