080a160c7b9595d516c9c70e83689a09b60839d0
galt
  Mon Jun 3 12:16:53 2013 -0700
fix SQL Injection
diff --git src/hg/hgTracks/pubsTracks.c src/hg/hgTracks/pubsTracks.c
index 0c57cd3..655d85b 100644
--- src/hg/hgTracks/pubsTracks.c
+++ src/hg/hgTracks/pubsTracks.c
@@ -59,31 +59,31 @@
 /* assignment of pubs classes to colors */
 static struct hash* pubsClassColors = NULL;
 
 static void pubsParseClassColors() 
 /* parse class colors from hgFixed.pubsClassColors into the hash pubsClassColors */
 {
 if (pubsClassColors!=NULL)
     return;
 
 pubsClassColors = hashNew(0);
 struct sqlConnection *conn = hAllocConn(database);
 if (!sqlTableExists(conn, "hgFixed.pubsClassColors")) 
     {
     return;
     }
-char *query = "SELECT class, rgbColor FROM hgFixed.pubsClassColors";
+char *query = "NOSQLINJ SELECT class, rgbColor FROM hgFixed.pubsClassColors";
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **row = NULL;
 while ((row = sqlNextRow(sr)) != NULL)
     {
     char *class = row[0];
     char *colStr = row[1];
     // copied from genePredItemClassColor - is there no function for this?
     // convert comma sep rgb string to array
     char *rgbVals[5];
     chopString(colStr, ",", rgbVals, sizeof(rgbVals));
     struct rgbColor *rgb;
     AllocVar(rgb);
     rgb->r = (sqlUnsigned(rgbVals[0]));
     rgb->g = (sqlUnsigned(rgbVals[1]));
     rgb->b = (sqlUnsigned(rgbVals[2]));
@@ -112,37 +112,37 @@
 /* bad solution: a function that is called before the extra field is 
  * accessed and that fills it from a sql query. Will need to redo this like gencode, 
  * drawing from atom, variome and bedLoadN or bedDetails */
 {
 char query[LARGEBUF];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 struct pubsExtra *extra = NULL;
 
 /* support two different storage places for article data: either the bed table directly 
  * includes the title + author of the article or we have to look it up from the articles 
  * table. Having a copy of the title in the bed table is faster */
 bool newFormat = FALSE;
 if (sqlColumnExists(conn, tg->table, "title")) 
     {
-    safef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s "
+    sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title, impact, classes FROM %s "
     "WHERE chrom = '%s' and chromStart = '%d' and name='%s'", tg->table, chromName, lf->start, lf->name);
     newFormat = TRUE;
     }
 else 
     {
-    safef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", 
+    sqlSafef(query, sizeof(query), "SELECT firstAuthor, year, title FROM %s WHERE articleId = '%s'", 
         articleTable, lf->name);
     newFormat = FALSE;
     }
 
 sr = sqlGetResult(conn, query);
 if ((row = sqlNextRow(sr)) != NULL)
     {
     char *firstAuthor = row[0];
     char *year    = row[1];
     char *title   = row[2];
     char *impact  = NULL;
     char *classes = NULL;
 
 
     extra = needMem(sizeof(struct pubsExtra));
@@ -223,49 +223,49 @@
 static void pubsAddExtra(struct track* tg, struct linkedFeatures* lf)
 /* add authorYear and title to linkedFeatures->extra */
 {
 char *articleTable = trackDbSettingClosestToHome(tg->tdb, "pubsArticleTable");
 if(isEmpty(articleTable))
     return;
 if (lf->extra != NULL) 
     return;
 
 struct sqlConnection *conn = hAllocConn(database);
 struct pubsExtra* extra = pubsMakeExtra(tg, articleTable, conn, lf);
 lf->extra = extra;
 hFreeConn(&conn);
 }
 
-static void dyStringPrintfWithSep(struct dyString *ds, char *sep, char *format, ...)
+static void sqlDyStringPrintfWithSep(struct dyString *ds, char* sep, char *format, ...)
 /*  Printf to end of dyString. Prefix with sep if dyString is not empty. */
 {
 if (ds->stringSize!=0)
     dyStringAppend(ds, sep);
 va_list args;
 va_start(args, format);
-dyStringVaPrintf(ds, format, args);
+sqlDyStringVaPrintfFrag(ds, format, args);
 va_end(args);
 }
 
 struct hash* searchForKeywords(struct sqlConnection* conn, char *articleTable, char *keywords)
 /* return hash with the articleIds that contain a given keyword in the abstract/title/authors */
 {
 if (isEmpty(keywords))
     return NULL;
 
 char query[12000];
-safef(query, sizeof(query), "SELECT articleId FROM %s WHERE "
+sqlSafef(query, sizeof(query), "SELECT articleId FROM %s WHERE "
 "MATCH (citation, title, authors, abstract) AGAINST ('%s' IN BOOLEAN MODE)", articleTable, keywords);
 //printf("query %s", query);
 struct slName *artIds = sqlQuickList(conn, query);
 if (artIds==NULL || slCount(artIds)==0)
     return NULL;
 
 // convert list to hash
 struct hash *hashA = hashNew(0);
 struct slName *el;
 for (el = artIds; el != NULL; el = el->next)
     hashAddInt(hashA, el->name, 1);
 freeMem(keywords);
 slFreeList(artIds);
 return hashA;
 }
@@ -274,67 +274,67 @@
 /* load items that fulfill keyword and year filter */
 {
 pubsParseClassColors();
 struct sqlConnection *conn = hAllocConn(database);
 char *keywords = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterKeywords");
 char *yearFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterYear");
 char *publFilter = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "pubsFilterPublisher");
 char *articleTable = pubsArticleTable(tg);
 
 if(sameOk(yearFilter, "anytime"))
     yearFilter = NULL;
 if(sameOk(publFilter, "all"))
     publFilter = NULL;
 
 if(isNotEmpty(keywords))
-    keywords = makeMysqlMatchStr(sqlEscapeString(keywords));
+    keywords = makeMysqlMatchStr(keywords);
 
 if (isEmpty(yearFilter) && isEmpty(keywords) && isEmpty(publFilter))
 {
     loadGappedBed(tg);
 }
 else
     {
     // put together an "extra" query to hExtendedRangeQuery that removes articles
     // without the keywords specified in hgTrackUi
     char *oldLabel = tg->longLabel;
     tg->longLabel = catTwoStrings(oldLabel, " (filter activated)");
     freeMem(oldLabel);
 
     char **row;
     struct linkedFeatures *lfList = NULL;
     struct trackDb *tdb = tg->tdb;
     int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0"));
     int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000"));
     boolean useItemRgb = bedItemRgb(tdb);
 
     char *extra = NULL;
     struct dyString *extraDy = dyStringNew(0);
     struct hash *articleIds = searchForKeywords(conn, articleTable, keywords);
     if (sqlColumnExists(conn, tg->table, "year"))
         // new table schema: filter fields are on main bed table
         {
         if (isNotEmpty(yearFilter))
-            dyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", sqlEscapeString(yearFilter));
+            sqlDyStringPrintfWithSep(extraDy, " AND ", " year >= '%s'", yearFilter);
         if (isNotEmpty(publFilter))
-            dyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", sqlEscapeString(publFilter));
+            sqlDyStringPrintfWithSep(extraDy, " AND ", " publisher = '%s'", publFilter);
         }
     else
         // old table schema, filter by doing a join on article table
         {
         if(isNotEmpty(yearFilter))
-            dyStringPrintf(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \
+            sqlDyStringPrintfFrag(extraDy, "name IN (SELECT articleId FROM %s WHERE year>='%s')", articleTable, \
                 yearFilter);
         }
 
 
     if (extraDy->stringSize > 0)
         extra = extraDy->string;
     else
         extra = NULL;
 
     int rowOffset = 0;
     struct sqlResult *sr = hExtendedRangeQuery(conn, tg->table, chromName, winStart, winEnd, extra,
                                                FALSE, NULL, &rowOffset);
     freeDyString(&extraDy);
 
     while ((row = sqlNextRow(sr)) != NULL)
@@ -443,44 +443,44 @@
 struct bed *bed = item;
 genericMapItem(tg, hvg, item, bed->name, bed->name, start, end, x, y, width, height);
 }
 
 static struct hash* pubsLookupSequences(struct track *tg, struct sqlConnection* conn, char *articleId, bool getSnippet)
 /* create a hash with a mapping annotId -> snippet or annotId -> shortSeq for an articleId*/
 {
     char query[LARGEBUF];
     char *sequenceTable = trackDbRequiredSetting(tg->tdb, "pubsSequenceTable");
     char *selectValSql = NULL;
     if (getSnippet)
         selectValSql = "replace(replace(snippet, \"<B>\", \"\\n>>> \"), \"</B>\", \" <<<\\n\")";
     else
         selectValSql = "concat(substr(sequence,1,4),\"...\",substr(sequence,-4))";
 
-    safef(query, sizeof(query), "SELECT annotId, %s  FROM %s WHERE articleId='%s' ", 
+    sqlSafef(query, sizeof(query), "SELECT annotId, %s  FROM %s WHERE articleId='%s' ", 
         selectValSql, sequenceTable, articleId);
     struct hash *seqIdHash = sqlQuickHash(conn, query);
-    //freeMem(sequenceTable); // XX Why does this crash??
+    //freeMem(sequenceTable); // XX Why does this crash?? because trackDbRequiredSetting returns a value in a hash. do not free.
     return seqIdHash;
 }
 
 static char *pubsArticleDispId(struct track *tg, struct sqlConnection *conn, char *articleId)
 /* given an articleId, lookup author and year and create <author><year> label for it */
 {
 char *dispLabel = NULL;
 char *articleTable = pubsArticleTable(tg);
 char query[LARGEBUF];
-safef(query, sizeof(query), "SELECT firstAuthor, year FROM %s WHERE articleId = '%s'", 
+sqlSafef(query, sizeof(query), "SELECT firstAuthor, year FROM %s WHERE articleId = '%s'", 
     articleTable, articleId);
 struct sqlResult *sr = sqlGetResult(conn, query);
 if (sr!=NULL)
     {
     char **row = NULL;
     row = sqlNextRow(sr);
     if (row != NULL)
         dispLabel = pubsFeatureLabel(row[0], row[1]);
     else
         dispLabel = articleId;
     }
 else
     dispLabel = articleId;
 sqlFreeResult(&sr);
 return dispLabel;