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

on uploadChangedFiles () {
		<<1/3/01; 4:59:41 PM by DW
			<<Rewrite. Out with the tree, keep a flat list of files.
		<<1/20/01; 10:41:40 AM by DW
			<<Add support for magic folders. 
			<<A new table,, contains items whose names are slash-delimited partial paths into the www folder. If a new or changed file appears in one of those folders, it's processed by a script, that's pointed to by the element in the magicFolders table. This way new content can be routed up to servers. This is the way blog images are managed, for example.
		<<2/12/01; 1:31:23 PM by DW
			<<Get max files per message from a pref, also respect a new pref, packetSizeLimit, which isn't a maximum packet size, because some files may be larger than the limit, but once a packet has that many chars, send it and start a new one.
	local (now = ());
	local (adrmagic =;
	local (pc = file.getpathchar ());
	local (addresslist = {});
	local (folder =, f, name, extension, adrfile, flwritedirectory = false);
	local (fdirectory = folder +;
	fileloop (f in folder, infinity) {
		name = file.filefrompath (f);
		extension = string.nthfield (name, ".", string.countfields (name, "."));
		if contains extension {
			if file.size (f) <= {
				adrfile = radio.upstream.getFileTable (f);
				if adrfile^.upstream.flerror or (file.modified (f) > adrfile^.upstream.whenLastUploaded) {
					addresslist = addresslist + {adrfile};
					if f != fdirectory {
						flwritedirectory = true}}}};
		bundle { //if it's in a magic folder, flow it out that way
			if defined (adrmagic^) {
				local (adr, magicfolder);
				for adr in adrmagic {
					magicfolder = + nameof (adr^);
					if string.lower (f) beginswith string.lower (string.replaceall (magicfolder, "/", pc)) { //got a hit!
						while typeof (adr^) == addressType {
							adr = adr^};
						adrfile = radio.upstream.getFileTable (f);
						if adrfile^.upstream.flerror or (file.modified (f) > adrfile^.upstream.whenLastUploaded) {
							adrfile^.upstream.f = nameof (adrfile^); //5/13/01; DW, magic file scripts need this defined
							try {adr^ (@adrfile^.upstream)};
							try {delete (@adrfile^.upstream.f)};
							adrfile^.upstream.whenLastUploaded = ()}}}}}};
	bundle { //if no files were modified, check if any were deleted, if so, write the directory
		if not flwritedirectory {
			flwritedirectory = radio.upstream.checkForDeletions ()}};
	bundle { //do the second pass, upload the files via RPC
		while sizeof (addresslist) > 0 {
			local (adrlist = {}, i, adr, ctchars = 0);
			for i = 1 to {
				adr = addresslist [1];
				ctchars = ctchars + file.size (nameof (adr^));
				if (ctchars >= and (sizeof (adrlist) > 0) {
				adrlist = adrlist + {adr};
				delete (@addresslist [1]);
				if sizeof (addresslist) == 0 {
			local (filelist = {});
			for adr in adrlist {
				filelist = filelist + {nameof (adr^)}};
			local (urllist = radio.upstream.uploadMultipleFiles (filelist));
			local (ixurllist = 1);
			for adr in adrlist {
				url = urllist [ixurllist++];
				adr^.upstream.flerror = url == "";
				adr^.upstream.url = url;
				if defined (adr^.upstream.ctUploads) {
				else {
					adr^.upstream.ctUploads = 1};
				adr^.upstream.whenLastUploaded = now}};
		if flwritedirectory {
			<<Once and for all, we can't save the directory until we've uploaded files.
				<<The URL will not be set if it's a new file.
				<<And even worse, whenLastUploaded will not be correct, or undefined if it's a new file.
				<<Believe me, I tried. ;->
					<<Saturday, September 16, 2000 at 10:28:24 PM by DW
			local (f = radio.upstream.saveDirectoryXml ());
			radio.upstream.uploadOneFile (f)}}};
bundle { //test code
	<<user.scheduler.hourly.doclock ()
	uploadChangedFiles ()}

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.