af6898753ba6d5f3872957cd270872ce4c4e3dfc max Tue Apr 11 08:19:27 2023 -0700 tolerate if browser CSS theme files do not exist, cleaning up the resource link mess a little, refs #7867 diff --git src/hg/lib/web.c src/hg/lib/web.c index 360ff9b..58247fc 100644 --- src/hg/lib/web.c +++ src/hg/lib/web.c @@ -1207,30 +1207,74 @@ } } void webFinishPartialLinkOutTable(int rowIx, int itemPos, int maxPerRow) /* Fill out partially empty last row. */ { finishPartialTable(rowIx, itemPos, maxPerRow, webPrintLinkOutCellStart); } void webFinishPartialLinkTable(int rowIx, int itemPos, int maxPerRow) /* Fill out partially empty last row. */ { finishPartialTable(rowIx, itemPos, maxPerRow, webPrintLinkCellStart); } +static struct dyString* getHtdocsSubdir(char *dirName) +/* return dystring with subdirectory under htDocs, tolerant of missing docRoot */ +{ +struct dyString *fullDirName = NULL; +char *docRoot = hDocumentRoot(); +if (docRoot != NULL) + fullDirName = dyStringCreate("%s/%s", docRoot, dirName); +else + // tolerate missing docRoot (i.e. when running from command line) + fullDirName = dyStringCreate("%s", dirName); +return fullDirName; +} + +char *webCssLink(char *fileName, boolean mustExist) +/* alternative for webTimeStampedLinkToResource for CSS files: returns a string with a time-stamped + * link to a CSS file as a html fragment . returns empty string if file does not exist. + * */ +{ +// construct the absolute path to the file on disk +char *relDir = cfgOptionDefault("browser.styleDir","style"); +struct dyString *absDir = getHtdocsSubdir(relDir); +struct dyString *absFileName = dyStringCreate("%s/%s", dyStringContents(absDir), fileName); + +struct dyString *htmlFrag = NULL; +if (!fileExists(dyStringContents(absFileName))) + { + if (mustExist) + errAbort("webTimeStampedLinkToResource: file: %s doesn't exist.\n", + dyStringContents(absFileName)); + else + htmlFrag = dyStringNew(0); + } +else + { + // construct a link with the relative path to the file on the web server + long mtime = fileModTime(dyStringContents(absFileName)); + htmlFrag = dyStringCreate("\n", relDir, fileName, mtime); + } + +dyStringFree(&absFileName); +dyStringFree(&absDir); +return dyStringContents(htmlFrag); +} + char *webTimeStampedLinkToResource(char *fileName, boolean wrapInHtml) // If wrapInHtml // returns versioned link embedded in style or script html (free after use). // else // returns full path of a versioned path to the requested resource file (js, or css). // NOTE: png, jpg and gif should also be supported but are untested. // // In production sites we use a versioned softlink that includes the CGI version. This has the following benefits: // a) flushes user's web browser cache when the user visits a GB site whose version has changed since their last visit; // b) enforces the requirement that static files are the same version as the CGIs (something that often fails to happen in mirrors). // (see notes in redmine #3170). // // In dev trees we use mtime to create a pseudo-version; this forces web browsers to reload css/js file when it changes, // so we don't get odd behavior that can be caused by caching of mis-matched javascript and style files in dev trees. // @@ -1248,37 +1292,39 @@ || sameString(".jpg",extension) || sameString(".gif",extension)); if (!js && !style) // && !image) NOTE: This code has not been tested on images but should work. errAbort("webTimeStampedLinkToResource: unknown resource type for %s.\n", fileName); char *httpHost = hHttpHost(); // Build and verify directory char *dirName = ""; if (js) dirName = cfgOptionDefault("browser.javaScriptDir", "js"); else if (style) dirName = cfgOptionDefault("browser.styleDir","style"); else if (image) dirName = cfgOptionDefault("browser.styleImagesDir","style/images"); + struct dyString *fullDirName = NULL; char *docRoot = hDocumentRoot(); if (docRoot != NULL) fullDirName = dyStringCreate("%s/%s", docRoot, dirName); else // tolerate missing docRoot (i.e. when running from command line) fullDirName = dyStringCreate("%s", dirName); + if (!fileExists(dyStringContents(fullDirName))) errAbort("webTimeStampedLinkToResource: dir: %s doesn't exist. (host: %s)\n", dyStringContents(fullDirName), httpHost); // build and verify real path to file struct dyString *realFileName = dyStringCreate("%s/%s", dyStringContents(fullDirName), fileName); if (!fileExists(dyStringContents(realFileName))) errAbort("webTimeStampedLinkToResource: file: %s doesn't exist.\n", dyStringContents(realFileName)); // build and verify link path including timestamp in the form of dir/baseName + timeStamp or CGI Version + ext long mtime = fileModTime(dyStringContents(realFileName)); struct dyString *linkWithTimestamp; linkWithTimestamp = dyStringCreate("%s/%s%s?v=%ld", dyStringContents(fullDirName), baseName, extension, mtime);