Use config file for both php and bash scripts

Can anyone with php experience please assist with some code for further development of the dropbox-uploader (emoncms cloud backup).

I’ve created a settings.cfg file to hold the configuration settings;

emoncms_apikey="377cc1sds87sdjckssk22b95"
dbuser="emoncms"
dbpass="priceless"
dbname="emoncms"
etc, etc

Which need to be accessed by both php AND bash scripts, so using this code in the php script;

<?php

$fh=fopen("settings.conf", "r");
while ($line=fgets($fh, 80)) {
  if (preg_match('/^[a-z]+=("[a-z0-9]+"|[0-9]+)$/', $line)) {
    $line_a=explode("=", $line);
    $conf[$line_a[0]]=$line_a[1];
  }
}
extract($conf);
echo "$dbuser";

…I can import the settings.conf as an array, and then extract the values. All good so far! However;
echo "$dbuser";
returns the value “emoncms” - whereas I need emoncms

Anyone any ideas how to remove the quotes.

Paul

Have you tried without the quotes?

echo $dbuser;

Yes, same result - “emoncms”

If I examine the array using;

print_r($conf);

I get:

[dbuser] => "emoncms"
[dbpass] => "priceless"
[dbname] => "emoncms"
[store] => "7"

Paul

you don’t want to remove the quotes from the config file? or will that cause the while loop to fail as it builds the array?

Yes, correct. Removing the quotes breaks the process.

Paul

I think the way the conf file is being read is as string lines rather than variable = value pairs. A quick php only fix might be to remove the quotes in the conf eg dbuser = emoncms so the quotes are not included as part of the string, but that won’t work in bash so I think you will need to remove the quotes whilst parsing the strings eg

$conf[$line_a[0]]=trim($line_a[1],‘"’);

Getting there! that removes the leading " but the trailing " still remains.

emoncms"

Paul

Here’s one way to do it in bash:

$dbuser=${dbuser//\"}

That’ll zap both leading and trailing quotes.

That’s odd, are you using a double quote in single quotes in the trim? eg

trim($string,’ " ');

I’ve sorted the bash script Bill, it’s the php script which is proving a pain.

Paul

Yes, this is a copy/paste;

$fh=fopen("settings.conf", "r");
while ($line=fgets($fh, 80)) {
  if (preg_match('/^[a-z]+=("[a-z0-9]+"|[0-9]+)$/', $line)) {
    $line_a=explode("=", $line);
    $conf[$line_a[0]]=trim($line_a[1],'"');
  }
}

Paul

OK. I took your post to mean you needed to pass variables to bash, and that it was bash that was having trouble reading them.

Here’s another PHP method for stripping the quote marks from a string:

Thanks Bill, but rather than removing the quotes from each string individually, it would be much cleaner if they could be removed whilst parsing the strings from the array. @pb66 is almost there with this solution, except it only removes the leading quote, and the trailing quote remains.

Paul

I’m not sure why the trim() doesn’t work, I can only assume there is something not visible (whitespace,tab,newline,null byte) on the end of the string blocking the trim (ie the double quote isn’t actually at the end)

I’m not familiar enough with php to know what that something could be from looking at the code.

@Bill.Thomson’s suggestion can be used during the parse process eg

$conf[$line_a[0]]=preg_replace(‘"’, “”, $line_a[1]);

should remove all double quotes, which means any strings containing double quotes(it is possible using escapes although perhaps unlikely to see) would be a problem.

There is also a possibility that whatever is stopping the trim may bite you now or later if sidestepped rather than understood and handled.

Although trim is designed for the task, I’d expect this to be fine to just remove ALL double quotes.

As with the trim function, you will need to nest or repeat parts of the code to cover both double and single quotes or alternatively just specify only double to be used.

1 Like

Yes, that was the issue!
Added a ‘trim’ to line 4 to remove the whitespace (and a few regex changes to capture URL’s), and appears to work ok now.

while ($line=fgets($fh, 80)) {
  if (preg_match('/^[a-zA-Z_]+=("[a-zA-Z:.0-9_\/]+")/', $line)) {
  //  $line_a=explode("=", $line);
    $line_a=array_map('trim',explode("=", $line));
    $conf[$line_a[0]]=trim($line_a[1], '"');
  }
}

results in…

Array
(
    [emoncms_server] => http://192.168.1.10/emoncms
    [emoncmsapikey] => 343h34h3j3hh34ijjdsds
    [dbuser] => emoncms
    [dbpass] => myPassword
    [dbname] => emoncms
    [datadir] => var
    [store] => 7
    [nodered] => Y
    [NRdir] => url:/192.url
)

Thanks for the help @pb66 & @Bill.Thomson

Paul

YW. Good to see you got it running!

My regexp is a bit rusty, but as a matter of interest why not just use 2 capture groups and remove the quotes at the same time? You could even make the first, any character (unless PHP is fussy about variable names).

^([a-zA-Z_]+)=“(.*)”

Thanks Brian, yes, that’s better!

I’ve made a further change too, by stopping the white-space occurring by modifying preg_match, instead of removing it later with trim.
To conclude, all 3 files are pasted below;

**** Settings ****
Edit and add your settings below, and save this file back as settings.conf

emoncms local IP address
emoncms_server="http://192.168.1.10/emoncms"

Needs to be emoncms write API key
emoncmsapikey=""

Database user name - default is emoncms
dbuser="emoncms"

Database user password
dbpass=""

Database name - default is emoncms
dbname="emoncms"

Path to emoncms data directories
datadir="/var/lib"

Create archive backups of node-red flows, configs etc. Y or N
nodered="N"

Node-red backup dir, default is /home/pi/.node-red
NRdir="/home/pi/.node-red"

Number of days of archives to store
store="7"

PHP file;

#!/usr/local/bin/php
<?php

$fh=fopen("settings.conf", "r");
$pattern='/^(\w+)="([\w\/\.\:]+)"/';
while ($line=fgets($fh, 80)) {

if (preg_match($pattern, $line, $match)) {
     $conf[$match[1]]=$match[2];
     }
}

print_r($conf);

extract($conf);

echo "$dbuser\n";
echo "$emoncms_server\n";
echo "$NRdir\n";
echo "$store\n";

…and the Bash file;

#!/bin/bash
eval `egrep '^([a-zA-Z_]+)="(.*)"' settings.conf`

echo "$dbuser"
echo "$emoncms_server"
echo "$NRdir"
echo "$store"

Paul

On the basis of TIMTOWTDI, you don’t need the explode or trim (I think), so (untested):

$pattern='/^(\w+)="([\w\/\.\:]+)"/';

if (preg_match($pattern, $line, $match) {
     $conf[$match[1]]=$match[2];
     }

{can’t remember how to get the code to colour!}
EDIT - edit your post Brian to see! - Ah excellent - noticed I had missed out the slashes around the regexp :frowning:

That works OK after adding an extra ) in the preg_match line, however despite the revised regex expression working fine in php, it strangely doesn’t work in the bash script?

Not a problem though, your previous regex exp works fine.

I’ve updated my post above with this change.

Paul