c7211155cab4ec213239cf6979ee4b63a1d96374
max
  Tue Aug 11 03:07:18 2015 -0700
adding email display during redirect, GET urls, adding onlyDbs/notDbs tags to support hg38, refs #15113.

diff --git src/hg/hgTracks/extTools.c src/hg/hgTracks/extTools.c
index 50ec9cf..00f512f 100644
--- src/hg/hgTracks/extTools.c
+++ src/hg/hgTracks/extTools.c
@@ -8,38 +8,43 @@
  * See README in this or parent directory for licensing information. */
 
 #include "common.h"
 #include "dystring.h"
 #include "hCommon.h"
 #include "htmshell.h"
 #include "hash.h"
 #include "web.h"
 #include "ra.h"
 #include "hgTracks.h"
 #include "extTools.h"
 #include "hgFind.h"
 #include "obscure.h"
 #include "net.h"
 
-static char *getRequiredRaSetting(struct hash *hash, char *name, struct lineFile *lf)
-/* Grab a group setting out of the ra hash.  errAbort if not found. */
+static char *cloneRaSetting(struct hash *hash, char *name, struct lineFile *lf, bool mustExist)
+/* clone a setting out of the ra hash.  errAbort if mustExit and not found, otherwise NULL. */
 {
 char *str;
 if ((str = hashFindVal(hash, name)) == NULL) 
+    {
+    if (mustExist)
         errAbort("missing required setting '%s' on line %d in file %s\n",
             name, lf->lineIx, lf->fileName);
-return str;
+    else
+        return NULL;
+    }
+return cloneString(str);
 }
 
 struct extTool *readExtToolRa(char *raFileName) 
 /* parse the extTools.ra file. Inspired by trackHub.c:readGroupRa() */
 {
 struct lineFile *lf = udcWrapShortLineFile(raFileName, NULL, 1*1024*1024);
 struct extTool *list = NULL;
 //struct hash *ra;
 struct slPair *raList;
 while ((raList = raNextStanzAsPairs(lf)) != NULL)
     {
     struct extTool *et;
     AllocVar(et);
 
     struct slPair *paramList = NULL;
@@ -59,42 +64,53 @@
             // hacky way to allow spaces in parameter names and values
             char *name = replaceChars(paramArr[0], "%20", " ");
             char *val;
             if (fCount==2)
                 val = cloneString(paramArr[1]);
             else
                 val = cloneString("");
             val = replaceChars(val, "%20", " ");
             slPairAdd(&paramList, name, val);
             }
         else
             // add all other name/val pairs to the hash
             hashAdd(raHash, raPair->name, cloneString(raPair->val));
         }
 
-    // pull out the normal fields from the hash
-    et->tool = cloneString(getRequiredRaSetting(raHash, "tool", lf));
-    et->shortLabel = cloneString(getRequiredRaSetting(raHash, "shortLabel", lf));
+    // pull out the required fields from the hash
+    et->tool = cloneRaSetting(raHash, "tool", lf, TRUE);
+    et->shortLabel = cloneRaSetting(raHash, "shortLabel", lf, TRUE);
+    et->longLabel = cloneRaSetting(raHash, "longLabel", lf, TRUE);
+    et->url = cloneRaSetting(raHash, "url", lf, TRUE);
+    et->dbs = NULL;
+
+    // optional fields
+    et->email = cloneRaSetting(raHash, "email", lf, FALSE);
+    if (hashFindVal(raHash, "onlyDbs"))
+        et->dbs = commaSepToSlNames(hashFindVal(raHash, "onlyDbs"));
+    if (hashFindVal(raHash, "notDbs"))
+        et->notDbs = commaSepToSlNames(hashFindVal(raHash, "notDbs"));
+
+    char *isHttpGet = hashFindVal(raHash, "isHttpGet");
+    if (isHttpGet && \
+     (sameString(isHttpGet, "yes") || sameString(isHttpGet, "on") || sameString(isHttpGet, "true")))
+            et->isHttpGet = TRUE;
+
     char *maxSize = hashFindVal(raHash, "maxSize");
     if (maxSize!=NULL)
         et->maxSize = sqlUnsignedOrError(maxSize, "Error: maxSize %s for tool %s is not a number", \
                 maxSize, et->tool);
-    et->longLabel = cloneString(getRequiredRaSetting(raHash, "longLabel", lf));
-    et->url = cloneString(getRequiredRaSetting(raHash, "url", lf));
-    et->dbs = NULL;
-    if (hashFindVal(raHash, "dbs"))
-        et->dbs = commaSepToSlNames(hashFindVal(raHash, "dbs"));
 
     slReverse(&paramList);
     et->params = paramList;
 
     slAddHead(&list, et);
     freeHashAndVals(&raHash);
     slPairFree(&raList);
     }
 
 if (list)
     slReverse(&list);
 lineFileClose(&lf);
 return list;
 }
 
@@ -105,104 +121,118 @@
 
 struct extTool *extTools = readExtToolRa("extTools.ra");
 struct extTool *et;
 for (et = extTools; et != NULL; et = et->next)
     if (sameWord(et->tool, tool))
         break;
 if (et==NULL)
     errAbort("No configuration found for tool %s", tool);
 
 // construct an invisible CGI form with the given parameters
 printf("<html><body>\n");
 
 if (debug)
     printf("Target URL: %s<p>", et->url);
 
-printf("<form id=\"redirForm\" method=\"POST\" action=\"%s\">\n", et->url);
-
-struct slPair *slp;
-char *db = cartString(cart, "db");
-char *pos = cartString(cart, "position");
-
 char *chromName;
 int winStart, winEnd;
-findGenomePos(db, pos, &chromName, &winStart, &winEnd, cart);
+char *db = cartString(cart, "db");
+char *pos = cartString(cart, "position");
 int len = winEnd-winStart;
+findGenomePos(db, pos, &chromName, &winStart, &winEnd, cart);
+
+char *url = replaceInUrl(et->url, "", cart, db, chromName, winStart, winEnd, NULL, TRUE);
+
+printf("You're being redirected from the UCSC Genome Browser to the site %s<br>\n", url);
+if (et->email)
+    printf("Please contact %s for questions on this tool.<br>\n", et->email);
+
+char *method = "POST";
+if (et->isHttpGet)
+    method = "GET";
+
+printf("<form id=\"redirForm\" method=\"%s\" action=\"%s\">\n", method, url);
+
+struct slPair *slp;
 
 if (et->maxSize!=0 && len > et->maxSize)
     {
     printf("Sorry, this tool accepts only a sequence with less than %d base pairs<p>\n"
       "Try to zoom in some more.<p>\n", et->maxSize);
     return;
     }
 
 boolean submitDone = FALSE;
 for (slp=et->params; slp!=NULL; slp=slp->next)
     {
     char* val = slp->val;
     if (sameWord(val, "$db"))
         val = db;
     if (sameWord(val, "$position"))
         val = pos;
     if (sameWord(val, "$returnUrl"))
         {
+        // get the full URL of this hgTracks page, so external page can construct a custom track
+        // and link back to us
         char* host = getenv("HTTP_HOST");
         char* reqUrl = getenv("REQUEST_URI");
 
         struct netParsedUrl npu;
         netParseUrl(reqUrl, &npu);
         safecpy(npu.protocol, sizeof(npu.protocol), "http");
         safecpy(npu.host, sizeof(npu.host), host);
         // remove everything after ? in URL
         char *e = strchr(npu.file, '?');
         if (e) *e = 0; 
         val = urlFromNetParsedUrl(&npu);
         }
     // half the current window size
     if (stringIn("$halfLen", val))
         {
         char buf[64];
         safef(buf, sizeof(buf), "%d", len/2);
         val = replaceChars(val, "$halfLen", buf);
         }
     if (sameWord(val, "$seq"))
         {
         static struct dnaSeq *seq = NULL;
         seq = hDnaFromSeq(db, chromName, winStart, winEnd, dnaLower);
         val = seq->dna;
         }
     // any remaining $-expression might be one of the general ones
     if (stringIn("$", val))
+        {
         val = replaceInUrl(val, "", cart, db, chromName, winStart, winEnd, NULL, TRUE);
+        }
 
     // output
     if (debug)
         {
         printf("%s: ", slp->name);
-        printf("<input name=\"%s\" value=\"%s\"><p>", slp->name, val);
+        printf("<input name=\"%s\" value=\"%s\"><p>\n", slp->name, val);
         }
     else
         {
         // parameter named submit is a special case
         if (sameWord(slp->name, "submit"))
             {
             submitDone = TRUE;
             printf("<input type=\"submit\" value=\"%s\" style=\"position: absolute; left: -9999px; "
                 "width: 1px; height: 1px;\">\n", val);
             }
         else
-            printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">", slp->name, val);
+            printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n", slp->name, val);
         }
     }
 
 // a hidden submit button, see
 // http://stackoverflow.com/questions/477691/submitting-a-form-by-pressing-enter-without-a-submit-button
 if (debug)
     printf("<input type=\"submit\">\n");
 else if (!submitDone)
     printf("<input type=\"submit\" style=\"position: absolute; left: -9999px; width: 1px; height: 1px;\">\n");
 printf("</form>\n");
 // a little javascript that clicks the submit button
 if (!debug)
     printf("<script>document.getElementById(\"redirForm\").submit();</script>\n");
 printf("</body></html>\n");
 }