e6a46ac87f958486b1d1bcef8e80dcd872ad81fe
hiram
  Sat Jun 10 19:01:23 2023 -0700
adding silent google reCAPTCHA v3 function to hgUserSuggestion refs #31325

diff --git src/hg/inc/cart.h src/hg/inc/cart.h
index d784bf5..1f54169 100644
--- src/hg/inc/cart.h
+++ src/hg/inc/cart.h
@@ -1,688 +1,693 @@
 /* cart - stuff to manage variables that persist from
  * one invocation of a cgi script to another (variables
  * that are carted around).  */
 
 /* Copyright (C) 2014 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #ifndef CART_H
 #define CART_H
 
 struct cart;         // forward definition for use in trackDb.h
 
 #include "jksql.h"
 #include "errAbort.h"
 #include "dystring.h"
 #include "linefile.h"
 #include "trackDb.h"
 
 #define namedSessionDbTableConfVariable    "namedSessionDbName"
 #define defaultNamedSessionDb              "namedSessionDb"
 
 // If cgi set as CART_VAR_EMPTY, then removed from cart
 // If If cgi created new and oldVars are stored, then will be CART_VAR_EMPTY in old vars
 #define CART_VAR_EMPTY "[]"
 #define IS_CART_VAR_EMPTY(var) ((var) == NULL || sameString(var,CART_VAR_EMPTY))
 
 // A list of headers each CGI can use to control their own HTTP headers
 extern struct slPair *httpHeaders;
 
 typedef struct sqlConnection *(*DbConnector)();
 /* funtion type used to get a connection to database */
 
 typedef void (*DbDisconnect)(struct sqlConnection **pConn);
 /* function type used to cleanup a connection from database */
 
 
 struct cart
 /* A cart of settings that persist. */
    {
    struct cart *next;	/* Next in list. */
    char *userId;	/* User ID in database. */
    char *sessionId;	/* Session ID in database. */
    struct hash *hash;	/* String valued hash. */
    struct hash *exclude;	/* Null valued hash of variables not to save. */
    struct cartDb *userInfo;	/* Info on user. */
    struct cartDb *sessionInfo;	/* Info on session. */
    };
 
 INLINE char *_cartVarDbName(const char *db, const char *var)
 /* generate cart variable name that is local to an assembly database.
  * Only for use inside of cart.h.  WARNING: static return */
 {
 static char buf[PATH_LEN]; // something rather big
 safef(buf, sizeof(buf), "%s_%s", var, db);
 return buf;
 }
 
 boolean cartTablesOk(struct sqlConnection *conn);
 /* Return TRUE if cart tables are accessible (otherwise, the connection
  * doesn't do us any good). */
 
 void cartParseOverHash(struct cart *cart, char *contents);
 /* Parse cgi-style contents into a hash table.  This will *not*
  * replace existing members of hash that have same name, so we can
  * support multi-select form inputs (same var name can have multiple
  * values which will be in separate hashEl's). */
 
 struct cart *cartNew(char *userId, char *sessionId,
 	char **exclude, struct hash *oldVars);
 /* Load up cart from user & session id's.  Exclude is a null-terminated list of
  * strings to not include. oldVars is an optional hash to put in values
  * that were just overwritten by cgi-variables. */
 
 struct cart *cartOfNothing();
 /* Create a new, empty, cart with no real connection to the database. */
 
 struct cart *cartFromHash(struct hash *hash);
 /* Create a cart from hash */
 
 struct cart *cartFromCgiOnly(char *userId, char *sessionId,
 	char **exclude, struct hash *oldVars);
 /* Create a new cart that contains only CGI variables, nothing from the
  * database, and no way to write back to database either. */
 
 void cartCheckout(struct cart **pCart);
 /* Save cart to database and free it up. */
 
 void cartSaveState(struct cart *cart);
 /* Free up cart and save it to database.
  * Intended for updating cart before background CGI runs.
  * Use cartCheckout() instead. */
 
 void cartEncodeState(struct cart *cart, struct dyString *dy);
 /* Add a CGI-encoded var=val&... string of all cart variables to dy. */
 
 char *cartSessionVarName();
 /* Return name of CGI session ID variable. */
 
 char *cartSessionId(struct cart *cart);
 /* Return session id. */
 
 unsigned cartSessionRawId(struct cart *cart);
 /* Return raw session id without security key. */
 
 unsigned cartUserRawId(struct cart *cart);
 /* Return raw user id without security key. */
 
 char *cartSidUrlString(struct cart *cart);
 /* Return session id string as in hgsid=N . */
 
 char *cartUserId(struct cart *cart);
 /* Return session id. */
 
 void cartRemove(struct cart *cart, char *var);
 /* Remove variable from cart. */
 
 void cartRemoveExcept(struct cart *cart, char **except);
 /* Remove variables except those in null terminated except array
  * from cart.  Except array may be NULL in which case all
  * are removed. */
 
 struct slPair *cartVarsLike(struct cart *cart, char *wildCard);
 /* Return a slPair list of cart vars that match the wildcard */
 
 struct slPair *cartVarsWithPrefix(struct cart *cart, char *prefix);
 /* Return a slPair list of cart vars that begin with prefix */
 
 struct slPair *cartVarsWithPrefixLm(struct cart *cart, char *prefix, struct lm *lm);
 /* Return list of cart vars that begin with prefix allocated in local memory.
  * Quite a lot faster than cartVarsWithPrefix. */
 
 void cartCloneVarsWithPrefix(struct cart *cart, char *prefix, char *newPrefix);
 /* Add a copy of all vars that start with prefix to cart.  The new vars will
  * start with newPrefix instead of prefix */
 
 void cartRemoveLike(struct cart *cart, char *wildCard);
 /* Remove all variable from cart that match wildCard. */
 
 void cartRemovePrefix(struct cart *cart, char *prefix);
 /* Remove variables with given prefix from cart. */
 
 boolean cartVarExists(struct cart *cart, char *var);
 /* Return TRUE if variable is in cart. */
 
 boolean cartListVarExists(struct cart *cart, char *var);
 /* Return TRUE if a list variable is in cart (list may still be empty). */
 
 INLINE boolean cartVarExistsDb(struct cart *cart, char *db, char *var)
 /* Return TRUE if variable_$db is in cart. */
 {
 return cartVarExists(cart, _cartVarDbName(db, var));
 }
 
 char *cartString(struct cart *cart, char *var);
 /* Return string valued cart variable. */
 
 INLINE char *cartStringDb(struct cart *cart, char *db, char *var)
 /* Return string valued cart var_$db. */
 {
 return cartString(cart, _cartVarDbName(db, var));
 }
 
 char *cartOptionalString(struct cart *cart, char *var);
 /* Return string valued cart variable or NULL if it doesn't exist. */
 
 INLINE char *cartOptionalStringDb(struct cart *cart, char *db, char *var)
 /* Return string valued cart variable_$db or NULL if it doesn't exist. */
 {
 return cartOptionalString(cart, _cartVarDbName(db, var));
 }
 
 char *cartNonemptyString(struct cart *cart, char *name);
 /* Return string value associated with name.  Return NULL
  * if value doesn't exist or if it is pure white space. */
 
 INLINE char *cartNonemptyStringDb(struct cart *cart, char *db, char *name)
 /* Return string value associated with name_$db.  Return NULL
  * if value doesn't exist or if it is pure white space. */
 {
 return cartNonemptyString(cart, _cartVarDbName(db, name));
 }
 
 char *cartUsualString(struct cart *cart, char *var, char *usual);
 /* Return variable value if it exists or usual if not. */
 
 INLINE char *cartUsualStringDb(struct cart *cart, char *db, char *var, char *usual)
 /* Return var_$db value if it exists or usual if not. */
 {
 return cartUsualString(cart, _cartVarDbName(db, var), usual);
 }
 
 char *cartCgiUsualString(struct cart *cart, char *var, char *usual);
 /* Look for var in CGI, then in cart, if not found then return usual. */
 
 struct slName *cartOptionalSlNameList(struct cart *cart, char *var);
 /* Return slName list (possibly with multiple values for the same var) or
  * NULL if not found. */
 
 struct hash *cartHashList(struct cart *cart, char *var);
 /* Return hash with multiple values for the same var or NULL if not found. */
 
 void cartAddString(struct cart *cart, char *var, char *val);
 /* Add string valued cart variable (if called multiple times on same var,
  * will create a list -- retrieve with cartOptionalSlNameList. */
 
 void cartSetString(struct cart *cart, char *var, char *val);
 /* Set string valued cart variable. */
 
 INLINE void cartSetStringDb(struct cart *cart, char *db, char *var, char *val)
 /* Set string valued cart var_$db. */
 {
 cartSetString(cart, _cartVarDbName(db, var), val);
 }
 
 int cartInt(struct cart *cart, char *var);
 /* Return int valued variable. */
 
 INLINE int cartIntDb(struct cart *cart, char *db, char *var)
 /* Return int valued variable_$db. */
 {
 return cartInt(cart, _cartVarDbName(db, var));
 }
 
 
 int cartIntExp(struct cart *cart, char *var);
 /* Return integer valued expression in variable. */
 
 int cartUsualInt(struct cart *cart, char *var, int usual);
 /* Return variable value if it exists or usual if not. */
 
 INLINE int cartUsualIntDb(struct cart *cart, char *db, char *var, int usual)
 /* Return variable_$db value if it exists or usual if not. */
 {
 return cartUsualInt(cart, _cartVarDbName(db, var), usual);
 }
 
 int cartUsualIntClipped(struct cart *cart, char *var, int usual,
 	int minVal, int maxVal);
 /* Return integer variable clipped to lie between minVal/maxVal */
 
 int cartCgiUsualInt(struct cart *cart, char *var, int usual);
 /* Look for var in CGI, then in cart, if not found then return usual. */
 
 void cartSetInt(struct cart *cart, char *var, int val);
 /* Set integer value. */
 
 INLINE void cartSetIntDb(struct cart *cart, char *db, char *var, int val)
 /* Set integer value for var_$db. */
 {
 cartSetInt(cart, _cartVarDbName(db, var), val);
 }
 
 double cartDouble(struct cart *cart, char *var);
 /* Return double valued variable. */
 
 INLINE double cartDoubleDb(struct cart *cart, char *db, char *var)
 /* Return double valued var_$db. */
 {
 return cartDouble(cart, _cartVarDbName(db, var));
 }
 
 double cartUsualDouble(struct cart *cart, char *var, double usual);
 /* Return variable value if it exists or usual if not. */
 
 INLINE double cartUsualDoubleDb(struct cart *cart, char *db, char *var, double usual)
 /* Return var_$db value if it exists or usual if not. */
 {
 return cartUsualDouble(cart, _cartVarDbName(db, var), usual);
 }
 
 double cartCgiUsualDouble(struct cart *cart, char *var, double usual);
 /* Look for var in CGI, then in cart, if not found then return usual. */
 
 void cartSetDouble(struct cart *cart, char *var, double val);
 /* Set double value. */
 
 INLINE void cartSetDoubleDb(struct cart *cart, char *db, char *var, double val)
 /* Set double value for var_$db. */
 {
 cartSetDouble(cart, _cartVarDbName(db, var), val);
 }
 
 boolean cartBoolean(struct cart *cart, char *var);
 /* Retrieve cart boolean. */
 
 INLINE boolean cartBooleanDb(struct cart *cart, char *db, char *var)
 /* Retrieve cart boolean for var_$db. */
 {
 return cartBoolean(cart, _cartVarDbName(db, var));
 }
 
 boolean cartUsualBoolean(struct cart *cart, char *var, boolean usual);
 /* Return variable value if it exists or usual if not.  */
 
 INLINE boolean cartUsualBooleanDb(struct cart *cart, char *db, char *var, boolean usual)
 /* Return var_$db value if it exists or usual if not.  */
 {
 return cartUsualBoolean(cart, _cartVarDbName(db, var), usual);
 }
 
 boolean cartCgiUsualBoolean(struct cart *cart, char *var, boolean usual);
 /* Look for var in CGI, then in cart, if not found then return usual. */
 
 void cartSetBoolean(struct cart *cart, char *var, boolean val);
 /* Set boolean value. */
 
 INLINE void cartSetBooleanDb(struct cart *cart, char *db, char *var, boolean val)
 /* Set boolean value for $var_db. */
 {
 cartSetBoolean(cart, _cartVarDbName(db, var), val);
 }
 
 void cartMakeTextVar(struct cart *cart, char *var, char *defaultVal, int charSize);
 /* Make a text control filled with value from cart if it exists or
  * default value otherwise.  If charSize is zero it's calculated to fit
  * current value.  Default value may be NULL. */
 
 void cartMakeIntVar(struct cart *cart, char *var, int defaultVal, int maxDigits);
 /* Make a text control filled with integer value - from cart if available
  * otherwise default.  */
 
 void cartMakeDoubleVar(struct cart *cart, char *var, double defaultVal, int maxDigits);
 /* Make a text control filled with integer value - from cart if available
  * otherwise default.  */
 
 void cartMakeCheckBox(struct cart *cart, char *var, boolean defaultVal);
 /* Make a check box filled with value from cart if it exists or
  * default value otherwise.  */
 
 void cartMakeRadioButton(struct cart *cart, char *var, char *val, char *defaultVal);
 /* Make a radio button that is selected if cart variable exists and matches
  * value (or value matches default val if cart var doesn't exist). */
 
 void cartSaveSession(struct cart *cart);
 /* Save session in a hidden variable. This needs to be called
  * somewhere inside of form or bad things will happen. */
 
 void cartDump(struct cart *cart);
 /* Dump contents of cart with anti-XSS HTML encoding. */
 
 void cartDumpHgSession(struct cart *cart);
 /* Dump contents of cart with escaped newlines for hgSession output files.
  * Cart variable "cartDumpAsTable" is ignored. */
 
 #define CART_DUMP_AS_TABLE "cartDumpAsTable"
 
 void cartDumpPrefix(struct cart *cart, char *prefix);
 /* Dump all cart variables with prefix */
 
 void cartDumpLike(struct cart *cart, char *wildcard);
 /* Dump all cart variables matching wildcard */
 
 struct hashEl *cartFindPrefix(struct cart *cart, char *prefix);
 /* Return list of name/val pairs from cart where name starts with
  * prefix.  Free when done with hashElFreeList. */
 
 struct hashEl *cartFindLike(struct cart *cart, char *wildCard);
 /* Return list of name/val pairs from cart where name matches
  * wildcard.  Free when done with hashElFreeList. */
 
 char *cartFindFirstLike(struct cart *cart, char *wildCard);
 /* Find name of first variable that matches wildCard in cart.
  * Return NULL if none. */
 
 void cartResetInDb(char *cookieName);
 /* Clear cart in database. */
 
 void cartEarlyWarningHandler(char *format, va_list args);
 /* Write an error message so user can see it before page is really started */
 
 void cartWarnCatcher(void (*doMiddle)(struct cart *cart), struct cart *cart, WarnHandler warner);
 /* Wrap error and warning handlers around doMiddl. */
 
 void cartEmptyShell(void (*doMiddle)(struct cart *cart), char *cookieName,
 	char **exclude, struct hash *oldVars);
 /* Get cart and cookies and set up error handling, but don't start writing any
  * html yet. The doMiddleFunction has to call cartHtmlStart(title), and
  * cartHtmlEnd(), as well as writing the body of the HTML.
  * oldVars - those in cart that are overlayed by cgi-vars are
  * put in optional hash oldVars. */
 
 void cartEmptyShellNoContent(void (*doMiddle)(struct cart *cart), char *cookieName,
                              char **exclude, struct hash *oldVars);
 /* Get cart and cookies and set up error handling.
  * The doMiddle function must write the Content-Type header line.
  * oldVars - those in cart that are overlayed by cgi-vars are
  * put in optional hash oldVars. */
 
 void cartHtmlStart(char *title);
 /* Write HTML header and put in normal error handler. Needed with cartEmptyShell,
  * but not cartHtmlShell. */
 
 void cartFooter(void);
 /* Write out HTML footer, possibly with googleAnalytics too */
 
 void cartHtmlEnd();
 /* Write out HTML footer and get rid or error handler. Needed with cartEmptyShell,
  * but not cartHtmlShell. */
 
 void cartWebStart(struct cart *theCart, char *db, char *format, ...)
 /* Print out pretty wrapper around things when working
  * from cart. Balance this with cartWebEnd. */
 #if defined(__GNUC__)
 __attribute__((format(printf, 3, 4)))
 #endif
 ;
 
 void cartVaWebStart(struct cart *cart, char *db, char *format, va_list args);
 /* Print out pretty wrapper around things when working
  * from cart. */
 
 void cartWebStartHeader(struct cart *cart, char *db, char *format, ...);
 /* Print out Content-type header and then pretty wrapper around things when working
  * from cart. */
 
 void cartWebEnd();
 /* End out pretty wrapper around things when working
  * from cart. */
 
+void cartWebEndExtra(char *footer);
+/* Write out HTML footer and get rid or error handler, with extra text
+ * at the end of the page as desired.
+ */
+
 void cartHtmlShellWithHead(char *head, char *title, void (*doMiddle)(struct cart *cart),
         char *cookieName, char **exclude, struct hash *oldVars);
 /* Load cart from cookie and session cgi variable.  Write web-page
  * preamble including head and title, call doMiddle with cart, and write end of web-page.
  * Exclude may be NULL.  If it exists it's a comma-separated list of
  * variables that you don't want to save in the cart between
  * invocations of the cgi-script. */
 
 void cartHtmlShell(char *title, void (*doMiddle)(struct cart *cart),
 	char *cookieName, char **exclude, struct hash *oldVars);
 /* Load cart from cookie and session cgi variable.  Write web-page preamble, call doMiddle
  * with cart, and write end of web-page.   Exclude may be NULL.  If it exists it's a
  * comma-separated list of variables that you don't want to save in the cart between
  * invocations of the cgi-script. oldVars is an optional hash that will get values
  * of things in the cart that were overwritten by cgi-variables. */
 
 void cartWriteCookie(struct cart *cart, char *cookieName);
 /* Write out HTTP Set-Cookie statement for cart. */
 
 struct cart *cartAndCookie(char *cookieName, char **exclude,
 	struct hash *oldVars);
 /* Load cart from cookie and session cgi variable.  Write cookie and
  * content-type part HTTP preamble to web page.  Don't write any HTML though. */
 
 struct cart *cartAndCookieNoContent(char *cookieName, char **exclude,
 	struct hash *oldVars);
 /* Load cart from cookie and session cgi variable. Don't write out
  * content type or any HTML. */
 
 struct cart *cartAndCookieWithHtml(char *cookieName, char **exclude,
 	struct hash *oldVars, boolean doContentType);
 /* Load cart from cookie and session cgi variable.  Write cookie
  * and optionally content-type part HTTP preamble to web page.  Don't
  * write any HTML though. */
 
 struct cart *cartForSession(char *cookieName, char **exclude,
 	struct hash *oldVars);
 /* This gets the cart without writing any HTTP lines at all to stdout. */
 
 void cartSetDbConnector(DbConnector connector);
 /* Set the connector that will be used by the cart to connect to the
  * database. Default connector is hConnectCart */
 
 void cartSetDbDisconnector(DbDisconnect disconnector);
 /* Set the connector that will be used by the cart to disconnect from the
  * database. Default disconnector is hDisconnectCart */
 
 
 /* Libified constants and code that originally belonged only to hgSession
  * (now hgTracks uses them too), plus a couple for DataTables in hgSession
  * and hgPublicSessions: */
 #define hgSessionPrefix "hgS_"
 #define hgPublicSessionsPrefix "hgPS_"
 #define dataTableStateName "DataTableState"
 #define hgSessionTableState hgSessionPrefix dataTableStateName
 #define hgPublicSessionsTableState hgPublicSessionsPrefix dataTableStateName
 
 #define hgsOtherUserName hgSessionPrefix "otherUserName"
 #define hgsOtherUserSessionName hgSessionPrefix "otherUserSessionName"
 #define hgsMergeCart hgSessionPrefix "merge"
 #define hgsOtherUserSessionLabel hgSessionPrefix "otherUserSessionLabel"
 #define hgsDoOtherUser hgSessionPrefix "doOtherUser"
 
 #define hgsLoadUrlName hgSessionPrefix "loadUrlName"
 #define hgsDoLoadUrl hgSessionPrefix "doLoadUrl"
 
 #define namedSessionTable cartNamedSessionDbTable()
 
 void sessionTouchLastUse(struct sqlConnection *conn, char *encUserName,
 			 char *encSessionName);
 /* Increment namedSessionDb.useCount and update lastUse for this session. */
 
 void cartLoadUserSession(struct sqlConnection *conn, char *sessionOwner,
 			 char *sessionName, struct cart *cart,
 			 struct hash *oldVars, char *actionVar);
 /* If permitted, load the contents of the given user's session, and then
  * reload the CGI settings (to support override of session settings).
  * If non-NULL, oldVars will contain values overloaded when reloading CGI.
  * If non-NULL, actionVar is a cartRemove wildcard string specifying the
  * CGI action variable that sent us here. */
 
 boolean cartLoadSettingsFromUserInput(struct lineFile *lf, struct cart *cart, struct hash *oldVars,
                                       char *actionVar, struct dyString *dyMessage);
 /* Verify that the user data in lf looks like valid settings (hgSession saved file;
  * like cartDump output, but values may or may not be htmlEncoded).
  * Older session files may have unencoded newlines, causing bogus variables;
  * watch out for those after pasted input variables like hgta_pastedIdentifiers.
  * Users have uploaded custom tracks, DTC genotypes, hgTracks HTML, even
  * binary data files.  Look for problematic patterns observed in the past.
  * Load settings into current session, and then reload the CGI settings
  * (to support override of session settings).
  * If non-NULL, oldVars will contain values overloaded when reloading CGI.
  * If non-NULL, actionVar is a cartRemove wildcard string specifying the
  * CGI action variable that sent us here.
  * If input contains suspect data, then add diagnostics to dyMessage.  If input
  * contains so much garbage that we shouldn't even try to load what passes the filters,
  * return FALSE. */
 
 char *cartGetOrderFromFile(char *genomeDb, struct cart *cart, char *speciesUseFile);
 /* Look in a cart variable that holds the filename that has a list of
  * species to show in a maf file */
 
 char *cartGetOrderFromFileAndMsaTable(char *genomeDb, struct cart *cart, char *speciesUseFile, char *msaTable);
 /* Look in a cart variable that holds the filename that has a list of
  * species to show in a maf file */
 
 char *cartLookUpVariableClosestToHome(struct cart *cart, struct trackDb *tdb,
                                       boolean parentLevel, char *suffix,char **pVariable);
 /* Returns value or NULL for a cart variable from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix
    Optionally fills the non NULL pVariable with the actual name of the variable in the cart */
 #define cartOptionalStringClosestToHome(cart,tdb,parentLevel,suffix) \
         cartLookUpVariableClosestToHome((cart),(tdb),(parentLevel),(suffix),NULL)
 
 void cartRemoveVariableClosestToHome(struct cart *cart, struct trackDb *tdb,
                                      boolean parentLevel, char *suffix);
 /* Looks for then removes a cart variable from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 char *cartStringClosestToHome(struct cart *cart, struct trackDb *tdb,
                               boolean parentLevel, char *suffix);
 /* Returns value or Aborts for a cart string from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 boolean cartVarExistsAnyLevel(struct cart *cart, struct trackDb *tdb,
                               boolean parentLevel, char *suffix);
 /* Returns TRUE if variable exists anywhere, looking from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 boolean cartListVarExistsAnyLevel(struct cart *cart, struct trackDb *tdb,
 				  boolean parentLevel, char *suffix);
 /* Return TRUE if a list variable for tdb->track (or tdb->parent->track,
  * or tdb->parent->parent->track, etc.) is in cart (list itself may be NULL). */
 
 char *cartUsualStringClosestToHome(struct cart *cart, struct trackDb *tdb, boolean parentLevel,
                                    char *suffix, char *usual);
 /* Returns value or {usual} for a cart string from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 boolean cartBooleanClosestToHome(struct cart *cart, struct trackDb *tdb,
                                  boolean parentLevel, char *suffix);
 /* Returns value or Aborts for a cart boolean ('on' or != 0) from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 boolean cartUsualBooleanClosestToHome(struct cart *cart, struct trackDb *tdb,
                                       boolean parentLevel, char *suffix,boolean usual);
 /* Returns value or {usual} for a cart boolean ('on' or != 0) from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 int cartUsualIntClosestToHome(struct cart *cart, struct trackDb *tdb,
                               boolean parentLevel, char *suffix, int usual);
 /* Returns value or {usual} for a cart int from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 double cartUsualDoubleClosestToHome(struct cart *cart, struct trackDb *tdb,
                                     boolean parentLevel, char *suffix, double usual);
 /* Returns value or {usual} for a cart fp double from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 struct slName *cartOptionalSlNameListClosestToHome(struct cart *cart, struct trackDb *tdb,
                                                    boolean parentLevel, char *suffix);
 /* Return slName list (possibly with multiple values for the same var) from lowest level on up:
    subtrackName.suffix, then compositeName.view.suffix, then compositeName.suffix */
 
 void cartRemoveAllForTdb(struct cart *cart, struct trackDb *tdb);
 /* Remove all variables from cart that are associated with this tdb. */
 
 void cartRemoveAllForTdbAndChildren(struct cart *cart, struct trackDb *tdb);
 /* Remove all variables from cart that are associated
    with this tdb and it's children. */
 
 char *cartOrTdbString(struct cart *cart, struct trackDb *tdb, char *var, char *defaultVal);
 /* Look first in cart, then in trackDb for var.  Return defaultVal if not found. */
 
 int cartOrTdbInt(struct cart *cart, struct trackDb *tdb, char *var, int defaultVal);
 /* Look first in cart, then in trackDb for var.  Return defaultVal if not found. */
 
 double cartOrTdbDouble(struct cart *cart, struct trackDb *tdb, char *var, double defaultVal);
 /* Look first in cart, then in trackDb for var.  Return defaultVal if not found. */
 
 boolean cartOrTdbBoolean(struct cart *cart, struct trackDb *tdb, char *var, boolean defaultVal);
 /* Look first in cart, then in trackDb for var.  Return defaultVal if not found. */
 
 boolean cartValueHasChanged(struct cart *newCart,struct hash *oldVars,char *setting,
                             boolean ignoreRemoved,boolean ignoreCreated);
 /* Returns TRUE if new cart setting has changed from old cart setting */
 
 int cartRemoveFromTdbTree(struct cart *cart,struct trackDb *tdb,char *suffix,boolean skipParent);
 /* Removes a 'trackName.suffix' from all tdb descendents (but not parent).
    If suffix NULL then removes 'trackName' which holds visibility */
 
 boolean cartTdbTreeReshapeIfNeeded(struct cart *cart,struct trackDb *tdbComposite);
 /* When subtrack vis is set via findTracks, and composite has no cart settings,
    then fashion composite to match found */
 
 boolean cartTdbTreeCleanupOverrides(struct trackDb *tdb,struct cart *newCart,struct hash *oldVars, struct lm *lm);
 /* When composite/view settings changes, remove subtrack specific settings
    Returns TRUE if any cart vars are removed */
 
 void cartCopyCustomComposites(struct cart *cart);
 /* Find any custom composite hubs and copy them so they can be modified. */
 
 void cartReplaceHubVars(struct cart *cart, char *hubFileVar, char *oldHubUrl, char *newHubUrl);
 /* Replace all cart variables corresponding to oldHubUrl (and/or its hub ID) with
  * equivalents for newHubUrl. */
 
 void cgiExitTime(char *cgiName, long enteredMainTime);
 /* single stderr print out called at end of CGI binaries to record run
  * time in apache error_log */
 
 void cartHubWarn(char *format, va_list args);
 /* save up hub related warnings to put out later */
 
 void cartFlushHubWarnings();
 /* flush the hub errors (if any) */
 
 void cartCheckForCustomTracks(struct cart *cart, struct dyString *dyMessage);
 /* Scan cart for ctfile_<db> variables.  Tally up the databases that have
  * live custom tracks and those that have expired custom tracks. */
 /* While we're at it, also look for saved blat results. */
 
 #define CART_HAS_DEFAULT_VISIBILITY "defaultsSet"
 
 extern void cartHideDefaultTracks(struct cart *cart);
 /* Hide all the tracks who have default visibilities in trackDb
  * that are something other than hide.  Do this only if the
  * variable CART_HAS_DEFAULT_VISIBILITY is set in the cart.  */
 
 char *cartGetPosition(struct cart *cart, char *database, struct cart **pLastDbPosCart);
 /* get the current position in cart as a string chr:start-end.
  * This can handle the special CGI params 'default' and 'lastDbPos'
  * Returned value has to be freed. Returns default position of assembly 
  * if no position set in cart nor as CGI var.
  * For virtual modes, returns the type and extraState. 
 */
 
 void cartSetDbPosition(struct cart *cart, char *database, struct cart *lastDbPosCart);
 /* Set the 'position.db' variable in the cart.*/
 
 void cartSetLastPosition(struct cart *cart, char *position, struct hash *oldVars);
 /* If position and oldVars are non-NULL, and oldVars' position is different, add it to the cart
  * as lastPosition.  This is called by cartHtmlShell{,WithHead} but not other cart openers;
  * it should be called after cartGetPosition or equivalent. */
 
 void cartTdbFetchMinMaxPixels(struct cart *theCart, struct trackDb *tdb,
                                 int defaultMin, int defaultMax, int defaultDefault,
                                 int *retMin, int *retMax, int *retDefault, int *retCurrent);
 /* Configure maximum track height for variable height tracks (e.g. wiggle, barchart)
  *      Initial height and limits may be defined in trackDb with the maxHeightPixels string,
  *      Or user requested limits are defined in the cart. */
 
 unsigned cartGetVersion(struct cart *cart);
 /* Get the current version of the cart, which is stored in the variable "cartVersion" */
 
 void cartSetVersion(struct cart *cart, unsigned version);
 /* Set the current version of the cart, which is stored in the variable "cartVersion" */
 
 void cartRewrite(struct cart *cart, unsigned trackDbCartVersion, unsigned cartVersion);
 /* Rewrite the cart to update it to expectations of trackDb. */
 
 void cartTurnOnSuper(struct cart *cart, char **trackNames, unsigned numTracks, char *superTrackName);
 /* Turn on a supertrack if any of the subtracks are not hidden.  ASSUMES ALL TRACKS ARE HIDDEN
  * by default.
  */
 
 char *cartNamedSessionDbTable();
 /* Get the name of the table that lists named sessions.  Don't free the result. */
 #endif /* CART_H */