Monday, November 08, 2010 at 12:00 AM.
river2Suite.cloudPipe.server
on server () {
<<Changes
<<12/28/09; 6:18:21 PM by DW
<<Allow callers to create new accounts if they have a valid Identica username and password. This will enable us to put up a test server so people can test their CloudPipe clients.
<<12/28/09; 3:00:42 PM by DW
<<Add an "ip" element to the system packet, the IP address of the server.
<<12/28/09; 2:58:35 PM by DW
<<If the server is disabled, return an error.
<<12/27/09; 9:16:58 AM by DW
<<On receiving a POST, return immediately. Send the body of a fatPing as CDATA.
<<12/26/09; 5:44:01 PM by DW
<<If method is POST, look for the OPML subscription list in the body.
<<12/26/09; 3:46:39 PM by DW
<<Change the sleep interval from 10 seconds to 3, and check for timeout after checking the feeds. Seems silly to sleep for three seconds and then exit for timeout without checking to see if something is available to return.
<<12/26/09; 1:59:21 PM by DW
<<Drop the "feedUpdated" packet -- it's redundant. Change the name of "item" to "fatPing". Much clearer what's going on.
<<12/15/09; 10:24:52 AM by DW
<<Created.
local (startticks = clock.ticks (), xmltext = "", indentlevel = 0);
local (pta = html.getpagetableaddress (), adrdata = river2Suite.init (), adruser);
on add (s) {
xmltext = xmltext + string.filledstring ("\t", indentlevel) + s + "\r"};
on encode (s) {
if system.environment.isMac {
return (xml.entityEncode (latinToMac.macToLatin (s), true))}
else {
return (xml.entityEncode (s, true))}};
on addErrorPacket (s) {
add ("<error>" + encode (s) + "</error>")};
on addSystemPacket () {
add ("<system>"); indentlevel++;
add ("<serialnum>" + adrdata^.stats.cloudPipeServer.ctUpdateCalls++ + "</serialnum>");
add ("<when>" + date.netstandardstring (clock.now ()) + "</when>");
add ("<secs>" + ((double (clock.ticks ()) - startticks) / 60) + "</secs>");
add ("<ip>" + tcp.dns.getmydottedid () + "</ip>"); //12/28/09 by DW
add ("</system>"); indentlevel--;
add ("</packets>"); indentlevel--};
add ("<?xml version=\"1.0\"?>");
add ("<packets>"); indentlevel++;
if not adrdata^.prefs.cloudPipeServer.enabled { //12/28/09 by DW
addErrorPacket ("Can't respond to request because the CloudPipe server is disabled.");
addSystemPacket ();
return (xmltext)};
bundle { //check username and password
local (flvaliduser = false);
webserver.util.parseAuth (pta); //set pta^.username and pta^.password
adruser = @adrdata^.users.[pta^.username];
if not defined (adruser^) { //12/28/09 by DW, check with Identica
if not identica.authenticate (pta^.username, pta^.password) {
addErrorPacket ("Can't respond to request because the username and password don't authenticate with Identica.");
addSystemPacket ();
return (xmltext)};
new (tabletype, adruser);
river2Suite.initUser (adruser);
adruser^.prefs.password = pta^.password};
if defined (adruser^) {
river2Suite.initUser (adruser);
if adruser^.prefs.password == pta^.password {
flvaliduser = true}};
if not flvaliduser {
addErrorPacket ("Can't serve updates because \"" + pta^.username + "\" is not a valid username or the password is incorrect.");
addSystemPacket ();
return (xmltext)};
adruser^.stats.cloudPipeServer.ctServerCalls++;
adruser^.stats.cloudPipeServer.whenLastServerCall = clock.now ()};
if pta^.method == "POST" { //12/26/09 by DW
<<scratchpad.cloudpipeserverparams = pta^
<<scratchpad.cloudPipeOpmltext = pta^.requestBody
thread.callscript (@river2Suite.cloudPipe.serverReceiveOpml, {adruser, pta^.requestBody});
addSystemPacket ();
return (xmltext)};
local (cttickstimeout = adrdata^.prefs.cloudPipeServer.ctSecsTimeout * 60);
loop {
bundle { //check all the feeds
local (adrfeed, flatleastoneupdate = false);
for adrfeed in @adruser^.feeds {
if adrfeed^.flRealtimeUpdate {
adrfeed^.flRealtimeUpdate = false;
local (urlfeed = nameof (adrfeed^));
<<add ("<feedUpdated>" + encode (urlfeed) + "</feedUpdated>")
bundle { //add the new items, each in its own packet
local (items = adrfeed^.items, i); //work with a local copy
new (tabletype, @adrfeed^.items);
for i = 1 to sizeof (items) {
add ("<fatPing feed=\"" + encode (urlfeed) + "\">"); indentlevel++;
local (s = xml.decompile (@items [i]));
s = string.replace (s, "<?xml version=\"1.0\"?>\r\n", "");
add ("<![CDATA[" + encode (s) + "]]>"); //12/27/09 by DW
add ("</fatPing>"); indentlevel--}};
flatleastoneupdate = true}};
if flatleastoneupdate { //must inform the caller of the updates! realtime! hoo hah!! :-)
addSystemPacket ();
return (xmltext)}};
if (clock.ticks () - startticks) >= cttickstimeout { //timeout
adruser^.stats.cloudPipeServer.ctTimeouts++;
adruser^.stats.cloudPipeServer.whenLastTimeout = clock.now ();
addSystemPacket ();
return (xmltext)};
adrdata^.stats.cloudPipeServer.ctUpdateLoops++;
adruser^.stats.cloudPipeServer.ctServerLoops++;
adruser^.stats.cloudPipeServer.whenLastServerLoop = clock.now ();
thread.sleepFor (3)}};
<<bundle //test code
<<local (ctrandomticks = random (1, 60 * 5))
<<loop
<<if (clock.ticks () - startticks) >= ctrandomticks
<<local (statename = states.nthstate (random (1, 50)))
<<add ("<state>" + encode (statename) + "</state>")
<<addSystemPacket ()
<<adrdata^.stats.cloudPipeServer.ctTotalTicks = adrdata^.stats.cloudPipeServer.ctTotalTicks + (clock.ticks () - startticks)
<<return (xmltext)
<<else
<<adrdata^.stats.cloudPipeServer.ctUpdateLoops++
<<thread.sleepTicks (10)
bundle { //test code
html.setpagetableaddress (@scratchpad.cloudpipeserverparams);
dialog.alert (server ())}
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.