@tobiastu / Unsplash

A new (to me) PHP trick - include

When your CMS persists config data to files, sometimes it is simply easier to cut out the middleman and just read the data yourself.

I had a need to identify the types of files that users are allowed to upload, and monitor the list for potential mistakes/insecure file-types. Cocnrete5 persists that data in a way that is easily viewable, thus easily scriptable.

Temet Nosce

Concrete5 is a Wordpress competitor with a number of nice-to-have editing features. However, some of the design choices seem, from my perspective, odd. One of the more puzzling ones is to generate php files from config data. I’ve always been a fan of trying to separate data from code, and config data certainly doesn’t seem to belong with the code so far as I’m concerned. Regardless, this is a sample of the data I have to work with:

# concrete/config/concrete.php
# (edited for brevity and appearance)
<?php
return array(
    /**
     * Installation status
     * @var bool
     */
    'installed'         => true,
    /**
     * The current Locale
     */
    'locale'            => 'en_US',
    /**
     * The current Charset
     */
    'charset'           => 'UTF-8',
    /**
     * Maintenance mode
     */
    'maintenance_mode'  => false,
    /**
     * ----------------------------------------------------
     * File upload settings
     * ----------------------------------------------------
     */
    'upload'            => array(
        /**
         * Allowed file extensions
         * @var string semi-colon separated.
         */
        'extensions' => '*.flv;*.jpg;*.gif;*.jpeg;*.ico;*.docx;' .
	    '*.xla;*.png;*.psd;*.swf;*.doc;*.txt;*.xls;*.xlsx;' .
            '*.csv;*.pdf;*.tiff;*.rtf;*.m4a;*.mov;*.wmv;*.mpeg;' .
	    '*.mpg;*.wav;*.3gp;*.avi;*.m4v;*.mp4;*.mp3;*.qt;*.ppt;' .
            '*.pptx;*.kml;*.xml;*.svg;*.webm;*.ogg;*.ogv'
    ),
);

That file gets regenerated at various times, usually as configuration values change.

The data I want is right there; how do I get it?

Old dog, new trick

I’ve been using PHP require almost exclusively since I wanted to move beyond a “Hello, World!” script. But require (and my preferred variant: require_once) don’t actually give me anything useful from the generated file.

PHP’s documentation on include has exactly the info I needed, but I will confess I only found it because of an answered question on Stack Overflow that Google helpfully found for me.

Exactly how hard is it to get that data?

$settings_path = "/path/to/your/concrete/config/concrete.php";
$settings = include $settings_path;
echo $settings["upload"]["extensions"];

Done.

Quis custodiet ipsos custodes?

The rest of the story is relatively banal: wrap the php script in a bash script, then expose the bash/wrapper script to your favorite monitoring system (Zabbix is in use at my employer). If you’re interested in a more thorough look, I created a Gist to help someone, likely me, do this exact thing.