1

I want to include some PHP plugins, which should be able to modify a single variable ($input). The function I am using is the following:

$globalVariable = 'Hello, World!';

function plugin($type, $file, $input){

    if($type == 'foo'){

          return include('../foo-plugins/' . $file);

    }
    else{

          return include('../bar-plugins/' . $file);

    }

}

And the plugin file:

<?php

    global $globalVariable; // This should not work

    echo $file; // This should not work
    echo $type; // This should not work

    return 'Hello ' . $input; // This should work

?>

This post explains how to pass a variable, but does not solve my problem as all variables are passed on.

How can I set the context for the included file so it only has access to the single variable $input?

I am open to any alternative approaches, that don't necessarily use include or require. Any help would be much appreciated!

Ood
  • 1,445
  • 4
  • 23
  • 43
  • To understand include/require, imagine PHP replacing that line with the contents of the file you've included/required. That means it will have access to anything that regular code in that spot would have access to, including `$file` and `$type`. If you only want to have access to certain variables, include is not the way to go about it. – aynber Nov 01 '22 at 16:56
  • @aynber What would you suggest to use instead of include or require? – Ood Nov 01 '22 at 16:57
  • Probably create another function or class *outside* of that function, and call it inside. – aynber Nov 01 '22 at 16:58
  • That would still have access to `global`. I will add that to my question. – Ood Nov 01 '22 at 17:00
  • Nor sure how you would be able to stop `global` from working if you're executing that PHP code during the same execution. – M. Eriksson Nov 01 '22 at 17:06
  • @M.Eriksson I would be happy to use any alternative approaches as long as the "external" code is isolated. – Ood Nov 01 '22 at 17:07
  • There might be some other ways, but the only ways I can think of would be to call the PHP file "stand alone" (like through `exec()`, `shell()`, a separate URL request, if it's on a server or something) and pass the variable you want them to be able to change and then grab the output. It would most likely be very ineffective though. – M. Eriksson Nov 01 '22 at 17:11
  • @M.Eriksson Thank you! That sounds like an acceptable solution for me. I will look into it. – Ood Nov 01 '22 at 17:12
  • They would still be able to acces the filename/path (for cli-calls) or the URL/script name (for web requests). It would more or less be equivalent to the `$file`-variable. Don't see how you can get past that though. – M. Eriksson Nov 01 '22 at 17:15
  • @M.Eriksson That is true, my only concern however is that that variables are isolated, which would be the case with this approach. – Ood Nov 01 '22 at 17:18

2 Answers2

1

Use a self-invoking anonymous function to isolate its variable scope locally:

  $globalVariable = 'Hello, World!';

  function plugin($type, $file, $input){
        if($type == 'foo') {
              return (function($file, $input) { 
                    return include('../foo-plugins/' . $file); 
              })($file, $input);
              
        } else {
              return (function($file, $input) { 
                    return include('../bar-plugins/' . $file); 
              })($file, $input);
        }
  }

However, there's nothing you can do to prevent it from accessing global variables in any scope. If global variables are a concern, the code should be run in a separate PHP process, for example by invoking it from the command line or as a separate HTTP request.

Mahn
  • 16,261
  • 16
  • 62
  • 78
  • Thank you! I think the best way to do this is by using a HTTP request like you mentioned. That way I can be sure the script is properly sandboxed. – Ood May 31 '23 at 20:36
1

There is a not perfect solution:

$globalVariable = 'Hello, World!';

  function plugin($type, $file, $input){
        $inst94a3u76bc0 = new \stdClass();
        $inst94a3u76bc0->file = $file;
        $inst94a3u76bc0->type = $type;

        unset($type, $file); // Unset them to avoid variable pollution.

        if($inst94a3u76bc0->type == 'foo') {
              return include('../foo-plugins/' . $inst94a3u76bc0->file); 
              
        } else {
              return include('../bar-plugins/' . $inst94a3u76bc0->file); 
        }
  }

However, this can not isolate the global declaration.

token yi
  • 11
  • 3