01423: CondAuth in farmconfig.php disables $DefaultPasswords in config.php

Summary: CondAuth in farmconfig.php disables $DefaultPasswords in config.php
Created: 2017-10-11 09:50
Status: Open
Category: Bug
From: Finar
Assigned:
Priority: 4
Version: 2.2.103
OS: xampp, VDS

Description: Let's make a WikiFarm.

http://localhost:8888/wiki1, farmconfig.php:

$WikiTitle = 'PARENT WikiFARM';
$FarmPubDirUrl = 'http://localhost:8888/wiki1_2-2-95/pub';
include_once("$FarmD/scripts/xlpage-utf-8.php");

http://localhost:8888/wiki2, config.php:

$WikiTitle = 'DAUGHTER WikiFARM';
$DefaultPasswords['read'] = 'secret';

Go to http://localhost:8888/wiki2 -- it will ask for password as expected.

Now, modify farmconfig.php this way:

$WikiTitle = 'PARENT WikiFARM';
$FarmPubDirUrl = 'http://localhost:8888/wiki1_2-2-95/pub';
include_once("$FarmD/scripts/xlpage-utf-8.php");

if (CondAuth($pagename, 'edit')) {
  // do nothing
}

Now, go to http://localhost:8888/wiki2 -- it will NOT ask for password!

I think, this problem is related to CondAuth. I also checked v 2.2.103 - the same result.

Finar October 11, 2017, at 09:51 AM

First, see $CookiePrefix -- you may simply need to set different prefixes in the different config.php files.

Yes, calling core functions from config files is tricky because PmWiki caches some of the user permissions. It is recommended to call these functions like CondAuth, RetrieveAuthPage, PageVar, PageTextVar, ResolvePageName and others after all possible local config files are included. In your case, I'd try this:

### near the end of (farm)config.php, add 3 lines:
if (file_exists("$LocalDir/config.php")) include_once("$LocalDir/config.php");
$pagename = ResolvePageName($pagename);
include_once("$FarmD/scripts/pgcust.php");

### then call CondAuth, PageVar or other core function directly
if (CondAuth($pagename, 'edit')) {
  // do something
}

Another way is to use a $PostConfig entry:

function MyFuncRunAfterConfig($pagename) {
  global $WikiTitle; # whatever you need
  if (CondAuth($pagename, 'edit')) {
    // do something
  }
}

# call after local/ config.php, Group.Page.php and Group.php:
$PostConfig['MyFuncRunAfterConfig'] = 40; # < 50

# OR, call function after local/ and after scripts/stdconfig.php:
$PostConfig['MyFuncRunAfterConfig'] = 60; # > 50

Again, this may be tricky, try it and report if it works or not. --Petko October 11, 2017, at 10:27 AM

Thank you,Petko!

I tried $CookiePrefix, it didn't help. Then I placed if (file_exists("$LocalDir/config.php")) include_once("$LocalDir/config.php"); one line before calling CondAuth, and this helped.

It could be solution, but in real project I have huge farmconfig.php and big config.php. And CondAuth is called few times in farmconfig.php I think it is not good idea to include big config.php in the middle of farmconfig.php, because of some unpredictable porblems will occur for sure.

As far as this is the only one known problem with my farm, for now I'm going to fix it this way:

// permissions must store in separate file, see http://www.pmwiki.org/wiki/PITS/01423
if (file_exists("$LocalDir/config-permissions.php")) include_once("$LocalDir/config-permissions.php");
if (CondAuth($pagename, 'edit')) {
...

So, I have to make separate files in DAUTHERs wikis if I want to change default permisssions.

If you will not say that it is very bad idea, I will try it tomorrow :)

Finar October 11, 2017, at 11:40 AM

In that case I'd try doing it the other way around: move all code that calls CondAuth, PageVar, etc. to a separate file in the farm's local directory, then place in farmconfig.php and/or config.php such lines:

  $PostConfig["$FarmD/local/farmconfig-extra.php"] = 40; # < 50
  $PostConfig["$LocalDir/config-extra.php"] = 45; # < 50

Then these external scripts will be included after farmconfig.php, config.php, Group.Page.php and Group.php. This has less chance to go wrong.

In fact, all these functions were designed to be called from within a Markup processing function when the page HTML is output, much later, long after config.php. It is not recommended to call them from local php files directly. There should be a way to rewrite your application logic to not call them directly, otherwise maybe call them at the very very end of the configuration part. --Petko October 12, 2017, at 06:38 AM

Thank you,Petko! Greate advice!

Finishing this theme, probably could you suggest better solution for (farm)config.php to get know, if current user has 'edit' rights, instead of using CondAuth()? And the best way to get current PageName and GroupName (instead of using PageVar())? Thanks!

Finar October 12, 2017, at 08:37 AM

It depends on why, and do I really, need to know these things that early. If it is to enable some ?action, I'd set $HandleAuth or $AuthCascade accordingly. If it is something to be enabled or printed/output for a user with edit rights, I'd use Conditional Markup, or if I have some complex custom markup, I could perform the CondAuth() check at the beginning of my markup function. The best way to get the GroupName is to simply place my code in local/GroupName.php, or use another Conditional Markup.

At any rate, before calling these functions I need to call $pagename = ResolvePageName($pagename); and this needs to be done after config.php: if I have a farmconfig.php, first include config.php like I did above, then ResolvePageName(), then using PageVar() is less risky; if I only have config.php, call ResolvePageName() at the very bottom and after it call PageVar().

Using a $PostConfig entry will make sure all configuration files have already been processed and no further PHP code is likely to change either permissions or page names:

  $PostConfig['MyFunctionName'] = 20; 
  $PostConfig["local/after_config.php"] = 44; 
  $PostConfig["local/after_stdconfig.php"] = 100; 

If the $PostConfig key is a function name, it will be called with the $pagename argument, like MyFunctionName($pagename), remember to declare your global variables. Otherwise, if a file exists with that name, it will be included. These entries will be ordered by the value, first 20, then 44, then 100, and if that number is < 50, it will be called after Group.Page.php and Group.php; if the number is >= 50 it will be called after stdconfig.php.

Of course, if your $PostConfig code does change user permissions or page names, then the results may be unpredictable. --Petko October 12, 2017, at 09:49 AM