We are testing a new Sessions page, with a searchable, "
"sortable table and one-click sharing. "
"
Try the new page.
\n",
@@ -2484,65 +2537,67 @@
hDisconnectCentral(&conn);
}
void doDeleteSessionJson(char *userName)
/* AJAX: delete the session named by hgsOldSessionName under the current user. */
{
struct sqlConnection *conn = hConnectCentral();
char *sessionName = trimSpaces(cloneString(cgiUsualString(hgsOldSessionName, "")));
if (isEmpty(userName))
{ saveSessionJsonError(conn, "Please log in and try again."); return; }
if (isEmpty(sessionName))
{ saveSessionJsonError(conn, "No session was specified."); return; }
char *encUserName = cgiEncodeFull(userName);
char *encSessionName = cgiEncodeFull(sessionName);
char query[512];
-sqlSafef(query, sizeof(query), "select shared from %s where userName = '%s' and sessionName = '%s';",
- namedSessionTable, encUserName, encSessionName);
-int shared = sqlQuickNum(conn, query);
+int shared = sessionSharedLevel(conn, encUserName, encSessionName);
+if (shared < 0)
+ { saveSessionJsonError(conn, "Could not find that session."); return; }
if (shared >= 2)
thumbnailRemove(encUserName, encSessionName, conn);
sqlSafef(query, sizeof(query), "DELETE FROM %s WHERE userName = '%s' AND sessionName = '%s';",
namedSessionTable, encUserName, encSessionName);
sqlUpdate(conn, query);
saveSessionJsonOk(conn, NULL);
}
void doShareSessionJson(char *userName)
/* AJAX: set the "shared by link" flag (0<->1) on hgsOldSessionName. Desired state in
* hgsNewSessionShare (0/1). Does not touch the gallery (shared==2) except to unshare. */
{
struct sqlConnection *conn = hConnectCentral();
char *sessionName = trimSpaces(cloneString(cgiUsualString(hgsOldSessionName, "")));
int desired = cgiUsualInt(hgsNewSessionShare, 0);
cartRemove(cart, hgsNewSessionShare);
if (isEmpty(userName))
{ saveSessionJsonError(conn, "Please log in and try again."); return; }
if (isEmpty(sessionName))
{ saveSessionJsonError(conn, "No session was specified."); return; }
char *encUserName = cgiEncodeFull(userName);
char *encSessionName = cgiEncodeFull(sessionName);
char query[512];
-sqlSafef(query, sizeof(query), "select shared from %s where userName = '%s' and sessionName = '%s';",
- namedSessionTable, encUserName, encSessionName);
-int shared = sqlQuickNum(conn, query);
+int shared = sessionSharedLevel(conn, encUserName, encSessionName);
+if (shared < 0)
+ { saveSessionJsonError(conn, "Could not find that session."); return; }
int newShared = desired ? 1 : 0;
sqlSafef(query, sizeof(query), "UPDATE %s SET shared = %d WHERE userName = '%s' AND sessionName = '%s';",
namedSessionTable, newShared, encUserName, encSessionName);
sqlUpdate(conn, query);
sessionTouchLastUse(conn, encUserName, encSessionName);
-if (newShared == 0 && shared >= 2)
+/* Either way out of the public listing takes the picture with it: this endpoint drops a session
+ * from shared==2 to 1 as well as to 0, and the file would otherwise be left behind. */
+if (shared >= 2 && newShared < 2)
thumbnailRemove(encUserName, encSessionName, conn);
char extra[32];
safef(extra, sizeof(extra), ", \"shared\": %d", newShared);
saveSessionJsonOk(conn, extra);
}
void doGallerySessionJson(char *userName)
/* AJAX: add/remove hgsOldSessionName to/from the public gallery (shared 2<->1). Desired state in
* hgsNewSessionShare (0/1). Adding requires a non-empty description, like the classic page. */
{
struct sqlConnection *conn = hConnectCentral();
char *sessionName = trimSpaces(cloneString(cgiUsualString(hgsOldSessionName, "")));
int desired = cgiUsualInt(hgsNewSessionShare, 0);
cartRemove(cart, hgsNewSessionShare);
if (isEmpty(userName))
@@ -2557,76 +2612,74 @@
{
if (!gotSettings)
{ saveSessionJsonError(conn, "This server does not support the public listing."); return; }
sqlSafef(query, sizeof(query),
"select settings from %s where userName = '%s' and sessionName = '%s';",
namedSessionTable, encUserName, encSessionName);
char *settings = sqlQuickString(conn, query);
char *description = getSetting(settings, "description");
if (isEmpty(description))
{
saveSessionJsonError(conn, "Please add a description (with the Edit button) before posting "
"this session to the public listing.");
return;
}
}
-sqlSafef(query, sizeof(query), "select shared from %s where userName = '%s' and sessionName = '%s';",
- namedSessionTable, encUserName, encSessionName);
-int shared = sqlQuickNum(conn, query);
+int shared = sessionSharedLevel(conn, encUserName, encSessionName);
+if (shared < 0)
+ { saveSessionJsonError(conn, "Could not find that session."); return; }
int newShared = desired ? 2 : 1;
sqlSafef(query, sizeof(query), "UPDATE %s SET shared = %d WHERE userName = '%s' AND sessionName = '%s';",
namedSessionTable, newShared, encUserName, encSessionName);
sqlUpdate(conn, query);
sessionTouchLastUse(conn, encUserName, encSessionName);
struct dyString *dyMsg = dyStringNew(256);
if (desired && shared < 2)
thumbnailAdd(encUserName, encSessionName, conn, dyMsg);
if (!desired && shared >= 2)
thumbnailRemove(encUserName, encSessionName, conn);
-dyStringFree(&dyMsg);
-char extra[32];
-safef(extra, sizeof(extra), ", \"shared\": %d", newShared);
-saveSessionJsonOk(conn, extra);
+/* Pass on anything thumbnailAdd had to say, e.g. that this mirror has no ImageMagick convert. The
+ * session is listed either way, but without this the reply is a bare success and the listing simply
+ * shows no picture. */
+struct dyString *dyExtra = dyStringNew(64);
+dyStringPrintf(dyExtra, ", \"shared\": %d", newShared);
+char *warning = thumbnailWarning(dyMsg);
+if (warning != NULL)
+ dyStringPrintf(dyExtra, ", \"warning\": \"%s\"", jsonStringEscape(warning));
+saveSessionJsonOk(conn, dyExtra->string);
}
void doOverwriteSessionJson(char *userName)
/* AJAX: re-save the current cart over an existing session (hgsOldSessionName), preserving its
* sharing level. Returns the refreshed created date, view count and assembly. */
{
struct sqlConnection *conn = hConnectCentral();
char *sessionName = trimSpaces(cloneString(cgiUsualString(hgsOldSessionName, "")));
if (isEmpty(userName))
{ saveSessionJsonError(conn, "Please log in and try again."); return; }
if (isEmpty(sessionName))
{ saveSessionJsonError(conn, "No session was specified."); return; }
if (!sqlTableExists(conn, namedSessionTable))
{ saveSessionJsonError(conn, "Required session table does not exist."); return; }
char *encUserName = cgiEncodeFull(userName);
char *encSessionName = cgiEncodeFull(sessionName);
char query[1024];
-sqlSafef(query, sizeof(query),
- "select count(*) from %s where userName = '%s' and sessionName = '%s';",
- namedSessionTable, encUserName, encSessionName);
-if (sqlQuickNum(conn, query) == 0)
+int shared = sessionSharedLevel(conn, encUserName, encSessionName);
+if (shared < 0)
{ saveSessionJsonError(conn, "Could not find that session to overwrite."); return; }
-sqlSafef(query, sizeof(query), "select shared from %s where userName = '%s' and sessionName = '%s';",
- namedSessionTable, encUserName, encSessionName);
-int shared = sqlQuickNum(conn, query);
int useCount = saveCartAsSession(conn, encUserName, encSessionName, shared);
/* Report the refreshed values so the table row can update in place. */
-boolean gotSettings = (sqlFieldIndex(conn, namedSessionTable, "settings") >= 0);
-(void)gotSettings;
sqlSafef(query, sizeof(query),
"select firstUse, contents from %s where userName = '%s' and sessionName = '%s';",
namedSessionTable, encUserName, encSessionName);
struct sqlResult *sr = sqlGetResult(conn, query);
char **row = sqlNextRow(sr);
char *dateOnly = NULL, *db2 = NULL;
if (row != NULL)
{
dateOnly = cloneString(row[0]);
char *spacePt = strchr(dateOnly, ' ');
if (spacePt != NULL)
*spacePt = '\0';
db2 = sessionValFromContents(row[1], "db");
}
sqlFreeResult(&sr);
@@ -2646,30 +2699,32 @@
{
struct sqlConnection *conn = hConnectCentral();
char *sessionName = trimSpaces(cloneString(cgiUsualString(hgsOldSessionName, "")));
char *newDescription = cloneString(cgiUsualString(hgsNewSessionDescription, ""));
cartRemove(cart, hgsNewSessionDescription);
if (isEmpty(userName))
{ saveSessionJsonError(conn, "Please log in and try again."); return; }
if (isEmpty(sessionName))
{ saveSessionJsonError(conn, "No session was specified."); return; }
boolean gotSettings = (sqlFieldIndex(conn, namedSessionTable, "settings") >= 0);
if (!gotSettings)
{ saveSessionJsonError(conn, "This server does not support session descriptions."); return; }
char *encUserName = cgiEncodeFull(userName);
char *encSessionName = cgiEncodeFull(sessionName);
char query[512];
+if (sessionSharedLevel(conn, encUserName, encSessionName) < 0)
+ { saveSessionJsonError(conn, "Could not find that session."); return; }
sqlSafef(query, sizeof(query), "select settings from %s where userName = '%s' and sessionName = '%s';",
namedSessionTable, encUserName, encSessionName);
char *settings = sqlQuickString(conn, query);
struct hash *settingsHash = raFromString(isEmpty(settings) ? "" : settings);
/* ra syntax needs \n / \r / backslash escaped (kept compatible with doSessionChange). */
newDescription = replaceChars(newDescription, "\\", "\\\\");
newDescription = replaceChars(newDescription, "\r", "\\r");
newDescription = replaceChars(newDescription, "\n", "\\n");
hashRemove(settingsHash, "description");
hashAdd(settingsHash, "description", newDescription);
struct dyString *dyRa = dyStringNew(512);
struct hashEl *hel = hashElListHash(settingsHash);
while (hel != NULL)
{
dyStringPrintf(dyRa, "%s %s\n", hel->name, (char *)hel->val);