6ba4e724f84f86544c11a90f3802fd6318cd154f
angie
Fri Dec 21 16:28:42 2018 -0800
Watch out for invalid data and unencoded newlines when reading in file uploaded as a saved session. refs #22638, #22637
cartLoadSettings did absolutely no checking that its input looked anything like cart settings, resulting in giant useless carts in which custom track files, hgTracks HTML and other arbitrary files apparently were parsed as cart settings. Now we do quite a bit of checking in cartLoadSettingsFromUserInput, and can warn the user if it looks like they are attempting to upload a custom track as a saved session.
The unencoded newlines are our fault -- since 2010, we have been writing out saved session files without encoding newlines in setting values (pasted in by the user). Then those newlines can be mistaken for the newlines that we use to separate settings. Oops! Use a heuristic that holds up so far to determine whether the newlines should have been encoded: they seem to occur in specific variables (like hgta_pastedIdentifiers), and those variables always appear in the middle of an alphabetically sorted cluster of variables with the same prefix (like hgta_).
And of course, we now write out saved session files with encoded newlines, which we decode when reading back in.
We even have to deal with carts that have mixed types of newlines from various garbage sources, using lineFileCarefulNewlines().
diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c
index 6cc60d9..75ac595 100644
--- src/hg/hgSession/hgSession.c
+++ src/hg/hgSession/hgSession.c
@@ -1217,31 +1217,31 @@
cartCheckForCustomTracks(cart, dyMessage);
hDisconnectCentral(&conn);
return dyStringCannibalize(&dyMessage);
}
void doSaveLocal()
/* Output current settings to be saved as a file on the user's machine.
* Return a message confirming what we did. */
{
char *fileName = textOutSanitizeHttpFileName(cartString(cart, hgsSaveLocalFileName));
char *compressType = cartString(cart, hgsSaveLocalFileCompress);
struct pipeline *compressPipe = textOutInit(fileName, compressType, NULL);
cleanHgSessionFromCart(cart);
-cartDumpNoEncode(cart);
+cartDumpHgSession(cart);
// Now add all the default visibilities to output.
outDefaultTracks(cart, NULL);
textOutClose(&compressPipe, NULL);
}
char *doLoad(boolean fromUrl, char *actionVar)
/* Load settings from a file or URL sent by the user.
* Return a message confirming what we did. */
{
struct dyString *dyMessage = dyStringNew(1024);
struct lineFile *lf = NULL;
webPushErrHandlersCartDb(cart, cartUsualString(cart, "db", NULL));
if (fromUrl)
@@ -1292,47 +1292,70 @@
}
else
dyStringPrintf(dyMessage,
"Sorry, I don't recognize the file type of "
"%s. Please submit plain text or "
"compressed text in one of the formats offered in "
"Save Settings.", fileName);
}
else
{
dyStringAppend(dyMessage, "Sorry, your web browser seems to have "
"posted no data");
if (isNotEmpty(fileName))
dyStringPrintf(dyMessage, ", only the filename %s",
fileName);
- dyStringAppend(dyMessage, ". Your settings have not been changed.");
+ dyStringAppend(dyMessage, " (empty file?). Your settings have not been changed.");
lf = NULL;
}
dyStringPrintf(dyMessage, " "
"Browser",
hLocalHostCgiBinUrl(),
cartSessionVarName(), cartSessionId(cart));
}
if (lf != NULL)
{
- cartLoadSettings(lf, cart, NULL, actionVar);
+ lineFileCarefulNewlines(lf);
+ struct dyString *dyLoadMessage = dyStringNew(0);
+ boolean ok = cartLoadSettingsFromUserInput(lf, cart, NULL, actionVar, dyLoadMessage);
+ lineFileClose(&lf);
+ if (ok)
+ {
+ dyStringAppend(dyMessage, dyLoadMessage->string);
cartCopyCustomComposites(cart);
hubConnectLoadHubs(cart);
cartCopyCustomTracks(cart);
cartHideDefaultTracks(cart);
cartCheckForCustomTracks(cart, dyMessage);
- lineFileClose(&lf);
+ }
+ else
+ {
+ dyStringClear(dyMessage);
+ dyStringAppend(dyMessage, ""
+ "Unable to load session: ");
+ dyStringAppend(dyMessage, dyLoadMessage->string);
+ dyStringAppend(dyMessage, "The uploaded file needs to have been previously saved from the "
+ "Save Settings section. If you feel you have reached this "
+ "message in error, please contact the "
+ "string));
+ dyStringAppend(dyMessage, "%0ACan you help me upload the data?\">"
+ "UCSC Genome Browser team for assistance.\n");
+ }
+ dyStringFree(&dyLoadMessage);
}
return dyStringCannibalize(&dyMessage);
}
void renamePrefixedCartVar(char *prefix, char *oldName, char *newName)
/* If cart has prefix+oldName, replace it with prefix+newName = submit. */
{
char varName[256];
safef(varName, sizeof(varName), "%s%s", prefix, oldName);
if (cartVarExists(cart, varName))
{
cartRemove(cart, varName);
safef(varName, sizeof(varName), "%s%s", prefix, newName);
cartSetString(cart, varName, "submit");
}