8f4e76f8972781dcf79755e7cf2a32015eb093f5
galt
Fri Apr 19 13:32:46 2019 -0700
tweaking summary/index.html static page output
diff --git src/hg/cirm/cdw/cdwGetFile/cdwGetFile.c src/hg/cirm/cdw/cdwGetFile/cdwGetFile.c
index 72ef033..6fa94bd 100644
--- src/hg/cirm/cdw/cdwGetFile/cdwGetFile.c
+++ src/hg/cirm/cdw/cdwGetFile/cdwGetFile.c
@@ -1,311 +1,312 @@
/* cdwGetFile - given a file ID and a security token (skipped for public cirm site), send the file using Apache */
/* Copyright (C) 2016 The Regents of the University of California
* See README in this or parent directory for licensing information. */
#include "common.h"
#include "linefile.h"
#include "hash.h"
#include "options.h"
#include "hgConfig.h"
#include "cheapcgi.h"
#include "sqlSanity.h"
#include "htmshell.h"
#include "portable.h"
#include "cart.h"
#include "cdw.h"
#include "hdb.h"
#include "hui.h"
#include "cdw.h"
#include "cdwValid.h"
#include "web.h"
#include "cdwLib.h"
#include "wikiLink.h"
#include "filePath.h"
/* Global vars */
struct cart *cart; // User variables saved from click to click
struct hash *oldVars; // Previous cart, before current round of CGI vars folded in
struct cdwUser *user; // Our logged in user if any
void errExit(char *msg, char *field)
/* print http header + message and exit. msg can contain %s */
{
printf("Content-Type: text/html\n\n");
puts("ERROR: ");
if (!field)
puts(msg);
else
printf(msg, field);
exit(0);
}
void mustHaveAccess(struct sqlConnection *conn, struct cdwFile *ef)
/* exit with error message if user does not have access to file ef */
{
boolean isPublic = cfgOptionBooleanDefault("cdw.siteIsPublic", FALSE);
if (isPublic)
return;
if (cdwCheckAccess(conn, ef, user, cdwAccessRead))
return;
else
if (user==NULL)
errExit("Sorry, this file has access restrictions. Please log in first.", NULL);
else
errExit("Sorry, user %s does not have access to this file.", user->email);
}
struct patcher
/* deal with patching replacement bits in html */
{
struct patcher *next;
char *match; // string to match
int size; // string size
int count; // match count
char *(*cdwLocalFunction)(struct cart *cart, boolean makeAbsolute); // function to make
};
static void printFileReplaceVar(char *filePath)
/* dump a text file to stdout with the html header, replace with the menubar */
{
printf("Content-Type: text/html\n\n");
int c;
FILE *file = fopen(filePath, "r");
if (file == 0)
errExit("Cannot open file %s", filePath);
struct patcher *patcherList = NULL, *p = NULL;
AllocVar(p);
p->match = cloneString("");
p->cdwLocalFunction = &cdwHeadTagDependencies;
slAddHead(&patcherList, p);
AllocVar(p);
p->match = cloneString("");
p->cdwLocalFunction = &cdwPageHeader;
slAddHead(&patcherList, p);
AllocVar(p);
p->match = cloneString("");
p->cdwLocalFunction = &cdwLocalMenuBar;
slAddHead(&patcherList, p);
AllocVar(p);
p->match = cloneString("");
p->cdwLocalFunction = &cdwPageFooter;
slAddHead(&patcherList, p);
for(p=patcherList; p; p=p->next)
{
p->size = strlen(p->match);
}
while ((c = getc(file)) != EOF)
{
putchar(c);
for(p=patcherList; p; p=p->next)
{
if (c==p->match[p->count])
p->count++;
else
p->count = 0;
if (p->count==p->size)
{
+ putchar('\n'); // make view source more readable
puts((*p->cdwLocalFunction)(cart, TRUE));
}
}
}
fclose(file);
}
void sendFile(char *format, char *filePath, char *suggestFileName)
/* format is one of "fastq", "fasta", defined in cdw.as. if format is NULL, use file extension. */
/* send file to user via Apache, using X-Sendfile or stdout, as needed */
{
if (format==NULL || sameWord(format, "unknown"))
{
char ext[FILEEXT_LEN];
splitPath(filePath, NULL, NULL, ext);
if (strlen(ext)>1)
{
format = cloneString(ext);
format++; // skip over . character
}
}
// html files are not sent via X-Sendfile as we need to replace one special variable
if (sameWord(format, "html"))
{
printFileReplaceVar(filePath);
return;
}
// pdf, jpeg files are shown directly in the internet browser, not downloaded
else if (sameWord(format, "jpg"))
printf("Content-Type: image/jpeg\n");
else if (sameWord(format, "pdf"))
printf("Content-Type: application/pdf\n");
else if (sameWord(format, "png"))
printf("Content-Type: image/png\n");
else if (sameWord(format, "json"))
printf("Content-Type: application/json\n");
else if (sameWord(format, "text"))
printf("Content-Type: text/plain\n");
else
{
printf("Content-Disposition: attachment; filename=%s\n", suggestFileName);
printf("Content-Type: application/octet-stream\n");
}
/* send pseudo-HTTP header to tell Apache to transfer filePath ( will honor byte range ) */
printf("Content-Length: %lld\n", (long long)fileSize(filePath));
printf("X-Sendfile: %s\n\n", filePath);
}
void sendFileByAcc(struct sqlConnection *conn, char* acc, boolean useSubmitFname, char *addExt)
/* send file identified by acc (=cdwValidFile.licensePlate), suggests a canonical filename of the format
* .
* Example URL: http://hgwdev.soe.ucsc.edu/cgi-bin/cdwGetFile?acc=SCH000FSW *
* if useSubmitFname is TRUE, suggest the submission filename, not a canonical name.
* if addExt is not NULL, will not retrieve the file identified by accession but rather its index file,
* with the given extension (.tbi or .bai) */
{
struct cdwValidFile *vf = cdwValidFileFromLicensePlate(conn, acc);
if (vf==NULL)
errExit("%s is not a valid accession in the CDW.", acc);
struct cdwFile *ef = cdwFileFromId(conn, vf->fileId);
char* filePath = cdwPathForFileId(conn, vf->fileId);
if (addExt != NULL)
{
if (! (sameWord(addExt, ".bai") || sameWord(addExt, ".tbi")))
errAbort("ERROR: The addExt argument to cdwGetFile can only be .bai or .tbi. No other values are allowed.");
if ((endsWith(filePath, ".vcf") || endsWith(filePath, ".VCF")) && sameWord(addExt, ".tbi"))
// the .tbi files of .vcf files are actually named .vcf.gz.tbi
filePath = catTwoStrings(filePath, ".gz.tbi");
else
filePath = catTwoStrings(filePath, addExt);
}
else
{
addExt = ""; // make sure reference to addExt does not fail below
// for .vcf files, we send the .vcf.gz version
if (endsWith(filePath, ".vcf") || endsWith(filePath, ".VCF"))
filePath = catTwoStrings(filePath, ".gz");
}
mustHaveAccess(conn, ef);
char suggestName[8000];
if (useSubmitFname)
safef(suggestName, sizeof(suggestName), "%s%s", basename(ef->submitFileName), addExt);
else
{
char *formatExt = fileExtFromFormat(vf->format);
if (vf->format && sameWord(vf->format, "unknown") && ef && ef->submitFileName && endsWith(ef->submitFileName, ".tar.gz"))
formatExt = cloneString(".tar.gz");
safef(suggestName, sizeof(suggestName), "%s%s%s", vf->licensePlate, formatExt, addExt);
freez(&formatExt);
}
sendFile(vf->format, filePath, suggestName);
}
void sendFileByPath(struct sqlConnection *conn, char *path)
/* send file identified by a submission pathname (cdwFile.submitFileName),
* suggests the original filename. */
/* path can be a suffix that matches a filename, so the initial '/hive' or
* '/data' can be omitted. *
* Example URL for testing:
* http://hgwdev.soe.ucsc.edu/cgi-bin/cdwGetFile/hive/groups/cirm/pilot/labs/quake/130625_M00361_0080_000000000-A43D1/Sample_1_L13_C31_IL3541-701-506/1_L13_C31_IL3541-701-506_TAAGGCGA-ACTGCATA_L001_R1_001.fastq.gz */
{
int fileId = cdwFileIdFromPathSuffix(conn, path);
if (fileId == 0)
errExit("A file with suffix %s does not exist in the database", path);
char *localPath = cdwPathForFileId(conn, fileId);
if (localPath == NULL)
errExit("A local file with suffix %s was not found in the database. This is an internal error.", path);
struct cdwFile *ef = cdwFileFromId(conn, fileId);
if (ef == NULL)
errExit("Could not find cdwFile for path %s", path);
mustHaveAccess(conn, ef);
sendFile(NULL, localPath, basename(ef->submitFileName));
}
struct cdwUser *authUserViaToken(struct sqlConnection *conn)
/* get the cgi variable "token" and return the cdw user for it */
{
char *token = cgiOptionalString("token");
if (token==NULL)
return NULL;
// get the userId for this token
struct sqlConnection *central = hConnectCentral();
char query[4096];
sqlSafef(query, sizeof(query), "SELECT userId FROM cdwDownloadToken WHERE token='%s'", token);
int userId = sqlQuickNum(central, query);
if (userId==0)
return NULL;
hDisconnectCentral(¢ral);
return cdwUserFromId(conn, userId);
}
void dispatch(struct sqlConnection *conn)
/* Dispatch page after to routine depending on cdwCommand variable */
{
char *userName = wikiLinkUserName();
if (userName==NULL)
// alternative to cookie is a token on the URL, for queries from wget
user = authUserViaToken(conn);
else
user = cdwUserFromUserName(conn, userName);
char *acc = cgiOptionalString("acc");
char *path = getenv("PATH_INFO"); // CGI gets trailing /x/y/z like path via this env. var.
if (path==NULL)
path = cgiOptionalString("path"); // when calling via cgi-spoof from command line
boolean useSubmitFname = cgiOptionalInt("useSubmitFname", 0);
char *addExt = cgiOptionalString("addExt");
if (acc != NULL)
sendFileByAcc(conn, acc, useSubmitFname, addExt);
else if (path != NULL)
sendFileByPath(conn, path);
else
errExit("Need at least the HTTP GET parameter 'acc' with an accession ID "
"or a file path with the HTTP parameter 'path' or the path directly after the CGI name, "
"separated by '/', e.g. cdwGetFile/valData/ce10/ce10.2bit';", NULL);
}
void localWebWrap(struct cart *theCart)
/* We got the http stuff handled, and a cart. */
{
cart = theCart;
struct sqlConnection *conn = sqlConnect(cdwDatabase);
dispatch(conn);
sqlDisconnect(&conn);
}
char *excludeVars[] = {"submit", NULL};
int main(int argc, char *argv[])
/* Process command line. */
{
cgiSpoof(&argc, argv);
oldVars = hashNew(0);
cartEmptyShellNoContent(localWebWrap, hUserCookie(), excludeVars, oldVars);
return 0;
}