45014fb713fc38c6fa2c5ca8e76874c5b48d133d
hiram
  Wed May 27 16:05:11 2026 -0700
correctly use the appropriate host for the hgcentral table refs #31811

diff --git src/hg/hubApi/liftOver.c src/hg/hubApi/liftOver.c
index dfa3b03f982..b0968de83ca 100644
--- src/hg/hubApi/liftOver.c
+++ src/hg/hubApi/liftOver.c
@@ -1,32 +1,29 @@
 /* liftOver functions */
 
 #include "dataApi.h"
 #include "hgFind.h"
 #include "cartTrackDb.h"
 #include "cartJson.h"
 #include "genark.h"
 #include "asmAlias.h"
 #include "assemblyList.h"
 #include "liftOver.h"
 #include "liftOverChain.h"
 #include "net.h"
 #include "wikiLink.h"
 #include "userdata.h"
-/* do not need the mailViaPipe function here
-#include "mailViaPipe.h"
-*/
 
 /**** SHOULD BE IN LIBRARY - code from hgConvert.c ******/
 static long chainTotalBlockSize(struct chain *chain)
 /* Return sum of sizes of all blocks in chain */
 {
 struct cBlock *block;
 long total = 0;
 for (block = chain->blockList; block != NULL; block = block->next)
     total += block->tEnd - block->tStart;
 return total;
 }
 /**** SHOULD BE IN LIBRARY - code from hgConvert.c ******/
 
 static void chainListOut(char *fromDb, char* toDb, int origSize, char *fromPos, struct chain *chainList)
 /* given the list of chains, output the list in JSON */
@@ -164,92 +161,95 @@
             jsonWriteString(jw, "pendingRequestTime", row[2]);
             }
         sqlFreeResult(&sr);
         }
     }
 
 apiFinishOutput(0, NULL, jw);
 hDisconnectCentral(&conn);
 }
 
 static void loginStatus()
 /* output current user login status as JSON */
 {
 char *userName = (loginSystemEnabled() || wikiLinkEnabled()) ? wikiLinkUserName() : NULL;
 struct jsonWrite *jw = apiStartOutput();
+char hgLoginLink[2048];
+safef(hgLoginLink, sizeof(hgLoginLink), "%shgLogin", hLoginHostCgiBinUrl());
 
 if (userName != NULL)
     {
     // Get both email and realName from gbMembers table
     struct sqlConnection *sc = hConnectCentral();
     struct dyString *query = sqlDyStringCreate("select email, realName from gbMembers where userName = '%s'", userName);
     struct sqlResult *sr = sqlGetResult(sc, dyStringCannibalize(&query));
     char **row = sqlNextRow(sr);
 
     char *email = NULL;
     char *realName = NULL;
     if (row != NULL)
         {
         email = cloneString(row[0] ? row[0] : "");
         realName = cloneString(row[1] ? row[1] : "");
         }
     sqlFreeResult(&sr);
     hDisconnectCentral(&sc);
 
     // Build logout URL with returnto parameter
     char *returnTo = cgiOptionalString("returnTo");
     struct dyString *logoutUrl = dyStringNew(0);
+    dyStringPrintf(logoutUrl, "%s?hgLogin.do.displayLogout=1", hgLoginLink);
     if (isNotEmpty(returnTo))
         {
         char *encodedReturnUrl = cgiEncodeFull(returnTo);
-        dyStringPrintf(logoutUrl, "/cgi-bin/hgLogin?hgLogin.do.displayLogout=1&returnto=%s", encodedReturnUrl);
+
+        dyStringPrintf(logoutUrl, "&returnto=%s", encodedReturnUrl);
         freeMem(encodedReturnUrl);
         }
-    else
-        {
-        dyStringPrintf(logoutUrl, "/cgi-bin/hgLogin?hgLogin.do.displayLogout=1");
-        }
 
     jsonWriteString(jw, "userName", userName);
     jsonWriteString(jw, "email", email ? email : "");
     jsonWriteString(jw, "realName", realName ? realName : "");
     jsonWriteString(jw, "logoutUrl", dyStringCannibalize(&logoutUrl));
 
     if (email)
         freeMem(email);
     if (realName)
         freeMem(realName);
     }
 else
     {
     jsonWriteString(jw, "userName", NULL);
     // Use returnTo parameter passed by calling JavaScript
     char *returnTo = cgiOptionalString("returnTo");
+    struct dyString *loginUrl = dyStringNew(0);
+    dyStringPrintf(loginUrl, "%s?hgLogin.do.displayLoginPage=1", hgLoginLink);
+    struct dyString *signUpUrl = dyStringNew(0);
+    dyStringPrintf(signUpUrl, "%s?hgLogin.do.displaySignupPage=1", hgLoginLink);
     if (isNotEmpty(returnTo))
         {
         char *encodedReturnUrl = cgiEncodeFull(returnTo);
-        struct dyString *loginUrl = dyStringNew(0);
-        dyStringPrintf(loginUrl, "/cgi-bin/hgLogin?hgLogin.do.displayLoginPage=1&returnto=%s", encodedReturnUrl);
+        dyStringPrintf(loginUrl, "&returnto=%s", encodedReturnUrl);
         jsonWriteString(jw, "loginUrl", dyStringCannibalize(&loginUrl));
         freeMem(encodedReturnUrl);
         }
     else
         {
         // No returnTo provided, just give basic login URL
-        jsonWriteString(jw, "loginUrl", "/cgi-bin/hgLogin?hgLogin.do.displayLoginPage=1");
+        jsonWriteString(jw, "loginUrl", dyStringCannibalize(&loginUrl));
         }
-    jsonWriteString(jw, "signupUrl", "/cgi-bin/hgLogin?hgLogin.do.displaySignupPage=1");
+    jsonWriteString(jw, "signupUrl", dyStringCannibalize(&signUpUrl));
     }
 
 apiFinishOutput(0, NULL, jw);
 }
 
 /**** SHOULD BE IN LIBRARY - code from hgConvert.c ******/
 static char *skipWord(char *fw)
 /* skips over current word to start of next.
  * Error for this not to exist. */
 {
 char *s;
 s = skipToSpaces(fw);
 if (s == NULL)
     errAbort("Expecting two words in .ra file line %s\n", fw);
 s = skipLeadingSpaces(s);
@@ -476,37 +476,30 @@
     }
 
 char *toAddr = cfgOption("chainFileRequestEmail");
 char *fromAddr = cfgOption("apiFromEmail");
 
 if (isNotEmpty(toAddr) && isNotEmpty(fromAddr))
     {
     char nowTime[256];
     time_t seconds = clock1();
     struct tm *timeNow = localtime(&seconds);
     strftime(nowTime, sizeof nowTime, "%Y-%m-%d %H:%M:%S", timeNow);
 
     struct dyString *msg = newDyString(0);
     /* may need to encode these inputs to make them safe */
     dyStringPrintf(msg, "%s\nLift over request\nfrom: %s\nto: %s\nemail '%s'\ncomment: '%s'", nowTime, fromGenome, toGenome, email, comment);
-    /* Even if the mailViaPipe returned a relevant return code, and I'm not
-    *    sure it would, there isn't much we can do about it from here.
-    *  Do *not* need to send email from here.  The cron job watch script
-    *     in the otto user will see the table updated and take care of
-    *     the email notifications
-    (void) mailViaPipe(toAddr, "liftOver request", msg->string, fromAddr);
-    */
 
     /* some kind of response here back to the request page */
     struct jsonWrite *jw = apiStartOutput();
     jsonWriteString(jw, "msg", dyStringCannibalize(&msg));
     apiFinishOutput(0,NULL,jw);
     char *ottoTable = cfgOption("ottoTable");	/* probably ottoRequest */
     if (isNotEmpty(ottoTable))
         {
         struct sqlConnection *conn = hConnectCentral();
         if (sqlTableExists(conn, ottoTable))
 	    {
             struct dyString *update = newDyString(0);
             sqlDyStringPrintf(update,
 		"INSERT INTO %s (requestType, fromDb, toDb, email, comment, requestTime, status, buildDir) VALUES ( 'liftOver', '%s','%s','%s','%s',now(), 0, '')",
 		ottoTable,  fromGenome, toGenome, email, comment);