mingled; $replaceExt = $destinationOptions->replaceExt; $useDocRoot = $destinationOptions->useDocRoot; try { // Check source // -------------- // TODO: make this check work with symlinks //$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source); // Calculate destination and check that the result is sane // ------------------------------------------------------- if (self::storeMingledOrNot($source, $mingled, $uploadDirAbs)) { $destination = self::appendOrSetExtension($source, $mingled, $replaceExt, true); } else { if ($useDocRoot) { // We must find the relative path from document root to source. // However, we dont know if document root is resolved or not. // We also do not know if source begins with a resolved or unresolved document root. // And we cannot be sure that document root is resolvable. // Lets say: // 1. document root is unresolvable. // 2. document root is configured to something unresolved ("/my-website") // 3. source is resolved and within an image root ("/var/www/my-website/wp-content/uploads/test.jpg") // 4. all image roots are resolvable. // 5. Paths::canUseDocRootForRelPaths()) returned true // Can the relative path then be found? // Actually, yes. // We can loop through the image roots. // When we get to the "uploads" root, it must neccessarily contain the unresolved document root. // It will in other words be: "my-website/wp-content/uploads" // It can not be configured to the resolved path because canUseDocRootForRelPaths would have then returned false as // It would not be possible to establish that "/var/www/my-website/wp-content/uploads/" is within document root, as // document root is "/my-website" and unresolvable. // To sum up, we have: // If document root is unresolvable while canUseDocRootForRelPaths() succeeded, then the image roots will all begin with // the unresolved path. // In this method, if $useDocRootForStructuringCacheDir is true, then it is assumed that canUseDocRootForRelPaths() // succeeded. // OH! // I realize that the image root can be passed as well: // $imageRoot = $webExpressContentDirAbs . '/webp-images'; // So the question is: Will $webExpressContentDirAbs also be the unresolved path? // That variable is calculated in WodConfigLoader based on various methods available. // I'm not digging into it, but would expect it to in some cases be resolved. Which means that relative path can not // be found. // So. Lets play it safe and require that document root is resolvable in order to use docRoot for structure if (!PathHelper::isDocRootAvailable()) { throw new \Exception( 'Can not calculate destination using "doc-root" structure as document root is not available. $_SERVER["DOCUMENT_ROOT"] is empty. ' . 'This is probably a misconfiguration on the server. ' . 'However, WebP Express can function without using documument root. If you resave options and regenerate the .htaccess files, it should ' . 'automatically start to structure the webp files in subfolders that are relative the image root folders rather than document-root.' ); } if (!PathHelper::isDocRootAvailableAndResolvable()) { throw new \Exception( 'Can not calculate destination using "doc-root" structure as document root cannot be resolved for symlinks using "realpath". The ' . 'reason for that is probably that open_basedir protection has been set up and that document root is outside outside that open_basedir. ' . 'WebP Express can function in that setting, however you will need to resave options and regenerate the .htaccess files. It should then ' . 'automatically stop to structure the webp files as relative to document root and instead structure them as relative to image root folders.' ); } $docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/'); $imageRoot = $webExpressContentDirAbs . '/webp-images'; // TODO: make this check work with symlinks //SanityCheck::absPathIsInDocRoot($imageRoot); $sourceRel = substr(realpath($source), strlen($docRoot) + 1); $destination = $imageRoot . '/doc-root/' . $sourceRel; $destination = self::appendOrSetExtension($destination, $mingled, $replaceExt, false); // TODO: make this check work with symlinks //$destination = SanityCheck::absPathIsInDocRoot($destination); } else { $destination = ''; $sourceResolved = realpath($source); // Check roots until we (hopefully) get a match. // (that is: find a root which the source is inside) foreach ($imageRoots->getArray() as $i => $imageRoot) { // in $obj, "rel-path" is only set when document root can be used for relative paths. // So, if it is set, we can use it (beware: we cannot neccessarily use realpath on document root, // but we do not need to - see the long comment in Paths::canUseDocRootForRelPaths()) $rootPath = $imageRoot->getAbsPath(); /* if (isset($obj['rel-path'])) { $docRoot = rtrim($_SERVER["DOCUMENT_ROOT"], '/'); $rootPath = $docRoot . '/' . $obj['rel-path']; } else { // If "rel-path" isn't set, then abs-path is, and we can use that. $rootPath = $obj['abs-path']; }*/ // $source may be resolved or not. Same goes for $rootPath. // We can assume that $rootPath is resolvable using realpath (it ought to exist and be within open_basedir for WP to function) // We can also assume that $source is resolvable (it ought to exist and within open_basedir) // So: Resolve both! and test if the resolved source begins with the resolved rootPath. if (strpos($sourceResolved, realpath($rootPath)) !== false) { $relPath = substr($sourceResolved, strlen(realpath($rootPath)) + 1); $relPath = self::appendOrSetExtension($relPath, $mingled, $replaceExt, false); $destination = $webExpressContentDirAbs . '/webp-images/' . $imageRoot->id . '/' . $relPath; break; } } if ($destination == '') { return false; } } } } catch (SanityException $e) { return false; } return $destination; } }