080a160c7b9595d516c9c70e83689a09b60839d0
galt
  Mon Jun 3 12:16:53 2013 -0700
fix SQL Injection
diff --git src/hg/hgc/pubs.c src/hg/hgc/pubs.c
index 09d4642..c4fd801 100644
--- src/hg/hgc/pubs.c
+++ src/hg/hgc/pubs.c
@@ -211,31 +211,31 @@
 long size = end - start;
 sprintLongWithCommas(startBuf, size);
 if (showSize)
     printf("<B>Genomic Size:</B>&nbsp;%s<BR>\n", startBuf);
 }
 
 static void printFilterLink(char *pslTrack, char *articleId, char *articleTable)
 /* print a link to hgTracks with an additional cgi param to activate the single article filter */
 {
     int start = cgiOptionalInt("o", -1);
     if (start==-1)
         return;
     int end = cgiInt("t");
     char qBuf[1024];
     struct sqlConnection *conn = hAllocConn(database);
-    safef(qBuf, sizeof(qBuf), "SELECT CONCAT(firstAuthor, year) FROM %s WHERE articleId='%s';", articleTable, articleId);
+    sqlSafef(qBuf, sizeof(qBuf), "SELECT CONCAT(firstAuthor, year) FROM %s WHERE articleId='%s';", articleTable, articleId);
     char *dispId = sqlQuickString(conn, qBuf);
 
     printf(
         "      <div class=\"subsection\">");
     printf(
         "      <P><A HREF=\"%s&amp;db=%s&amp;position=%s%%3A%d-%d&amp;pubsFilterArticleId=%s&amp;%s=pack&amp;hgFind.matches=%s\">",
         hgTracksPathAndSettings(), database, seqName, start+1, end, articleId, pslTrack, dispId);
 
     printf("Show these sequence matches individually on genome browser</A> (activates track \""
         "Individual matches for article\")</P>");
 
     printPositionAndSize(start, end, 1);
     printf(
         "      </div> <!-- class: subsection --> \n");
     hFreeConn(&conn);
@@ -263,33 +263,33 @@
 if (names==0)
     errAbort("You need to specify at least one article section.");
 
 char *nameListString = slNameListToString(names, ',');
 slNameFree(names);
 return nameListString;
 }
 
 
 static struct sqlResult *queryMarkerRows(struct sqlConnection *conn, char *markerTable, \
     char *articleTable, char *item, int itemLimit, char *sectionList)
 /* query marker rows from mysql, based on http parameters  */
 {
 char query[4000];
 /* Mysql specific setting to make the group_concat function return longer strings */
-sqlUpdate(conn, "SET SESSION group_concat_max_len = 100000");
+sqlUpdate(conn, "NOSQLINJ SET SESSION group_concat_max_len = 100000");
 
-safef(query, sizeof(query), "SELECT distinct %s.articleId, url, title, authors, citation, "  
+sqlSafef(query, sizeof(query), "SELECT distinct %s.articleId, url, title, authors, citation, "  
     "pmid, extId, "
     "group_concat(snippet, concat(\" (section: \", section, \")\") SEPARATOR ' (...) ') FROM %s "
     "JOIN %s USING (articleId) "
     "WHERE markerId='%s' AND section in (%s) "
     "GROUP by articleId "
     "ORDER BY year DESC "
     "LIMIT %d",
     markerTable, markerTable, articleTable, item, sectionList, itemLimit);
 
 if (pubsDebug)
     printf("%s", query);
 
 struct sqlResult *sr = sqlGetResult(conn, query);
 
 return sr;
@@ -332,31 +332,31 @@
 
 printf("<INPUT TYPE=\"hidden\" name=\"o\" value=\"%s\" />\n", cgiString("o"));
 printf("<INPUT TYPE=\"hidden\" name=\"g\" value=\"%s\" />\n", cgiString("g"));
 printf("<INPUT TYPE=\"hidden\" name=\"t\" value=\"%s\" />\n", cgiString("t"));
 printf("<INPUT TYPE=\"hidden\" name=\"i\" value=\"%s\" />\n", cgiString("i"));
 printf("<INPUT TYPE=\"hidden\" name=\"hgsid\" value=\"%d\" />\n", cart->sessionId);
 printf("<BR>");
 printf("<INPUT TYPE=\"submit\" VALUE=\"Submit\" />\n");
 printf("</FORM><P>\n");
 }
 
 static void printLimitWarning(struct sqlConnection *conn, char *markerTable, 
     char *item, int itemLimit, char *sectionList)
 {
 char query[4000];
-safef(query, sizeof(query), "SELECT COUNT(*) from %s WHERE markerId='%s' AND section in (%s) ", markerTable, item, sectionList);
+sqlSafef(query, sizeof(query), "SELECT COUNT(*) from %s WHERE markerId='%s' AND section in (%s) ", markerTable, item, sectionList);
 if (sqlNeedQuickNum(conn, query) > itemLimit) 
 {
     printf("<b>This marker is mentioned more than %d times</b><BR>\n", itemLimit);
     printf("The results would take too long to load in your browser and are "
     "therefore limited to %d articles.<P>\n", itemLimit);
 }
 }
 
 static void printMarkerSnippets(struct sqlConnection *conn, char *articleTable, char *markerTable, char *item)
 {
 
 /* do not show more snippets than this limit */
 int itemLimit=100;
 
 printSectionCheckboxes();
@@ -391,31 +391,31 @@
 
 freeMem(sectionList);
 sqlFreeResult(&sr);
 }
 
 static char *urlToLogoUrl(char *pubsArticleTable, char *articleId, char *urlOrig)
 /* return a string with relative path of logo for publisher given the url of
  * fulltext or a table/articleId, has to be freed 
 */
 {
 struct sqlConnection *conn = hAllocConn(database);
 char *pubCode = NULL;
 if (hHasField("hgFixed", pubsArticleTable, "publisher"))
     {
     char query[4000];
-    safef(query, sizeof(query), "SELECT publisher from %s where articleId=%s", 
+    sqlSafef(query, sizeof(query), "SELECT publisher from %s where articleId=%s", 
         pubsArticleTable, articleId);
     pubCode = sqlQuickString(conn, query);
     }
 else 
     {
     // get top-level domain url if not publisher field
     char url[1024];
     memcpy(url, urlOrig, sizeof(url));
     char *slashParts[20];
     // split http://www.sgi.com/test -> to [http:,www.sgi.com,test]
     int partCount = chopString(url, "/", slashParts, ArraySize(slashParts));
     if (partCount<3)
         return NULL;
     // split www.sgi.com to [www,sgi,com]
     char *dotParts[20];
@@ -424,31 +424,31 @@
         return NULL;
     pubCode = dotParts[partCount-2];
     }
     
 // construct path to image
 char *logoUrl = needMem(512);
 safef(logoUrl, 512, "../images/pubs_%s.png", pubCode);
 return logoUrl;
 }
 
 static char *printArticleInfo(struct sqlConnection *conn, char *item, char *pubsArticleTable)
 /* Header with information about paper, return documentId */
 {
 char query[512];
 
-safef(query, sizeof(query), "SELECT articleId, url, title, authors, citation, abstract, pmid, "
+sqlSafef(query, sizeof(query), "SELECT articleId, url, title, authors, citation, abstract, pmid, "
     "source, extId FROM %s WHERE articleId='%s'", pubsArticleTable, item);
 
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row;
 char *articleId=NULL;
 if ((row = sqlNextRow(sr)) == NULL)
     {
     printf("Could not resolve articleId %s, this is an internal error.\n", item);
     printf("Please send an email to max@soe.ucsc.edu\n");
     sqlFreeResult(&sr);
     return NULL;
     }
 
 articleId = cloneString(row[0]);
 char *url      = row[1];
@@ -496,38 +496,38 @@
 if (pubsIsElsevier)
     printf("<P><SMALL>Copyright 2012 Elsevier B.V. All rights reserved.</SMALL></P>");
 
 sqlFreeResult(&sr);
 return articleId;
 }
 
 static struct hash *getSeqIdHash(struct sqlConnection *conn, char *trackTable, \
     char *articleId, char *item, char *seqName, int start)
 /* return a hash with the sequence IDs for a given chain of BLAT matches */
 {
 if (start==-1)
     return NULL;
 char query[512];
 /* check first if the column exists (some debugging tables on hgwdev don't have seqIds) */
-safef(query, sizeof(query), "SHOW COLUMNS FROM %s LIKE 'seqIds';", trackTable);
+sqlSafef(query, sizeof(query), "SHOW COLUMNS FROM %s LIKE 'seqIds';", trackTable);
 char *seqIdPresent = sqlQuickString(conn, query);
 if (!seqIdPresent) {
     return NULL;
 }
 
 /* get sequence-Ids for feature that was clicked (item&startPos are unique) and return as hash*/
-safef(query, sizeof(query), "SELECT seqIds,'' FROM %s WHERE name='%s' "
+sqlSafef(query, sizeof(query), "SELECT seqIds,'' FROM %s WHERE name='%s' "
     "and chrom='%s' and chromStart=%d;", trackTable, item, seqName, start);
 if (pubsDebug)
     printf("%s<br>", query);
 
 // split comma-sep list into parts
 char *seqIdCoordString = sqlQuickString(conn, query);
 char *seqIdCoords[1024];
 if (isEmpty(seqIdCoordString))
     return NULL;
 int partCount = chopString(seqIdCoordString, ",", seqIdCoords, ArraySize(seqIdCoords));
 int i;
 
 struct hash *seqIdHash = NULL;
 seqIdHash = newHash(0);
 for (i=0; i<partCount; i++) 
@@ -684,31 +684,31 @@
  *   - other seqs (isClickedSection=False) -> show all other seqs
  * 
  * */
 {
 // get data from mysql
 // I support two different schemas: new and old. On old tables, there is no fileUrl yet on the annotations
 // that means that oldQuery just uses an empty string for the fileUrl field.
 char *oldQuery = "SELECT fileDesc, snippet, locations, annotId, sequence, \"\" FROM %s WHERE articleId='%s'";
 char *newQuery = "SELECT fileDesc, snippet, locations, annotId, sequence, fileUrl FROM %s WHERE articleId='%s'";
 
 char *queryTemplate = oldQuery;
 if (hHasField("hgFixed", pubsSequenceTable, "fileUrl"))
     queryTemplate = newQuery;
 
 char query[4096];
-safef(query, sizeof(query), queryTemplate, pubsSequenceTable, articleId);
+sqlSafef(query, sizeof(query), queryTemplate, pubsSequenceTable, articleId);
 if (pubsDebug)
     puts(query);
 struct sqlResult *sr = sqlGetResult(conn, query);
 
 // construct title for section
 char *otherFormat = NULL;
 if (fasta)
     otherFormat = "table";
 else
     otherFormat = "fasta";
 
 char fullTitle[5000];
 safef(fullTitle, sizeof(fullTitle), 
 "%s&nbsp;<A HREF=\"../cgi-bin/hgc?%s&o=%s&t=%s&g=%s&i=%s&fasta=%d\"><SMALL>(%s format)</SMALL></A>\n", 
 title, cartSidUrlString(cart), cgiOptionalString("o"), cgiOptionalString("t"), cgiString("g"), cgiString("i"), 
@@ -874,31 +874,31 @@
     }
 freeHash(&clickedSeqs);
 }
 
 static void printTrackVersion(struct trackDb *tdb, struct sqlConnection *conn, char *item) 
 {
 char versionString[256];
 char dateReference[256];
 char headerTitle[512];
 /* see if hgFixed.trackVersion exists */
 boolean trackVersionExists = hTableExists("hgFixed", "trackVersion");
 
 if (trackVersionExists)
     {
     char query[256];
-    safef(query, sizeof(query), \
+    sqlSafef(query, sizeof(query), \
     "SELECT version,dateReference FROM hgFixed.trackVersion "
     "WHERE db = '%s' AND name = 'pubs' ORDER BY updateTime DESC limit 1", database);
     struct sqlResult *sr = sqlGetResult(conn, query);
     char **row;
 
     /* in case of NULL result from the table */
     versionString[0] = 0;
     while ((row = sqlNextRow(sr)) != NULL)
         {
         safef(versionString, sizeof(versionString), "version %s",
             row[0]);
         safef(dateReference, sizeof(dateReference), "%s",
             row[1]);
         }
     sqlFreeResult(&sr);
@@ -912,31 +912,31 @@
 if (versionString[0])
     safef(headerTitle, sizeof(headerTitle), "%s - %s", item, versionString);
 else
     safef(headerTitle, sizeof(headerTitle), "%s", item);
 
 genericHeader(tdb, headerTitle);
 }
 
 static bioSeq *getSeq(struct sqlConnection *conn, char *table, char *id)
 /* copied from otherOrgs.c */
 {
 char query[512];
 struct sqlResult *sr;
 char **row;
 bioSeq *seq = NULL;
-safef(query, sizeof(query), 
+sqlSafef(query, sizeof(query), 
     "select sequence from %s where annotId = '%s'", table, id);
 sr = sqlGetResult(conn, query);
 if ((row = sqlNextRow(sr)) != NULL)
     {
     AllocVar(seq);
     seq->name = cloneString(id);
     seq->dna = cloneString(row[0]);
     seq->size = strlen(seq->dna);
     }
 sqlFreeResult(&sr);
 
 return seq;
 }
 
 void pubsAli(struct sqlConnection *conn, char *pslTable, char *seqTable, char *item)