ComboStrap / combo

Dokuwiki Combo Plugin. Making Web Publication a Breeze
https://combostrap.com
GNU General Public License v2.0
15 stars 3 forks source link

LocalPath's relativize() fails in some cases #70

Open robertoea opened 1 year ago

robertoea commented 1 year ago

Checking ...->isSymlink() might not be enough, because it might be (one of) the ancestor's directories that is symlinked. Also, the $localPath->isSymlink() condition in relativize() might be missing a return.

Background: Creating a new page doesn't work on my instance after upgrading combostrap to the new major version. My dokuwiki is set up on a symlinked dir and looking at the error log it appeared that combo failed to relativize the file path. Forcing canonical absolute path resolution solved the issue.

gerardnico commented 1 year ago

Thanks for reporting. I miss it, I don't know how.

Can I have your case specifically so that I can test it. Where is the symlink?

robertoea commented 1 year ago

Basically my web hosting provider set up the directories like this:

domains
  example.com (primary domain)
    private_html --> symlinked to ../example.com/public_html
    public_html
      wiki
  alias.com (add-on domain)
    private_html --> symlinked to ../alias.com/public_html
    public_html --> symlinked to ../example.com/public_html
private_html --> symlinked to example.com/private_html
public_html --> symlinked to example.com/public_html

When accessing https://wiki.alias.com, pages will be served from domains/alias.com/private_html/wiki (which resolves to domains/example.com/public_html/wiki).

gerardnico commented 1 year ago

Thanks. Sorry for the inconvenience, that's infuriating, I know. Combostrap file system should stay on the physical path (ie domains/example.com/public_html/wiki)

I still don't see the relativization that does not work.

What do you mean with Forcing canonical absolute path resolution solved the issue.

Thanks Nico

Ps for me later, the code location are:

gerardnico commented 1 year ago

I took a look at the installation and its strange that you got wiki/ in the boostrap resources. ie https://cdn.jsdelivr.net/wiki//npm/bootstrap@5.0.1/dist/css/bootstrap.min.css Why? Because it's hard coded.

robertoea commented 1 year ago

Basically the symptom was that when I created or edited a new page, I got an error The local path ($path) is not inside a wiki path drive.

IIRC, Dokuwiki tried to add a file in public_html/wiki/data, but the driveRoot was detected in private_html. Either that, or the other way around.

I think I just commented out the conditions that checked isAbsolute so toCanonicalAbsolutePath is always called:

public function relativize(LocalPath $localPath): LocalPath
    {

        /**
         * One of the problem of relativization is
         * that it may be:
         * * logical (when using a symling)
         * * physical
         */
        //if (!$this->isAbsolute() || $this->isShortName()) {
            /**
             * This is not a logical resolution
             * (if the path is logically not absolute and is a symlink,
             * we have a problem)
             */
            $actualPath = $this->toCanonicalAbsolutePath();
        //} else {
        //    $actualPath = $this;
        //}
        //if (!$localPath->isAbsolute() || $localPath->isShortName()) {
            $localPath = $localPath->toCanonicalAbsolutePath();
        //}

        if (strpos($actualPath->toAbsoluteId(), $localPath->toAbsoluteId()) === 0) {
            if ($actualPath->toAbsoluteId() === $localPath->toAbsoluteId()) {
                return LocalPath::createFromPathString("");
            }
            $sepCharacter = 1; // delete the sep characters
            $relativePath = substr($actualPath->toAbsoluteId(), strlen($localPath->toAbsoluteId()) + $sepCharacter);
            $relativePath = str_replace($this->getDirectorySeparator(), WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT, $relativePath);
            return LocalPath::createFromPathString($relativePath);
        }
        /**
         * May be a symlink link
         */
        if ($this->isSymlink()) {
            $realPath = $this->toCanonicalAbsolutePath();
            return $realPath->relativize($localPath);
        }
        if ($localPath->isSymlink()) {
            $localPath = $localPath->toCanonicalAbsolutePath();
            $this->relativize($localPath);
        }
        throw new ExceptionBadArgument("The path ($localPath) is not a parent path of the actual path ($actualPath)");

    }
gerardnico commented 1 year ago

It would be great if I can have the stack trace in the log to see where the relativize function was called during the creation because recreating your environment is a lot of work.

robertoea commented 1 year ago

I don't have access to the server at the moment, but IIRC it's called from createFromPathObject in WikiPath.php.

gerardnico commented 1 year ago

I want the stack trace to go way back until the creation of the page. I'll wait.

In this function, the code throws an exception, where we can see the paths involved and the whole code path. During the page creation, at some point, the paths passed are not good.

gerardnico commented 1 year ago

If there is a symlink in a child folder (generally the data folder), the relativization will not work if we take the canonical path.

The file would be at: /data-dokuwiki/pages/xxxx and the folder would be at /dokuwiki/data/pages while logically the file is at: /dokuwiki/data/pages/xxxx I try to do the resolution always logically by default.

robertoea commented 1 year ago

Is this what you need?

An error has occurred

An error has occurred during the execution of the action (combo_page)

Error (only seen by manager):

The local path (file:///home/user/domains/example.com/public_html/wiki/data/pages/slot_header.txt) is not inside a wiki path drive

#0 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/LocalPath.php(239): ComboStrap\WikiPath::createFromPathObject()
#1 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/FetcherMarkupBuilder.php(134): ComboStrap\LocalPath->toWikiPath()
#2 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/FetcherMarkup.php(178): ComboStrap\FetcherMarkupBuilder->setRequestedExecutingPath()
#3 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/TemplateSlot.php(212): ComboStrap\FetcherMarkup::createXhtmlMarkupFetcherFromPath()
#4 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/FetcherPage.php(263): ComboStrap\TemplateSlot->getMarkupFetcher()
#5 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/ComboStrap/FetcherPage.php(132): ComboStrap\FetcherPage->buildObjectIfNeeded()
#6 /home/user/domains/example.com/public_html/wiki/lib/plugins/combo/action/docustom.php(180): ComboStrap\FetcherPage->getFetchString()
#7 /home/user/domains/example.com/public_html/wiki/inc/Extension/EventHandler.php(80): action_plugin_combo_docustom->executeComboDoAction()
#8 /home/user/domains/example.com/public_html/wiki/inc/Extension/Event.php(74): dokuwiki\Extension\EventHandler->process_event()
#9 /home/user/domains/example.com/public_html/wiki/inc/ActionRouter.php(80): dokuwiki\Extension\Event->advise_before()
#10 /home/user/domains/example.com/public_html/wiki/inc/ActionRouter.php(48): dokuwiki\ActionRouter->setupAction()
#11 /home/user/domains/example.com/public_html/wiki/inc/ActionRouter.php(60): dokuwiki\ActionRouter->__construct()
#12 /home/user/domains/example.com/public_html/wiki/inc/actions.php(16): dokuwiki\ActionRouter::getInstance()
#13 /home/user/domains/example.com/public_html/wiki/doku.php(126): act_dispatch()
#14 {main}
gerardnico commented 1 year ago

Yes.

I have symlinked the DokuWiki root installation on my environment and it works. Maybe it comes from the wiki sub-directory configuration. Still searching.

This is the Apache configuration that I have used:

<VirtualHost *:80>
    DocumentRoot "d:/dokuwiki-symlink"
    ServerName combo.nico.lan
    DirectoryIndex index.php
    <Directory "d:/dokuwiki-symlink" >
        Require all granted
        AllowOverride All
        Options Indexes FollowSymLinks Includes ExecCGI
    </Directory>
</VirtualHost>

Do you know your HTTP server configuration?

gerardnico commented 1 year ago

If you add ?do=admin&page=config to your URL in order to go to the configuration. Can you give me the configuration that you have in savedir and basedir ?

image

I'm trying to see the configuration value $conf['datadir']. This is where the pages are stored.

At least, as you seem to have a bit of Php knowledge, in a PHP script, you can do

global $conf;
$pageDirectory = $conf['datadir'];
echo $pageDirectory

Ps: I use a farm therefore the symlink does not impact the data configuration....

gerardnico commented 1 year ago

If you set the savedir to the real location of your files

robertoea commented 1 year ago

savedir is ./data basedir is empty $pageDirectory is /home/user/domains/example.com/private_html/wiki/data/pages

If I set savedir to the real location I don't have the problem anymore.

gerardnico commented 1 year ago

Thanks! I will let this problem cool down to work on the best approach to solve this particular problem.