bf2c869e642b5be1ad6f3542d078f155fc4d81f2
chmalee
  Wed Apr 19 14:08:42 2017 -0700
Removing typo of extraneous . from hubConnect redirect page, no refs

diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index df88f2c..23abdee 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -1,782 +1,782 @@
 /* hgHubConnect - the CGI web-based program to select track data hubs to connect with. */
 
 /* Copyright (C) 2014 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 
 #include "common.h"
 #include "hash.h"
 #include "linefile.h"
 #include "errAbort.h"
 #include "errCatch.h"
 #include "hCommon.h"
 #include "dystring.h"
 #include "jksql.h"
 #include "cheapcgi.h"
 #include "htmshell.h"
 #include "hdb.h"
 #include "hui.h"
 #include "cart.h"
 #include "dbDb.h"
 #include "web.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "dystring.h"
 #include "hPrint.h"
 #include "jsHelper.h"
 #include "obscure.h"
 #include "hgConfig.h"
 #include "trix.h"
 #include "net.h"
 
 
 struct cart *cart;	/* The user's ui state. */
 struct hash *oldVars = NULL;
 
 static char *pageTitle = "Track Data Hubs";
 char *database = NULL;
 char *organism = NULL;
 
 static void ourCellStart()
 {
 fputs("<TD>", stdout);  // do not add a newline
 }
 
 static void ourCellEnd()
 {
 puts("</TD>");
 }
 
 static void ourPrintCellLink(char *str, char *url)
 {
 ourCellStart();
 printf("<A class=\"cv\" HREF=\"%s\" TARGET=_BLANK>\n", url);
 if (str != NULL)
     fputs(str, stdout); // do not add a newline -- was causing trailing blanks get copied in cut and paste 
 puts("</A>");
 ourCellEnd();
 }
 
 static void ourPrintCell(char *str)
 {
 ourCellStart();
 if (str != NULL)
     fputs(str, stdout); // do not add a newline -- was causing trailing blanks get copied in cut and paste 
 ourCellEnd();
 }
 
 static char *removeLastComma(char *string)
 {
 if (string != NULL)
     {
     int len = strlen(string);
 
     if ( string[len - 1] == ',')
 	string[len - 1]  = 0;
     else if (len > 2 && endsWith(string,", "))
         string[len - 2] = 0;
     }
 return string;
 }
 
 #define GENLISTWIDTH 40
 static void printGenomeList(struct slName *genomes, int row)
 /* print supported assembly names from sl list */
 {
 /* List of associated genomes. */
 struct dyString *dy = newDyString(100);
 struct dyString *dyShort = newDyString(100);
 char *trimmedName = NULL;
 for(; genomes; genomes = genomes->next)
     {
     trimmedName = trackHubSkipHubName(genomes->name);
     dyStringPrintf(dy,"%s, ", trimmedName);
     if (dyShort->stringSize == 0 || (dyShort->stringSize+strlen(trimmedName)<=GENLISTWIDTH))
 	dyStringPrintf(dyShort,"%s, ", trimmedName);
     }
 char *genomesString = removeLastComma( dyStringCannibalize(&dy));
 char *genomesShort = removeLastComma( dyStringCannibalize(&dyShort));
 char tempHtml[1024+strlen(genomesString)+strlen(genomesShort)];
 if (strlen(genomesShort) > GENLISTWIDTH)  // If even the first element is too long, truncate it.
     genomesShort[GENLISTWIDTH] = 0;
 if (strlen(genomesShort)==strlen(genomesString))
     {
     safef(tempHtml, sizeof tempHtml, "%s", genomesString);
     }
 else
     {
     char id[256];
     safef(tempHtml, sizeof tempHtml, 
 	"<span id=Short%d>[+]&nbsp;%s...</span>"
 	"<span id=Full%d style=\"display:none\">[-]<br>%s</span>"
 	, row, genomesShort 
 	, row, genomesString);
 
     safef(id, sizeof id, "Short%d", row);
     jsOnEventByIdF("click", id,
 	"document.getElementById('Short%d').style.display='none';"
 	"document.getElementById('Full%d').style.display='inline';"
 	"return false;"
 	, row, row);
 
     safef(id, sizeof id, "Full%d", row);
     jsOnEventByIdF("click", id, 
 	"document.getElementById('Full%d').style.display='none';"
 	"document.getElementById('Short%d').style.display='inline';"
 	"return false;"
 	, row, row);
     }
 ourPrintCell(tempHtml);
 //ourPrintCell(removeLastComma( dyStringCannibalize(&dy)));
 }
 
 
 static void printGenomes(struct trackHub *thub, int row)
 /* print supported assembly names from trackHub */
 {
 /* List of associated genomes. */
 struct trackHubGenome *genomes = thub->genomeList;
 struct slName *list = NULL, *el;
 for(; genomes; genomes = genomes->next)
     {
     el = slNameNew(genomes->name);
     slAddHead(&list, el);
     }
 slReverse(&list);
 printGenomeList(list, row);
 }
 
 
 static void hgHubConnectUnlisted(struct hubConnectStatus *hubList, 
     struct hash *publicHash)
 /* Put up the list of unlisted hubs and other controls for the page. */
 /* uses publicHash to distingusih public hubs from unlisted ones */
 /* NOTE: Destroys hubList */
 {
 // put out the top of our page
 printf("<div id=\"unlistedHubs\" class=\"hubList\"> \n"
     "<table id=\"unlistedHubsTable\"> \n"
     "<thead><tr> \n"
 	"<th colspan=\"6\" id=\"addHubBar\"><label for=\"hubUrl\">URL:</label> \n"
 	"<input name=\"hubText\" id=\"hubUrl\" class=\"hubField\" "
 	    "type=\"text\" size=\"65\"> \n"
 	"<input name=\"hubAddButton\" id='hubAddButton' "
 		"class=\"hubField\" type=\"button\" value=\"Add Hub\">\n"
 	"</th> \n"
     "</tr> \n");
 jsOnEventById("click", "hubAddButton", 
     "var hubText = document.getElementById('hubUrl');"
     "hubText.value=$.trim(hubText.value);"
     "if(validateUrl($('#hubUrl').val())) { "
     " document.addHubForm.elements['hubUrl'].value=hubText.value;"
     " document.addHubForm.submit(); return true; } "
     "else { return false; }"
     );
 
 // count up the number of unlisted hubs we currently have
 int unlistedHubCount = 0;
 struct hubConnectStatus *unlistedHubList = NULL;
 struct hubConnectStatus *hub, *nextHub;
 
 for(hub = hubList; hub; hub = nextHub)
     {
     nextHub = hub->next;
     // if url is not in publicHash, it's unlisted */
     if (!((publicHash != NULL) && hashLookup(publicHash, hub->hubUrl)))
 	{
 	unlistedHubCount++;
 	slAddHead(&unlistedHubList, hub);
 	}
     }
 
 hubList = NULL;  // hubList no longer valid
 
 if (unlistedHubCount == 0)
     {
     // nothing to see here
     printf("<tr><td>No Unlisted Track Hubs</td></tr>");
     printf("</thead></table></div>");
     return;
     }
 
 // time to output the big table.  First the header
 printf(
     "<tr> "
 	"<th>Display</th> "
 	"<th>Hub Name</th> "
 	"<th>Description</th> "
 	"<th>Assemblies</th> "
     "</tr>\n"
     "</thead>\n");
 
 // start first row
 printf("<tbody>");
 
 char id[256];
 int count = 0;
 for(hub = unlistedHubList; hub; hub = hub->next)
     {
     char hubName[64];
     safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, hub->id);
     if (!cartUsualBoolean(cart, hubName, FALSE))
 	continue;
 
     if (count)
 	webPrintLinkTableNewRow();  // ends last row and starts a new one
     count++;
 
     puts("<tr>");
 
     ourCellStart();
     safef(id, sizeof id, "hubDisconnectButton%d", count);
     printf("<input name=\"hubDisconnectButton\" id='%s' "
 	"class=\"hubDisconnectButton\" type=\"button\" value=\"Disconnect\">\n", id);
     jsOnEventByIdF("click", id, 
 	"document.disconnectHubForm.elements['hubId'].value='%d';"
 	"document.disconnectHubForm.submit(); return true;", hub->id);
     ourCellEnd();
 
     if (hub->trackHub != NULL)
 	{
 	ourPrintCellLink(hub->trackHub->shortLabel, hub->hubUrl);
 	}
     else
 	ourPrintCell("");
 
     if (!isEmpty(hub->errorMessage))
 	{
 	ourCellStart();
 	printf("<span class=\"hubError\">ERROR: %s </span>"
 	    "<a TARGET=_BLANK href=\"../goldenPath/help/hgTrackHubHelp.html#Debug\">Debug Help</a>\n", 
 	    hub->errorMessage);
 	
 	safef(id, sizeof id, "hubClearButton%d", count);
 	// give people a chance to clear the error 
 	printf("<input name=\"hubClearButton\"  id='%s' "
 		"class=\"hubButton\" type=\"button\" value=\"Retry Hub\">"
 		, id);
 	jsOnEventByIdF("click", id,
 	    "document.resetHubForm.elements['hubCheckUrl'].value='%s';"
 	    "document.resetHubForm.submit(); return true;", hub->hubUrl);
 	ourCellEnd();
 	}
     else if (hub->trackHub != NULL)
 	{
 	if (hub->trackHub->descriptionUrl != NULL)
 	    ourPrintCellLink(hub->trackHub->longLabel, hub->trackHub->descriptionUrl);
 	else
 	    ourPrintCell(hub->trackHub->longLabel);
 	}
     else
 	ourPrintCell("");
 
     if (hub->trackHub != NULL)
 	printGenomes(hub->trackHub, count);
     else
 	ourPrintCell("");
 
     puts("</tr>");
     }
 
 printf("</tbody></TABLE>\n");
 printf("</div>");
 }
 
 static void addPublicHubsToHubStatus(struct sqlConnection *conn, char *publicTable, char  *statusTable)
 /* add url's in the hubPublic table to the hubStatus table if they aren't there already */
 {
 char query[1024];
 sqlSafef(query, sizeof(query), "select hubUrl from %s where hubUrl not in (select hubUrl from %s)\n", publicTable, statusTable); 
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     char *errorMessage = NULL;
     char *url = row[0];
 
     // add this url to the hubStatus table
     hubFindOrAddUrlInStatusTable(database, cart, url, &errorMessage);
     }
 }
 
 struct hash *getUrlSearchHash(char *trixFile, char *hubSearchTerms)
 /* find hubs that match search term in trixFile */
 {
 struct hash *urlSearchHash = newHash(5);
 struct trix *trix = trixOpen(trixFile);
 int trixWordCount = chopString(hubSearchTerms, " ", NULL, 0);
 char *trixWords[trixWordCount];
 trixWordCount = chopString(hubSearchTerms, " ", trixWords, trixWordCount);
 
 struct trixSearchResult *tsList = trixSearch(trix, trixWordCount, trixWords, tsmExpand);
 for ( ; tsList != NULL; tsList = tsList->next)
     hashStore(urlSearchHash, tsList->itemId);
 
 return urlSearchHash;
 }
 
 static boolean outputPublicTable(struct sqlConnection *conn, char *publicTable, char *statusTable, struct hash **pHash)
 /* Put up the list of public hubs and other controls for the page. */
 {
 char *trixFile = hReplaceGbdb(cfgOptionEnvDefault("HUBSEARCHTRIXFILE", "hubSearchTrixFile", "/gbdb/hubs/public.ix"));
 char *hubSearchTerms = cartOptionalString(cart, hgHubSearchTerms);
 char *cleanSearchTerms = cloneString(hubSearchTerms);
 int trixFd = netUrlOpen(trixFile);
 boolean haveTrixFile = (trixFd != -1);
 if (haveTrixFile)
     close(trixFd);
 struct hash *urlSearchHash = NULL;
 
 printf("<div id=\"publicHubs\" class=\"hubList\"> \n");
 
 // if we have a trix file, draw the search box
 if (haveTrixFile)
     {
     puts("Enter search terms to find in public track hub description pages:<BR>"
 	"<input name=\"hubSearchTerms\" id=\"hubSearchTerms\" class=\"hubField\" "
 	"type=\"text\" size=\"65\"> \n"
 	"<input name=\"hubSearchButton\" id='hubSearchButton' "
 	    "class=\"hubField\" type=\"button\" value=\"Search Public Hubs\">\n");
     jsOnEventById("click", "hubSearchButton",
 	"document.searchHubForm.elements['hubSearchTerms'].value=$('#hubSearchTerms').val();"
 	"document.searchHubForm.submit();return true;");
     puts("<BR><BR>\n");
     }
 
 // if we have search terms, put out the line telling the user so
 if (haveTrixFile && !isEmpty(hubSearchTerms))
     {
     printf("Displayed list <B>restricted by search terms:</B> %s\n", hubSearchTerms);
     puts("<input name=\"hubDeleteSearchButton\" id='hubDeleteSearchButton' "
 	"class=\"hubField\" type=\"button\" value=\"Show All Hubs\">\n");
     jsOnEventById("click", "hubDeleteSearchButton",
 	"document.searchHubForm.elements['hubSearchTerms'].value='';"
 	"document.searchHubForm.submit();return true;");
     puts("<BR><BR>\n");
 
     strLower(cleanSearchTerms);
     urlSearchHash = getUrlSearchHash(trixFile, cleanSearchTerms);
     }
 
 // make sure all the public hubs are in the hubStatus table.
 addPublicHubsToHubStatus(conn, publicTable, statusTable);
 
 struct hash *publicHash = newHash(5);
 char query[512];
 bool hasDescription = sqlColumnExists(conn, publicTable, "descriptionUrl");
 if (hasDescription)
     sqlSafef(query, sizeof(query), "select p.hubUrl,p.shortLabel,p.longLabel,p.dbList,s.errorMessage,s.id,p.descriptionUrl from %s p,%s s where p.hubUrl = s.hubUrl", 
 	  publicTable, statusTable); 
 else
     sqlSafef(query, sizeof(query), "select p.hubUrl,p.shortLabel,p.longLabel,p.dbList,s.errorMessage,s.id from %s p,%s s where p.hubUrl = s.hubUrl", 
 	 publicTable, statusTable); 
 
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row;
 int count = 0;
 boolean gotAnyRows = FALSE;
 char jsId[256];
 while ((row = sqlNextRow(sr)) != NULL)
     {
     ++count;
     char *url = row[0], *shortLabel = row[1], *longLabel = row[2], 
     	  *dbList = row[3], *errorMessage = row[4], *descriptionUrl = row[6];
     int id = atoi(row[5]);
 
     hashStore(publicHash, url);
     if ((urlSearchHash != NULL) && (hashLookup(urlSearchHash, url) == NULL))
 	continue;
 
     struct slName *dbListNames = slNameListFromComma(dbList);
 
     if (gotAnyRows)
 	webPrintLinkTableNewRow();
     else
 	{
 	/* output header */
 
 	puts("<I>Clicking Connect redirects to the gateway page of the selected hub's default assembly.</I><BR>");
 	printf("<table id=\"publicHubsTable\"> "
 	    "<thead><tr> "
 		"<th>Display</th> "
 		"<th>Hub Name</th> "
 		"<th>Description</th> "
 		"<th>Assemblies</th> "
 	    "</tr></thead>\n");
 
 	// start first row
 	printf("<tbody> <tr>");
 	gotAnyRows = TRUE;
 	}
 
     if (id != 0)
 	{
 	ourCellStart();
 	char hubName[32];
 	safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, id);
 	if (cartUsualBoolean(cart, hubName, FALSE))
 	    {
 	    safef(jsId, sizeof jsId, "hubDisconnectButton%d", count);
 	    printf("<input name=\"hubDisconnectButton\" id='%s' "
 		"class=\"hubDisconnectButton\" type=\"button\" value=\"Disconnect\">\n", jsId);
 	    jsOnEventByIdF("click", jsId, 
 		"document.disconnectHubForm.elements['hubId'].value= '%d';"
 		"document.disconnectHubForm.submit();return true;", id);
 	    }
 	else
 	    {
 	    // get first name off of list of supported databases
 	    char * name = dbListNames->name;
 
 	    // if the name isn't currently loaded, we assume it's a hub
 	    if (!hDbExists(name))
 		{
 		char buffer[512];
 
 		safef(buffer, sizeof buffer, "hub_%d_%s",  id, name);
 		name = cloneString(buffer);
 		}
 
 	    safef(jsId, sizeof jsId, "hubConnectButton%d", count);
 	    printf("<input name=\"hubConnectButton\" id='%s' "
 		"class=\"hubButton\" type=\"button\" value=\"Connect\">\n", jsId);
 	    jsOnEventByIdF("click", jsId, 
 		"document.connectHubForm.elements['hubUrl'].value= '%s';"
 		"document.connectHubForm.elements['db'].value= '%s';"
 		"document.connectHubForm.submit();return true;", url,name);
 	    }
 
 	ourCellEnd();
 	}
     else
 	errAbort("cannot get id for hub with url %s\n", url);
 
     ourPrintCellLink(shortLabel, url);
 
     if (isEmpty(errorMessage))
 	{
 	if (hasDescription && !isEmpty(descriptionUrl))
 	    ourPrintCellLink(longLabel, descriptionUrl);
 	else
 	    ourPrintCell(longLabel);
 	}
     else
 	{
 	ourCellStart();
 	printf("<span class=\"hubError\">ERROR: %s </span>"
 	    "<a href=\"../goldenPath/help/hgTrackHubHelp.html#Debug\">Debug Help</a>", 
 	    errorMessage);
 	safef(jsId, sizeof jsId, "hubClearButton%d", count);
 	printf(
 	"<input name=\"hubClearButton\" id='%s' "
 		"class=\"hubButton\" type=\"button\" value=\"Retry Hub\">"
 		, jsId);
 	jsOnEventByIdF("click", jsId, 
 	    "document.resetHubForm.elements['hubCheckUrl'].value='%s';"
 	    "document.resetHubForm.submit();return true;", url);
 	ourCellEnd();
 	}
 
     printGenomeList(dbListNames, count); 
     }
 sqlFreeResult(&sr);
 
 if (gotAnyRows)
     printf("</TR></tbody></TABLE>\n");
 
 printf("</div>");
 *pHash = publicHash;
 return gotAnyRows;
 }
 
 
 struct hash *hgHubConnectPublic()
 /* Put up the list of public hubs and other controls for the page. */
 {
 struct hash *retHash = NULL;
 struct sqlConnection *conn = hConnectCentral();
 char *publicTable = cfgOptionEnvDefault("HGDB_HUB_PUBLIC_TABLE", 
 	hubPublicTableConfVariable, defaultHubPublicTableName);
 char *statusTable = cfgOptionEnvDefault("HGDB_HUB_STATUS_TABLE", 
 	hubStatusTableConfVariable, defaultHubStatusTableName);
 if (!(sqlTableExists(conn, publicTable) && 
 	outputPublicTable(conn, publicTable,statusTable, &retHash)) )
     {
     printf("<div id=\"publicHubs\" class=\"hubList\"> \n");
     printf("No Public Track Hubs found that match search criteria.<BR>");
     printf("</div>");
     }
 hDisconnectCentral(&conn);
 
 return retHash;
 }
 
 static void tryHubOpen(unsigned id)
 /* try to open hub, leaks trackHub structure */
 {
 /* try opening this again to reset error */
 struct sqlConnection *conn = hConnectCentral();
 struct errCatch *errCatch = errCatchNew();
 struct hubConnectStatus *hub = NULL;
 if (errCatchStart(errCatch))
     hub = hubConnectStatusForId(conn, id);
 errCatchEnd(errCatch);
 if (errCatch->gotError)
     hubUpdateStatus( errCatch->message->string, NULL);
 else
     hubUpdateStatus(NULL, hub);
 errCatchFree(&errCatch);
 
 hDisconnectCentral(&conn);
 }
 
 
 static int doRedirect(struct cart *theCart)
 {
 struct hubConnectStatus *hub = hubConnectNewHub();
 if (hub == NULL)
     return 0;
 
 char headerText[1024];
 
 char *errorMessage;
 hubFindOrAddUrlInStatusTable(database, cart, hub->hubUrl, &errorMessage);
 
 // if there is an error message, we stay in hgHubConnect
 if (errorMessage != NULL)
     return 0;
 
 getDbAndGenome(cart, &database, &organism, oldVars);
 
 int redirDelay = 3;
 printf( "<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"%d;URL=%s?%s\">",
 	  redirDelay,"../cgi-bin/hgGateway",cartSidUrlString(cart));
 safef(headerText, sizeof(headerText), "Hub Connect Successful");
 cartWebStart(cart, NULL, "%s", headerText);
 
 hPrintf("You will be automatically redirected to the gateway page for this hub's default database "
     "(<A HREF=\"../cgi-bin/hgGateway?%s\">%s</A>) in %d seconds.<BR><BR>",
 	  cartSidUrlString(cart),trackHubSkipHubName(database),redirDelay);
 
 struct trackHub *tHub = hub->trackHub;
 if (tHub->email != NULL)
     {
-    hPrintf("<B>This hub is provided courtesy of <A HREF=\"mailto:%s\">%s</A>.</B>. Please contact them with any questions.", tHub->email, tHub->email);
+    hPrintf("<B>This hub is provided courtesy of <A HREF=\"mailto:%s\">%s</A>.</B> Please contact them with any questions.", tHub->email, tHub->email);
     }
 
 hPrintf("<BR><BR>");
 hPrintf("Hub: %s<BR><BR>", tHub->longLabel);
 hPrintf("Hub Genomes: ");
 struct trackHubGenome *genomeList = tHub->genomeList;
 
 boolean firstTime = TRUE;
 for(; genomeList; genomeList = genomeList->next)
     {
     if (!firstTime)
 	hPrintf(",");
     firstTime = FALSE;
     hPrintf("<A href=\"../cgi-bin/hgTracks?db=%s&%s\">%s</A>",genomeList->name, 
 	cartSidUrlString(cart),trackHubSkipHubName(genomeList->name));
     }
 hPrintf("<BR><BR>");
 return 1;
 }
 
 static void doResetHub(struct cart *theCart)
 {
 char *url = cartOptionalString(cart, hgHubCheckUrl);
 
 if (url != NULL)
     {
     udcSetCacheTimeout(1);
     unsigned id = hubResetError(url);
     tryHubOpen(id);
     }
 else
     errAbort("must specify url in %s\n", hgHubDataText);
 }
 
 static void doClearHub(struct cart *theCart)
 {
 char *url = cartOptionalString(cart, hgHubDataText);
 
 printf("<pre>clearing hub %s\n",url);
 if (url != NULL)
     hubClearStatus(url);
 else
     errAbort("must specify url in %s\n", hgHubDataText);
 printf("<pre>Completed\n");
 }
 
 
 static void checkTrackDbs(struct hubConnectStatus *hubList)
 {
 struct hubConnectStatus *hub = hubList;
 
 for(; hub; hub = hub->next)
     {
     struct errCatch *errCatch = errCatchNew();
     if (errCatchStart(errCatch))
 	{
 	hubAddTracks(hub, database);
 	}
     errCatchEnd(errCatch);
     if (errCatch->gotError)
 	{
 	hub->errorMessage = cloneString(errCatch->message->string);
 	hubUpdateStatus( errCatch->message->string, hub);
 	}
     else
 	hubUpdateStatus(NULL, hub);
     }
 }
 
 void doMiddle(struct cart *theCart)
 /* Write header and body of html page. */
 {
 cart = theCart;
 
 if(cgiIsOnWeb())
     checkForGeoMirrorRedirect(cart);
 
 if (cartVarExists(cart, hgHubDoClear))
     {
     doClearHub(cart);
     cartWebEnd();
     return;
     }
 
 if (cartVarExists(cart, hgHubCheckUrl))
     {
     doResetHub(cart);
     }
 
 if (cartVarExists(cart, hgHubDoRedirect))
     {
     if (doRedirect(cart))
 	{
 	cartWebEnd();
 	return;
 	}
     }
 
 cartWebStart(cart, NULL, "%s", pageTitle);
 jsIncludeFile("jquery.js", NULL);
 jsIncludeFile("utils.js", NULL);
 jsIncludeFile("jquery-ui.js", NULL);
 
 webIncludeResourceFile("jquery-ui.css");
 
 jsIncludeFile("ajax.js", NULL);
 jsIncludeFile("hgHubConnect.js", NULL);
 jsIncludeFile("jquery.cookie.js", NULL);
 
 printf("<div id=\"hgHubConnectUI\"> <div id=\"description\"> \n");
 printf(
     "<P>Track data hubs are collections of external tracks that can be imported into the UCSC Genome Browser. "
     "Hub tracks show up under the hub's own blue label bar on the main browser page, "
     "as well as on the configure page. For more information, see the "
     "<A HREF=\"../goldenPath/help/hgTrackHubHelp.html\" TARGET=_blank>"
     "User's Guide</A>."
     "To import a public hub click its \"Connect\" button below.</P>"
     "<P><B>NOTE: Because Track Hubs are created and maintained by external sources,"
     " UCSC is not responsible for their content.</B></P>"
    );
 printf("</div>\n");
 
 getDbAndGenome(cart, &database, &organism, oldVars);
 
 char *survey = cfgOptionEnv("HGDB_HUB_SURVEY", "hubSurvey");
 char *surveyLabel = cfgOptionEnv("HGDB_HUB_SURVEY_LABEL", "hubSurveyLabel");
 
 if (survey && differentWord(survey, "off"))
     hPrintf("<span style='background-color:yellow;'><A HREF='%s' TARGET=_BLANK><EM><B>%s</EM></B></A></span>\n", survey, surveyLabel ? surveyLabel : "Take survey");
 hPutc('\n');
 
 // grab all the hubs that are listed in the cart
 struct hubConnectStatus *hubList =  hubConnectStatusListFromCartAll(cart);
 
 checkTrackDbs(hubList);
 
 // here's a little form for the add new hub button
 printf("<FORM ACTION=\"%s\" NAME=\"addHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubUrl", "");
 cgiMakeHiddenVar( hgHubDoFirstDb, "on");
 cgiMakeHiddenVar( hgHubDoRedirect, "on");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 cartSaveSession(cart);
 puts("</FORM>");
 
 // this is the form for the connect hub button
 printf("<FORM ACTION=\"%s\" NAME=\"connectHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubUrl", "");
 cgiMakeHiddenVar("db", "");
 cgiMakeHiddenVar( hgHubDoRedirect, "on");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 cartSaveSession(cart);
 puts("</FORM>");
 
 // this is the form for the disconnect hub button
 printf("<FORM ACTION=\"%s\" NAME=\"disconnectHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar("hubId", "");
 cgiMakeHiddenVar(hgHubDoDisconnect, "on");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 cartSaveSession(cart);
 puts("</FORM>");
 
 // this is the form for the reset hub button
 printf("<FORM ACTION=\"%s\" NAME=\"resetHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar(hgHubCheckUrl, "");
 cartSaveSession(cart);
 puts("</FORM>");
 
 // this is the form for the search hub button
 printf("<FORM ACTION=\"%s\" NAME=\"searchHubForm\">\n",  "../cgi-bin/hgHubConnect");
 cgiMakeHiddenVar(hgHubSearchTerms, "");
 cgiMakeHiddenVar(hgHubDoSearch, "on");
 cartSaveSession(cart);
 puts("</FORM>");
 
 // ... and now the main form
 printf("<FORM ACTION=\"%s\" METHOD=\"POST\" NAME=\"mainForm\">\n", "../cgi-bin/hgGateway");
 cartSaveSession(cart);
 
 // we have two tabs for the public and unlisted hubs
 printf("<div id=\"tabs\">"
        "<ul> <li><a href=\"#publicHubs\">Public Hubs</a></li>"
        "<li><a href=\"#unlistedHubs\">My Hubs</a></li> "
        "</ul> ");
 
 struct hash *publicHash = hgHubConnectPublic();
 hgHubConnectUnlisted(hubList, publicHash);
 printf("</div>");
 
 printf("<div class=\"tabFooter\">");
 
 char *emailAddress = cfgOptionDefault("hub.emailAddress","genome@soe.ucsc.edu");
 printf("<span class=\"small\">"
     "Contact <A HREF=\"mailto:%s\">%s</A> to add a public hub."
     "</span>\n", emailAddress,emailAddress);
 printf("</div>");
 
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 
 puts("</FORM>");
 printf("</div>\n");
 cartWebEnd();
 }
 
 char *excludeVars[] = {"Submit", "submit", "hc_one_url", 
     hgHubCheckUrl, hgHubDoClear, hgHubDoDisconnect,hgHubDoRedirect, hgHubDataText, 
     hgHubConnectRemakeTrackHub, NULL};
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 long enteredMainTime = clock1000();
 oldVars = hashNew(10);
 cgiSpoof(&argc, argv);
 cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars);
 cgiExitTime("hgHubConnect", enteredMainTime);
 return 0;
 }