57a384c55958100f74a922cae995836aba8ea99b
max
  Mon Jun 24 10:27:43 2013 -0700
working around a sqlinj messages
diff --git src/hg/hgc/pubs.c src/hg/hgc/pubs.c
index c4fd801..e001483 100644
--- src/hg/hgc/pubs.c
+++ src/hg/hgc/pubs.c
@@ -1,39 +1,43 @@
 /* pubs.c - display details of publiations literature track (pubsxxx tables) */
 
 #include "common.h"
 #include "jksql.h"
 #include "hdb.h"
 #include "hgc.h"
 #include "hgColors.h"
 #include "trackDb.h"
 #include "web.h"
 #include "hash.h"
 #include "net.h"
 #include "obscure.h"
 #include "common.h"
 #include "string.h"
-//include "hgTrackUi.h"
+#include "dystring.h"
 
 // cgi var to activate debug output
 static int pubsDebug = 0;
 
 // global var for printArticleInfo to indicate if article has suppl info 
-// Most publishers have supp data
+// Most publishers have supp data.
+// If they don't have it, we can skip the fileType column in the table
 bool pubsHasSupp = TRUE; 
+
 // global var for printArticleInfo to indicate if article is elsevier
+// If it's elsevier, we print the copyright line
 bool pubsIsElsevier = FALSE; 
+
 // the article source is used to modify other parts of the page
 static char *articleSource;
 // we need the external article PMC Id for yif links
 static char *extId = NULL;
 
 // section types in mysql table, for all annotations tables
 // we note where the hit is located in the document
 static char *pubsSecNames[] ={
       "header", "abstract",
       "intro", "methods",
       "results", "discussion",
       "conclusions", "ack",
       "refs", "unknown" };
 //
 // whether a checkbox is checked by default, have to correspond to pubsSecNames
@@ -261,48 +265,50 @@
 }
 
 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, "NOSQLINJ SET SESSION group_concat_max_len = 100000");
 
-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);
+// rather ugly compared to single safef line, but needed to rewrite with dyString for sql inj
+struct dyString *query = newDyString(4000);
+sqlDyStringPrintf(query,"SELECT distinct ");
+sqlDyStringPrintf(query, "%s.articleId,url,title,authors,citation,pmid,extId, ", markerTable);
+sqlDyStringPrintf(query, 
+    "group_concat(snippet, concat(\" (section: \", section, \")\") SEPARATOR ' (...) ') FROM %s ",
+    markerTable);
+sqlDyStringPrintf(query, "JOIN %s USING (articleId) ", articleTable);
+sqlDyStringPrintf(query, "WHERE markerId='%s' AND section in (", item);
+// this part triggered sql injection warning as the section list includes ' and ,
+sqlDyStringAppend(query, sectionList);
+sqlDyStringPrintf(query, ") GROUP BY articleId ORDER BY year DESC LIMIT %d", itemLimit);
 
 if (pubsDebug)
-    printf("%s", query);
+    printf("%s", query->string);
 
-struct sqlResult *sr = sqlGetResult(conn, query);
+struct sqlResult *sr = sqlGetResult(conn, query->string);
 
 return sr;
 }
 
 
 static void printSectionCheckboxes()
 /* show a little form with checkboxes where user can select sections they want to show */
 {
 // labels to show to user, have to correspond to pubsSecNames
 char *secLabels[] ={
       "Title", "Abstract",
       "Introduction", "Methods",
       "Results", "Discussion",
       "Conclusions", "Acknowledgements",
       "References", "Undetermined section (e.g. for a brief communication)" };
@@ -331,33 +337,39 @@
 }
 
 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];
-sqlSafef(query, sizeof(query), "SELECT COUNT(*) from %s WHERE markerId='%s' AND section in (%s) ", markerTable, item, sectionList);
-if (sqlNeedQuickNum(conn, query) > itemLimit) 
+//char query[4000];
+struct dyString *query = newDyString(4000);
+sqlDyStringPrintf(query, "SELECT COUNT(*) from ");
+dyStringAppend(query, markerTable); 
+sqlDyStringPrintf(query, " WHERE markerId='%s' AND section in ", item);
+dyStringPrintf(query, " (%s) ", sectionList); // no need to check for illegal characters here
+
+//sqlSafef(query, sizeof(query), "SELECT COUNT(*) from %s WHERE markerId='%s' AND section in (%s) ", markerTable, item, sectionList);
+if (sqlNeedQuickNum(conn, query->string) > 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();
 char *sectionList = makeSqlMarkerList();