d27769317be7f92e199f69d75b10a7421eecf770
max
Sat Sep 26 21:57:15 2026 -0700
hgGeneGraph: require a form submission and a checked answer to file a feedback report
diff --git src/hg/hgGeneGraph/hgGeneGraph src/hg/hgGeneGraph/hgGeneGraph
index 7ee374f979d..0f87b36bf9d 100755
--- src/hg/hgGeneGraph/hgGeneGraph
+++ src/hg/hgGeneGraph/hgGeneGraph
@@ -19,31 +19,31 @@
# dark blue, dashed = only low-throughput data
# dark blue, thickness = low-throughput data + text
# dark blue + dashed = only pathway data
# code review
# - os.system is not a security risk here, no variables go into the cmd line
# - mysql statements are not escaped, instead all CGI vars are checked for non-alpha letters
# hgFixed tables required for this script: ggLink (main table with gene-gene links),
# ggLinkEvent (details about link), ggEventDb (details about links from databases),
# ggEventText (details about links from text mining), ggDoc (details about documents for ggEventText)
# ggGeneName (symbols), ggGeneClass (HPRD/Panther class)
# these are default python modules on python 2.7, no errors expected here
-import sys, cgi, os, string, urllib.request, urllib.parse, urllib.error, operator, hashlib, html
+import sys, cgi, os, string, urllib.request, urllib.parse, urllib.error, operator, hashlib, html, random
from sys import exit
from collections import defaultdict, namedtuple
from os.path import *
#These two lines should be commented out whenever committing this file into git.
#They activate stack traces to stdout which can in certain cases reveal the mysql password,
#when there is a Mysql connection problem.
#import cgitb
#cgitb.enable()
# import the UCSC-specific library
sys.path.append(join(dirname(__file__), "pyLib"))
try:
from hgLib3 import cgiArgs, cgiSetup, cgiString, printContentType, printMenuBar, \
sqlConnect, sqlQuery, errAbort, cfgOption, runCmd, cgiGetAll, printHgcHeader, \
@@ -1880,57 +1880,69 @@
print("
Interaction %s - %s
" % (causeGene, themeGene))
conn = sqlConnect(GGDB)
rows = queryEventText(conn, causeGene, themeGene)
print ("")
print ("Thank you for reporting errors, e.g.")
print("
- not true (e.g. the authors state that the interaction does not happen )
")
print("- text mining errors (the authors did not say anything about this particular interaction)
")
print("
")
print("This makes it easier for us to improve the text mining system or database imports.
")
print("You can leave your email address in the comment if you want to give us the possibility to comment.")
print ("Optional comment:
")
- print(('
')
#printMsrNlpRows(rows)
showSnipsLink(conn, causeGene, themeGene)
#def namedtuple_factory(cursor, row):
#"""
#used as a function pointer to sqlite to have it return structs with names and not just arrays
#"""
#fields = [col[0] for col in cursor.description]
#Row = collections.namedtuple("Row", fields)
#return Row(*row)
#def openSqlite(dbName):
#" opens sqlite database and have it return structs (=namedtuples) "
#tryCount = retries
#con = None
#con = sqlite3.connect(dbName, timeout=20)
#con.row_factory = namedtuple_factory
##con.row_factory = sqlite3.Row
-def removeInteraction(param, captcha, comment):
+def removeInteraction(param, captcha, captchaHash, comment):
+ if os.environ.get("REQUEST_METHOD") != "POST":
+ errAbort("This action requires a form submission, not a link.")
+ if captcha is None or captchaHash is None or saltedHash(captcha.strip()) != captchaHash:
+ errAbort("The answer to the arithmetic question was not correct. Please go back and try again.")
+
fields = param.split(":")
if len(fields)!=2:
errAbort( "illegal CGI parameter")
causeGene, themeGene = fields
ip = html.escape(os.environ["REMOTE_ADDR"])
conn = hConnectCentral()
if not sqlTableExists(conn, "ggFeedback"):
# sqlQuery() reads cursor.description, which is None after a statement that returns no
# rows, so it cannot run a CREATE
sqlUpdate(conn, "CREATE TABLE ggFeedback (causeGene varchar(255), themeGene varchar(255), pmid varchar(255), " \
"comment varchar(10000), time TIMESTAMP, ip varchar(255), INDEX allIdx (causeGene, themeGene, pmid));")
# name the columns: the positional version put NOW() into "comment" and the comment text
@@ -2006,32 +2018,33 @@
print("%s: %d" % (db, len(pairSet)))
print("")
def htmlMiddle():
" print html middle part "
sys.stdout.flush()
flag = getCgiVar("flag")
if flag!=None:
flagInteraction(flag)
exit(0)
remove = getCgiVar("remove")
if remove!=None:
captcha = getCgiVar("captcha")
+ captchaHash = getCgiVar("captchaHash", maxLen=40)
comment = getCgiVar("comment", allowAnyChar=True, maxLen=10000)
- removeInteraction(remove, captcha, comment)
+ removeInteraction(remove, captcha, captchaHash, comment)
exit(0)
docId = getCgiVar("docId")
if docId!=None:
showDoc(docId)
exit(0)
link = getCgiVar("link")
if link!=None:
showLink(link)
exit(0)
page = getCgiVar("page")
if page=="stats":
showStats()