Tuesday, August 18, 2009 at 7:34 PM.

newsRiverSuite.viewSubscriptions

on viewSubscriptions () {
	<<Changes:
		<<8/17/08; 10:47:13 AM by DW
			<<Converted to use newsRiverSuite.imageRef instead of the one in dotOpml.root.
		<<1/17/06; 7:03:36 PM by DW
			<<More defensive driving around missing channeltitles.
		<<3/20/02; 9:43:09 AM by DW
			<<Don't try to work with channels that don't have channelTitles. In theory this is never supposed to happen. But enough users are getting broken by this, I felt it was time to work around the problem.
		<<3/19/02; 5:27:30 PM by DW
			<<Support for partnerFeed attribute on GET request.
		<<1/24/02; 7:26:51 PM by DW
			<<Minor tweaks and reworks to make the page work better. Moved the Unsubscribe button to the bottom of the page.
		<<1/13/02; 11:18:05 PM by JES
			<<If a searchArg named url is present, use its value for the value of the URL-entry box. This makes it possible to create a link on your website, which allows people to subscribe their copy of Radio to your RSS feed.
		<<1/9/02; 12:52:03 AM by JES
			<<Decode entities in the channel name in the success message, which appears after subscribing to a new channel.
		<<1/9/02; 12:47:39 AM by JES
			<<Moved the Delete button to a similar location to where it is on the News page -- it's no longer on its own, to the right of the subscriptions table. Added <nobr/> tags to the date field in the subscriptions table, so that the dates won't wrap to multiple lines.
		<<1/6/02; 4:25:04 AM by JES
			<<Added table css classes.
		<<1/4/02; 3:32:20 PM by JES
			<<Commented out some debugging code.
		<<12/12/01; 11:16:32 AM by DW
			<<Workaround crashing bug in kernel.
		<<12/10/01; 1:38:16 AM by JES
			<<Decode entities in the channel title -- no more ' in the page.
		<<12/8/01; 12:50:36 PM by DW
			<<Adding a new subscription should provide feedback. "You are now subscribed to the blah blah feed."
			<<Improved the error message when a subscription doesn't work.
		<<11/24/01; 3:55:33 PM by DW
			<<Added help link.
		<<11/14/01; 10:00:27 AM by DW
			<<Localized.
		<<1/23/01; 3:12:53 PM by DW
			<<Created.
		<<2/12/01; 10:00:38 AM by DW
			<<Clean up and debug.
			<<Add headers to columns.
			<<Fixed a major bug in unsubscribing. If you unsubscribed from more than one channel, it would change the indexing and believe it or not it would unsubscribe from the wrong channels. Oy. Now we scan in reverse order and pad the checkbox names with 0's so things get deleted in the correct order.
		<<2/12/01; 4:40:42 PM by PBS
			<<Channels with quotes and angle brackets in the description would message up the rendering. Fixed.
			<<Link title for the XML button, so it's consistent with other pages.
		<<2/24/01; 6:16:29 PM by PBS
			<<Help links.
		<<3/4/01; 5:05:00 PM by JES
			<<Toss the HotList cache when subscribing or unsubscribing to/from a channel.
		<<3/4/01; 6:13:06 PM by JES
			<<Toss the homepage cache when unsubscribing from a channel.
		<<3/5/01; 8:47:23 PM by PBS
			<<Fixed a typo when tossing the hot list cache.
		<<7/26/01; 4:04:24 PM by JES
			<<Don't error if a channel's channeldescription or channellink aren't defined.
	local (pta = html.getpagetableaddress ());
	<<scratchpad.vsparams = pta^
	pta^.title = newsRiverSuite.getString ("subscriptions.title");
	local (adrdata = xml.aggregator.init ());
	local (xmlImg = newsRiverSuite.imageRef ("newsRiver/icons/xml"));
	local (htmltext = "", indentlevel = 0);
	on add (s) {
		htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r\n"};
	local (errorstring = "", initialurl = "http://", adrnewservice = nil, flopmlsub = false, opmltitle = "");
	if pta^.method == "POST" {
		local (args);
		new (tabletype, @args);
		webserver.parseargs (pta^.requestbody, @args);
		if defined (args.subscribe) {
			if sizeof (args.url) > sizeof (initialurl) {
				bundle { //set flopmlsub
					local (xmltext = tcp.httpreadurl (args.url), xstruct);
					xml.compile (xmltext, @xstruct);
					try {
						xml.getaddress (@xstruct, "opml");
						opmltitle = string.nthfield (args.url, "/", string.countfields (args.url, "/"));
						flopmlsub = true}};
				if flopmlsub {
					try {
						local (adrlist = @adrdata^.newsRiver.readingLists.[args.url]);
						if defined (adrlist^) {
							errorstring = "Can't subscribe because you are already subscribed to the list."}
						else {
							new (tabletype, adrlist);
							newsRiverSuite.readingList.beforeScan ();
							adrnewservice = adrlist}}
					else {
						errorstring = tryerror}}
				else {
					if not xml.aggregator.subscribeService (args.url, @errorstring, @adrnewservice) {
						initialurl = args.url}}};
			adrdata^.newsRiver.flSubscriptionListDirty = true};
		if defined (args.unsubscribe) {
			delete (@args.unsubscribe);
			try {delete (@args.url)};
			local (i, adr, ix);
			for i = sizeof (args) downto 1 {
				adr = @args [i];
				ix = number (nameof (adr^));
				if ix > 100000 { //it's a reading list
					local (adrlist = @adrdata^.newsriver.readinglists [ix - 100000]);
					newsRiverSuite.readingList.unsubscribe (nameof (adrlist^))}
				else { //it's a feed
					local (adrservice = @adrdata^.services [ix]);
					xml.aggregator.unsubscribeService (nameof (adrservice^))}};
			adrdata^.newsRiver.flSubscriptionListDirty = true}};
	local (sortedtable);
	bundle { //fill sorted table
		local (adrsort);
		new (tabletype, @sortedtable);
		for adr in @adrdata^.services {
			bundle { //don't show feeds that come from reading lists
				if defined (adr^.flManualSub) {
					if not adr^.flManualSub {
						continue}}};
			if defined (adr^.compilation) {
				if sizeof (adr^.compilation) > 0 {
					try { //missing channeltitle doesn't stop us -- 3/20/02 DW
						local (channeltitle = adr^.compilation.channeltitle);
						if sizeof (channeltitle) > 0 {
							adrsort = @sortedtable.[adr^.compilation.channeltitle];
							if defined (adrsort^) { //collision
								local (ct = 1);
								loop {
									adrsort = @sortedtable.[adr^.compilation.channeltitle + "." + ct++];
									if not defined (adrsort^) {
										break}}};
							adrsort^ = nameof (adr^)}}}}}};
		<<local (oldtarget = target.set (@sortedtable))
		<<table.sortby ("Value")
		<<target.set (oldtarget)
		<<scratchpad.sortedtable = sortedtable; edit (@scratchpad.sortedtable)
	add ("<form method=\"POST\">"); indentlevel++;
	bundle { //add the URL entry box
		<<if pta^.method == "GET" //1/13/02 JES: try to set initialurl
			<<if defined (pta^.radioResponder.getArgs.url)
				<<initialurl = pta^.radioResponder.getArgs.url
			<<if defined (pta^.radioResponder.getArgs.partnerFeed) //something like "nyt.arts"
				<<local (feed = pta^.radioResponder.getArgs.partnerFeed)
				<<local (part1 = string.nthfield (feed, ".", 1))
				<<local (part2 = string.nthfield (feed, ".", 2))
				<<local (adrurl = @radio.data.partnerUrls.[part1].[part2])
				<<if defined (adrurl^)
					<<initialurl = adrurl^
		add ("<p>" + newsRiverSuite.getString ("subscriptions.subscribeIntro") + "</p>");
		add ("<blockquote>"); indentlevel++;
		add ("<table>"); indentlevel++;
		add ("<tr>"); indentlevel++;
		add ("<td align=\"left\">" + "URL" + ":</td>");
		add ("<td valign=\"top\"><input type=\"text\" name=\"url\" size=\"55\" maxlength=\"255\" value=\"" + initialurl + "\"></td>");
		add ("<td><input type=\"submit\" name=\"subscribe\" value=\"" + newsRiverSuite.getString ("subscriptions.addButton") + "\">" + "</td>");
		add ("</tr>"); indentlevel--;
		<<add ("<tr><td colspan=\"3\" align=\"right\">" + radio.userInterface.helpLink ("addChannel") + "</td></tr>")
		add ("</table>"); indentlevel--;
		add ("</blockquote>"); indentlevel--;
		if errorstring != "" {
			add ("<font color=\"red\">" + newsRiverSuite.getString ("subscriptions.cantSubscribeBecause") + "\"" + errorstring + "\"</font><br>")};
		if adrnewservice != nil {
			<<12/12/01; 11:16:51 AM by DW
				<<Site of a crashing bug in Radio 7.1b36. 
				<<Workaround provided by Lawrence Lee. 
				<<(Good work!!)
			local (t);
			new (tabletype, @t);
			if flopmlsub {
				t.channeltitle = opmltitle}
			else { //1/17/06 by DW, do it in a try
				try {
					t.channeltitle = newsRiverSuite.decodeEntities (adrnewservice^.compilation.channeltitle)}
				else {
					t.channeltitle = "Untitled feed"}};
			add (newsRiverSuite.getString ("subscriptions.confirmSubscription", @t))}};
		<<add ("<br>")
	add ("<p>");
	<<bundle //add unsubscribe button
		<<add ("<table align=\"right\" cellspacing=\"0\" cellpadding=\"1\"><tr><td valign=\"top\">  <input type=\"submit\" name=\"unsubscribe\" value=\"" + newsRiverSuite.getString ("subscriptions.unsubscribeButton") + "\"></td></tr></table>")
	bundle { //add the text at the top of the page
		add (newsRiverSuite.getString ("subscriptions.tableIntro"))};
		<<add (newsRiverSuite.getString ("subscriptions.tableIntro") + " " + radio.userInterface.helpLink ("The Subscriptions page"))
	add ("</p>");
	add ("<blockquote>"); indentlevel++;
	add ("<table><tr>"); indentlevel++;
	add ("<td>"); indentlevel++;
	bundle { //add subscription table
		add ("<table class=\"dwsFrameTable\" cellspacing=\"0\" cellpadding=\"0\"><tr bgcolor=\"" + newsRiverData.htmlColors.frameColor + "\"><td>"); indentlevel++;
		add ("<table class=\"dwsTable\" border=\"0\" cellspacing=\"1\" cellpadding=\"5\">"); indentlevel++;
		local (i, adrsort, adr, adrsource, ct = 0);
		<<bundle //add header
			<<add ("<tr bgcolor=\"" + newsRiverData.htmlColors.cellBgColor + "\"><td> </td><td><b>Name</b></td><td align=\"right\"><b>Updated</b></td><td align=\"right\"><b>Ct</b></td><td> </td></tr>")
		on addrow (idForCheckbox, title, channeldescription, channellink, timeLastChange, ctChanges, xmlUrl) {
			local (link);
			add ("<tr bgcolor=\"" + newsRiverData.htmlColors.cellBgColor + "\">"); indentlevel++;
			bundle { //add checkbox
				local (name = nameof (adr^));
				local (checkboxval = "xxx ");
				if false {
					checkboxval = checkboxval + "checked"};
				add ("<td class=\"dwsTableCell\" valign=\"top\"><input type=\"checkbox\" name=\"" + string.padwithzeros (idForCheckbox, 8) + "\" value=" + checkboxval + "></td>")};
			if sizeof (title) > 50 {
				title = string.mid (title, 1, 50) + ".."};
			bundle { //set link
				if sizeof (channellink) > 0 {
					link = "<a href=\"" + channellink + "\">" + newsRiverSuite.decodeEntities (title) + "</a>"}
				else {
					link = newsRiverSuite.decodeEntities (title)}};
			add ("<td class=\"dwsTableCell\" valign=\"top\" title=\"" + newsRiverSuite.translateToEntities (channeldescription) + "\" nowrap>" + link + "</td>");
			add ("<td class=\"dwsTableCell\" align=\"right\" valign=\"top\"><nobr><font size=\"-1\">" + newsRiverSuite.getDateString (timeLastChange, false) + "</font></nobr></td>");
			add ("<td class=\"dwsTableCell\" align=\"right\" valign=\"top\"><font size=\"-1\">" + ctChanges + "</font></td>");
			add ("<td class=\"dwsTableCell\" valign=\"top\"><a href=\"" + xmlUrl + "\" title=\"" + newsRiverData.english.strings.misc.xmlToolTip + "\">" + xmlimg + "</a></td>");
			add ("</tr>"); indentlevel--};
		bundle { //add reading list subscriptions
			if sizeof (adrdata^.newsriver.readinglists) > 0 {
				local (adrlist);
				add ("<tr bgcolor=\"" + newsRiverData.htmlColors.cellBgColor + "\"><td colspan=\"5\"><center><b>R E A D I N G   L I S T S</b></center></td></tr>");
				for adrlist in @adrdata^.newsriver.readinglists {
					addrow (indexOf (adrlist^) + 100000, adrlist^.title, "", "", adrlist^.stats.timeLastChange, adrlist^.stats.ctChanges, nameof (adrlist^))};
				add ("<tr bgcolor=\"" + newsRiverData.htmlColors.cellBgColor + "\"><td colspan=\"5\"><center><b>F E E D S</b></center></td></tr>")}};
		for adrsort in @sortedtable {
			adr = @adrdata^.services.[adrsort^];
			if defined (adr^.compilation) {
				if sizeof (adr^.compilation) > 0 {
					local (title = "Untitled feed");
					if defined (adr^.compilation.channeltitle) {
						title = adr^.compilation.channeltitle};
					local (channeldescription = "", channellink = "");
					if defined (adr^.compilation.channeldescription) {
						channeldescription = newsRiverSuite.decodeEntities (adr^.compilation.channeldescription)};
					if defined (adr^.compilation.channellink) {
						channellink = adr^.compilation.channellink};
					addrow (indexOf (adr^), title, channeldescription, channellink, adr^.timeLastChange, adr^.ctChanges, nameof (adr^))}}};
		add ("</table>"); indentlevel--;
		add ("</td></tr></table>"); indentlevel--};
	add ("</td>"); indentlevel--;
	add ("</tr></table>"); indentlevel--;
	add ("</blockquote>"); indentlevel--;
	add ("<br><a name=\"unsubscribeButton\"><input type=\"submit\" name=\"unsubscribe\" value=\"Unsubscribe\"></a>");
	add ("</form>"); indentlevel--;
	return (htmltext)};
bundle { //test code
	html.setpagetableaddress (@scratchpad.vsparams);
	viewSubscriptions ()}



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.