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

system.verbs.builtins.webserver.util.pathToAddressExt

on pathToAddressExt (path, nomad, adrParamTable, flput = false) {
	<<Changes
		<<1/7/06; 10:27:06 PM by DW
			<<If there's a script in the prefs sub-table of the website named objectNotFoundHander, run it, allowing it to redirect to a different location. This is a poor man's version of the handler in mainResponder, needed for newsRiver's website.
		<<1/7/06; 9:40:23 PM by DW
			<<De-Biermanized.
		<<Bierman comments
			<<Sunday, May 24, 1998 at 12:13:45 PM by PBS
				<<Force the docTree-walk loop to execute one time through if the path == "/"
				<<Fixes weird %2Fdefault/ paths.
			<<Script: system.verbs.builtins.webserver.util.pathToAddressExt; Version 3; Date: Thu, 21 May 1998 17:34:23 GMT; ID: RAB
				<<Handle the default path transparency.
			<<Script: system.verbs.builtins.webserver.util.pathToAddressExt; Version 2; Date: Mon, 11 May 1998 21:19:36 GMT; ID: RAB
				<<Added code for handling PUT.  The code is the same as GET if replacing an element, but returns true is all but the final element exists.
				<<This allows the put to add a new item, but NOT a new structure.
			<<Script: system.verbs.builtins.webserver.util.pathToAddressExt; Version 1; Date: Wed, 06 May 1998 20:26:15 GMT; ID: RAB
	local (remainder, firstpart, treeElement = 1, fileElementStart = 0, doctree, origNomad);
	local (default, flFile);
	local (dataTableAdr, responderTableAdr,  prefsTableAdr);
	
	on callObjectNotFoundHandler () { //1/7/06 by DW
		local (n = nomad, newn, adronfh);
		loop {
			newn = parentof (n^);
			if not defined (newn^) {
				return};
			n = newn;
			adronfh = @n^.["#objectNotFoundHandler"];
			if defined (adronfh^) {
				break}};
		html.setpagetableaddress (adrParamTable);
		adronfh^ ()};
	on resolveDefault (addPart) {
		local (k, newDefault);
		flFile = false;
		case typeOf(default^) {
			tableType {
				newDefault = @default^.[addPart];
				if defined (newDefault^) {
					default = newDefault;
					return (true)};
				if addPart == "" {
					for k in prefsTableAdr^.ODBdefault {
						newDefault = @default^.[k];
						if defined (newDefault^) {
							default = newDefault;
							return (true)}}}};
			addressType {
				default = default^;
				if defined (default^) {
					return (resolveDefault (addPart))}};
			filespecType {
				default = default^;
				if file.isFolder (default) {
					default = string.poptrailing(default, file.getpathChar ()) + file.getpathChar () + addPart;
					if file.exists (default) {
						flFile = true;
						return (true)}}}};
		return (false)};
	
	responderTableAdr = adrParamTable^.responderTableAdr; // the responder table
	dataTableAdr = @responderTableAdr^.["data"]; //This table contains the user data for this responder
	prefsTableAdr = @dataTableAdr^.["prefs"]; //This table contains the user prefs for this responder
	
	path = string.popLeading (path, "/");
	remainder = path;
	bundle { //walk the doc tree
		local (flFirstTime = true);
		new (listType, @doctree);
		doctree[treeElement] = nomad;
		loop {
			if remainder == "" and not (flFirstTime) {
				break};
			flFirstTime = false;
			firstpart = string.nthfield (remainder, '/', 1);
			remainder = string.delete (remainder, 1, sizeof (firstpart) + 1);
			if (firstpart contains "\\") or (firstpart contains ":")  or (firstpart contains "#") {
				<<This means they are trying things like foo:::, etc, having a colon or backslash is not leagal syntax and therefore is a Bad Request
				adrParamTable^.code = 400;
				adrParamTable^.responseBody = webserver.util.buildErrorPage ("400 Bad Request", "The object " + adrParamTable^.path + " has improper syntax.");
				return (false)};
			if firstpart == ".." {
				if treeElement <= 1 {
					<<Access above the base is not allowed
					adrParamTable^.code = 403;
					adrParamTable^.responseBody = webserver.util.buildErrorPage ("403 Forbidden", "Access to the object " + adrParamTable^.path + " is forbidden.");
					return (false)};
				--treeElement;
				nomad = doctree[treeElement];
				if treeElement < fileElementStart {
					fileElementStart = 0}} // This means we've dot-dotted our way back into the ODB table
			else { //we are adding an element to the doc tree
				if firstpart beginswith ".." {
					<<This means they are trying things like ..., etc, starting with .. is not leagal syntax and therefore is a Bad Request
					adrParamTable^.code = 400;
					adrParamTable^.responseBody = webserver.util.buildErrorPage ("400 Bad Request", "The object " + adrParamTable^.path + " has improper syntax.");
					return (false)};
				if fileElementStart == 0 { //we are processing in the ODB walk
					origNomad = nomad;;
					nomad = @nomad^.[firstpart];
					if adrParamTable^.responder == "websiteFramework" { //Handle images
						if !defined (nomad^) {
							if string.lower(firstpart) == string.lower (html.getPagePref("imageFolderName", origNomad)) {
								firstpart = "#" + firstpart;
								nomad = @origNomad^.[firstpart]}}};
					if !defined (nomad^) { //first do some magic if the firstpart exists within the default tree
						local (flResolved = false);
						<<the object doesn't exist
						<<Is it within the default path.
						for i in prefsTableAdr^.ODBdefault {
							default = @origNomad^.[i];
							if defined (default^) {
								if resolveDefault (firstpart) {
									nomad = default;
									if flFile {
										fileElementStart = treeElement + 1};
									flResolved = true;
									break}}};
						if not flResolved {
							if flput { //processing for the PUT is a little different then for GET
								if remainder == "" { //Then this is valid and the leaf is a new element
									adrParamTable^.resultPath = nomad;
									adrParamTable^.resultType = addressType; //we already know we are an address type here
									return (true)}};
							adrParamTable^.code = 404;
							adrParamTable^.responseBody = webserver.util.buildErrorPage ("404 Not Found", "The object " + adrParamTable^.path  + " doesn't exist.");
							callObjectNotFoundHandler ();
							return (false)}}
					else {
						if typeOf (nomad^) == addressType {
							nomad = nomad^;
							if !defined (nomad^) { //the object doesn't exist
								adrParamTable^.code = 404;
								adrParamTable^.responseBody = webserver.util.buildErrorPage ("404 Not Found", "The object " + adrParamTable^.path  + " doesn't exist.");
								callObjectNotFoundHandler ();
								return (false)}};
						if typeOf (nomad^) == filespecType {
							nomad = nomad^;
							fileElementStart = treeElement + 1}}}
				else { //we are walking in the file system
					nomad = string.poptrailing(nomad, file.getpathChar ()) + file.getpathChar () + firstpart;
					if !file.exists(nomad) { //no generosity - if any element along the path does not exist, fail immedialtly
						<<the file doesn't exist
						if flput { //processing for the PUT is a little different then for GET
							if remainder == "" { //Then this is valid and the leaf is a new element
								adrParamTable^.resultPath = nomad;
								adrParamTable^.resultType = filespecType; //we already know we are a file type here
								return (true)}};
						adrParamTable^.code = 404;
						adrParamTable^.responseBody = webserver.util.buildErrorPage ("404 Not Found", "The object " + adrParamTable^.path + " does not exist.");
						return (false)}};
				++treeElement;
				doctree[treeElement] = nomad}}};
	
	adrParamTable^.resultPath = nomad;
	adrParamTable^.resultType = addressType; //default
	if fileElementStart > 0 { //nope, we were in the file system
		adrParamTable^.resultType = filespecType};
	return (true)}
<<bundle // testing
	<<local (paramTable)
	<<new (tableType, @paramTable)
	<<paramTable.responder = "default"
	<<paramTable.responderTableAdr = @user.webserver.responders.default
	<<paramTable.path = "/"
	<<dialog.notify(webserver.util.pathToAddressExt (paramTable.path, @user.webserver.responders.default.data.docTree, @paramTable))
	<<paramTable.path = "/images/"
	<<dialog.notify(webserver.util.pathToAddressExt (paramTable.path, @user.webserver.responders.default.data.docTree, @paramTable))
	<<paramTable.path = "/frontier/debug/.../scripts"
	<<dialog.notify(webserver.util.pathToAddressExt (paramTable.path, @user.webserver.responders.default.data.docTree, @paramTable))
	<<paramTable.path = "/bierman/samples/davenet"
	<<dialog.notify(webserver.util.pathToAddressExt (paramTable.path, @user.webserver.responders.default.data.docTree, @paramTable))
	<<paramTable.path = "/bierman/samples/davenet/../../../../"
	<<dialog.notify(webserver.util.pathToAddressExt (paramTable.path, @user.webserver.responders.default.data.docTree, @paramTable))



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.