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

on ftp (checkboxprompt, introtext) {
		<<2/1/02; 1:03:39 PM by JES
			<<Added checkbox for passive mode. Defaults to checked. Call radio.upstream.folderNeedsUpstream, instead of setting items in the filetables directly, to trigger uploading to the new upstream location.
		<<1/19/02; 8:17:26 PM by JES
			<<When turning on or off the FTP option, clear the cached URLs in the upstream sub-tables in This prevents the navigator links from linking to the old URLs from before you switched the FTP option on or off.
		<<1/7/02; 6:27:45 PM by JES
			<<Made the label for the URL field all caps, instead of Url.
		<<1/6/02; 3:21:53 AM by JES
			<<Make sure that the path ends with a trailing slash character, since it's required for the ftp verbs to work. Make the spaces in the user name and repeat password fields into non-breaking spaces. Only add an extra table row for the errorstring if there was an error.
		<<1/5/02; 9:34:25 PM by PBS
			<<Changed text from Repeat to Repeat Password.
		<<12/14/01; 12:41:56 PM by JES
			<<When switching to xss or ftp, loop over, and change the whenLastUploaded date to date (0), to force the files to upstream to the new location.
		<<11/29/01; 4:43:57 PM by DW
			<<Created. Do the whole form in a script. I spent half a day trying to figure out why things aren't getting passed around correctly. Enough. Customize.
	local (pta = html.getpagetableaddress ());
	<<scratchpad.params = pta^
	local (htmltext = "", indentlevel = 0);
	on add (s) {
		htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"};
	local (adrfile, adrrootspec);
	radio.file.getFileAttributes (, @adrfile);
	radio.upstream.getUpstreamSpec (adrfile, @adrrootspec);
	local (errorstring = "");
	local (enabled = false, username = "", password = "", server = "", path = "", url = "", flpassive = true);
	case pta^.method {
		"GET" { //read the current values
			local (adrfile, adrrootspec);
			radio.file.getFileAttributes (, @adrfile);
			radio.upstream.getUpstreamSpec (adrfile, @adrrootspec);
			case adrrootspec^.type {
				"ftp" {
					enabled = true;
					username = adrrootspec^.username;
					password =[adrrootspec^.passwordName];
					server = adrrootspec^.server;
					path = adrrootspec^.path;
					url = adrrootspec^.url;
					if defined (adrrootspec^.mode) {
						if adrrootspec^.mode != "passive" {
							flpassive = false}}}}};
		"POST" { //if the passwords are okay, write to #upstream.xml
			local (args = pta^.radioresponder.postargs);
			try {
				local (f = nameof (adrrootspec^));
				if defined (args.enabled) { //write out a #upstream.xml for FTP'ing
					enabled = true; username = args.username; password = args.password; server = args.server; path = args.path; url = args.url;
					if not (path endsWith "/") { //add a trailing slash
						path = path + "/"};
					if args.password != args.passwordRepeat {
						scriptError ("the passwords don't match")}; = binary (args.password);
					if defined (args.usePassiveMode) {
						flpassive = true}
					else { //not checked
						flpassive = false};
					radio.upstream.builtinDrivers.ftp.saveUpstreamSpec (f, args.username, "ftp", args.server, args.path, args.url, flpassive)}
				else {
					radio.upstream.builtinDrivers.xmlStorageSystem.saveUpstreamSpec (f,,};
				bundle { //trigger upstream, clear cached upstream URLs
					radio.upstream.folderNeedsUpstream (}}
					<<bundle //old code
						<<local (adrfile)
						<<try //1/19/02 JES: clear the cached upstream url for the upstream folder
							<<[].upstream.url = ""
						<<local (lowerUpstreamFolder = string.lower (
						<<for adrfile in
							<<if defined (adrfile^.baseUpstreamFolder)
								<<if string.lower (adrfile^.baseUpstreamFolder) == lowerUpstreamFolder
									<<adrfile^.upstream.whenLastUploaded = date (0)
									<<adrfile^.url = "" //1/19/02 JES: clear the cached upstream url for the file
			else {
				errorstring = radio.prefs.errorstring ("Can't change the FTP settings because " + tryerror + ".")}}};
	bundle { //add the checkbox
		local (checked = "");
		if enabled {
			checked = " checked"};
		add ("<tr><td colspan=\"2\"><input type=\"checkbox\" name=\"enabled\" id=\"enabled\" value=xxx" + checked + "> <label for=\"enabled\">" + checkboxprompt + "</label></td></tr>")};
	add ("<tr><td colspan=\"2\"><br>" + introtext + "<br><br></td></tr>");
	bundle { //add form fields
		add ("<tr><td align=\"left\">User name:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"text\" name=\"username\" size=\"50\" maxlength=\"100\" value=\"" + username + "\"></td></tr>");
		add ("<tr><td align=\"left\">Password:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"password\" name=\"password\" size=\"50\" maxlength=\"100\" value=\"" + password + "\"></td></tr>");
		add ("<tr><td align=\"left\">Repeat Password:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"password\" name=\"passwordRepeat\" size=\"50\" maxlength=\"100\" value=\"" + password + "\"></td></tr>");
		add ("<tr><td align=\"left\">Server:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"text\" name=\"server\" size=\"50\" maxlength=\"100\" value=\"" + server + "\"></td></tr>");
		add ("<tr><td align=\"left\">Path:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"text\" name=\"path\" size=\"50\" maxlength=\"100\" value=\"" + path + "\"></td></tr>");
		add ("<tr><td align=\"left\">URL:</td><td valign=\"top\" width=\"80%\" colspan=\"1\"><input type=\"text\" name=\"url\" size=\"50\" maxlength=\"100\" value=\"" + url + "\"></td></tr>");
		local (checked = "");
		if flpassive {
			checked = " checked"};
		add ("<tr><td colspan=\"2\"><input type=\"checkbox\" name=\"usePassiveMode\" id=\"usePassiveMode\" value=xxx" + checked + "> <label for=\"usePassiveMode\">Check this box to use passive mode (PASV).</label></td></tr>")};
	if errorstring != "" {
		add ("<tr><td colspan=\"2\"><br>" + errorstring + "</td></tr>")};
	return (htmltext)}
<<bundle //test code
	<<html.setpagetableaddress (@scratchpad.params)
	<<ftp ("xxx", "yyy")

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.