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

system.verbs.builtins.radio.file.folderToOpml

on folderToOpml (folder, adrcallback=nil, ownername=user.prefs.name, owneremail=user.prefs.mailAddress, adrCloud=nil) {
	<<Changes
		<<5/24/02; 5:02:13 PM by JES
			<<Add an XML comment to the top of the file, saying what application generated the OPML.
		<<1/7/02; 1:32:28 PM by JES
			<<Don't include files/folders whose names begin with ".".
		<<12/31/01; 1:22:00 AM by JES
			<<Added adrCloud parameter.
		<<12/1/01; 4:58:22 PM by JES
			<<When creating file-type <outline>s, if the file has an upstream url, add the url attribute whose value is the file's url.
		<<11/16/01; 5:56:39 PM by JES
			<<When creating file-type <outline>s, use the filename in the upstream URL if available, instead of the name of the file in the filesystem. Prevents upstreamed .html files rendered from .txt files from being deleted on xss servers.
		<<6/23/01; 8:22:40 PM by DW
			<<Created. A fast way of converting a folder to OPML.
			<<Used in creating directory.opml for upstreamed folders.
			<<The callback gets a shot at every file we consider, if it returns false we skip it.
		<<7/21/01; 2:00:41 AM by JES
			<<Fixed a crash when testing to see if a callback script address was passed in.
				<<The crash was caused by dereferencing adrcallback, when testing to see if a callback was passed in, which is wrong.
				<<We should have been testing to see if the callback address was nil, and not if the dereferenced address of the callback was nil.
		<<7/24/01; 1:21:52 AM by JES
			<<Skip invisible files. This skips icon files on MacOS (in particular).
	local (xmltext = "", indentlevel = 0);
	on add (s) {
		xmltext = xmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"};
	add ("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
	add ("<!-- OPML generated by Radio UserLand v" + frontier.version () + " on " + date.netStandardString (clock.now ()) + " -->\r\n");
	if adrCloud == nil {
		add ("<opml version=\"1.0\">"); indentlevel++}
	else {
		add ("<opml version=\"1.1\">"); indentlevel++};
	bundle { //add head
		local (adrfile);
		radio.file.getFileAttributes (folder, @adrfile);
		add ("<head>"); indentlevel++;
		add ("<ownerName>" + ownername + "</ownerName>");
		add ("<ownerEmail>" + owneremail + "</ownerEmail>");
		add ("<dateCreated>" + adrfile^.created + "</dateCreated>");
		add ("<dateModified>" + adrfile^.modified + "</dateModified>");
		if adrCloud != nil {
			with adrCloud^ {
				add ("<cloud domain=\"" + server + "\" port=\"" + port + "\" path=\"" + path + "\" registerProcedure=\"" + registerProcedure + "\" protocol=\"" + protocol + "\"/>")}};
		add ("</head>"); indentlevel--};
	bundle { //add body
		add ("<body>"); indentlevel++;
		local (lowerdirectoryfname = string.lower (radio.data.upstream.directoryFileName));
		on dofolder (folder, fltoplevel=false) { //return true if at least one file was inserted
			local (f, fname, atts, flfolder, adrfile, flinserted);
			fileloop (f in folder) {
				if not file.isVisible (f) { //skip invisible files
					continue};
				if file.fileFromPath (f) beginsWith "." { //skip files that begin with "."
					continue};
				fname = file.filefrompath (f);
				if fltoplevel { //don't include the directory in the directory
					if string.lower (fname) == lowerdirectoryfname {
						continue}};
				local (adrfile);
				radio.file.getFileAttributes (f, @adrfile);
				if adrcallback != nil { //7/21/01 JES: adrcallback, not adrcallback^ -- this was causing a crash
					try {
						if not adrcallback^ (f) {
							continue}}};
				if adrfile^.flFolder {
					fname = string.mid (fname, 1, sizeof (fname) - 1);
					if adrfile^.ctfiles > 0 {
						add ("<outline type=\"folder\" text=\"" + fname + "\">"); indentlevel++;
						dofolder (f);
						add ("</outline>"); indentlevel--}
					else {
						add ("<outline type=\"folder\" text=\"" + fname + "\"/>")}}
				else {
					local (upstreamfname = fname, urlattribute = "");
					if adrfile^.upstream.url != "" {
						upstreamfname = string.nthField (adrfile^.upstream.url, "/", string.countFields (adrfile^.upstream.url, "/"));
						urlattribute = " url=\"" + adrfile^.upstream.url + "\""};
					add ("<outline type=\"file\" text=\"" + upstreamfname + "\" size=\"" + adrfile^.size + "\" whenCreated=\"" + date.netStandardString (adrfile^.created) + "\" whenLastUploaded=\"" + date.netStandardString (adrfile^.upstream.whenLastUploaded) + "\"" + urlattribute + "/>")}}};
		dofolder (folder, true);
		add ("</body>"); indentlevel--};
	add ("</opml>"); indentlevel--;
	return (xmltext)}
<<bundle //test code
	<<on callback (f) //skip folders with their own #upstream.xml files
		<<if file.isfolder (f)
			<<return (not file.exists (f + "#upstream.xml"))
		<<return (true) //include it
	<<local (xmltext = folderToOpml ("Backup:Radio UserLand:www:system:upstream:", @callback))
	<<file.writewholefile (file.getSystemDisk () + "tmp.xml", xmltext)
	<<webbrowser.opendocument (file.getSystemDisk () + "tmp.xml")



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.