'wordpress on apache2 running python as cgi

So here is what I want to do:

On my Raspi a python program is running. On a wordpress site the current state of the program should be displayed and some configurations should be changeable.

Here is the problem:

Whenever I want to execute the python script, I get a 500 error code. It doesn't matter if I just want to display the value or change it. I'm new to html, cgi and apache, tried a lot but now I have no clue how to continue. I'd appreciate it a lot if someone could point me in the right direction.

Here are my configurations:

Apache:

Edited the file /etc/apache2/apache2.conf:

<Directory /var/www/>
    Options +ExecCGI +Indexes +FollowSymLinks 
    AddHandler cgi-script .cgi .py
    AllowOverride None
    Require all granted
</Directory>

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
   Require all granted
</Directory>

<Directory "/var/www/cgi-bin">
    Options All
</Directory>

I also ran sudo a2enmod cgi

The webserver directory (/var/www/) looks like this:

.
├── cgi-bin
└── html
    ├── pma
    │   └── ...
    └── wordpress
        └── ...

Wordpress:

On a wordpress site, I go into the "text" mode and have the following html code:

Curent Value: <form action="/cgi-bin/apfautostartval.py" method="get"></form>

<form action="/cgi-bin/apfcgi.py" method="post" target="_blank">
<input name="autoTest" type="radio" value="True" /> True (do automatic scan)
<input name="autoTest" type="radio" value="False" /> False (do manual scan)
<input type="submit" value="Submit" /></form>

Python files:

The apfautostartval.py should just get the value from the config.ini and post it:

#!/usr/bin/python3

import configparser
import os
import cgi, cgitb 

cgitb.enable()    
# Create config parser
config = configparser.ConfigParser()
configFilePath = os.path.join(os.path.sep,"home","pi",..., "config.ini")

config.read(configFilePath)
print("Content-type: text/html")
print()
print("<!DOCTYPE html>")
print("<html>")
print("<body>")
print(str(config['SETTINGS']["autoTest"]))  
print("</body>")
print("</html>")

And finally the apfcgi.py should receive the submitted new value and write it to the config.ini:

#!/usr/bin/python3

import configparser
import os
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 
cgitb.enable()    
# Create config parser
config = configparser.ConfigParser()
configFilePath = os.path.join(os.path.sep,"home","pi",..., "config.ini")

print("Content-type: text/html")
print()
print("<!DOCTYPE html>")
print("<html>")
print("<body>")

# Receive autotest command from  web site 
if form.getvalue("autoTest"):
    config.read(configFilePath)
    if form.getvalue("autoTest").lower() == "true":
        config['SETTINGS']["autoTest"] = "True"
    else:
        config['SETTINGS']["autoTest"] = "False"

    with open(configFilePath, 'w') as configfile:
        config.write(configfile)    

print("</body>")
print("</html>")


Solution 1:[1]

I had the same problem. The problem was in the encoding. By default, ConfigParser.read() uses the encoding=none parameter. I specified utf-8 and it worked.

config = configparser.ConfigParser()
config.read(configFilePath, encoding='utf-8')

Solution 2:[2]

Ok I have found the solution for one part of the problem:

When changing the value make sure, you granted permissions to the file for cgi scripts:

in /etc/apache2/apache2.config add:

<Directory "/home/pi/dirToTheConfigFile/">
    Options +ExecCGI +Indexes +FollowSymLinks 
    AddHandler cgi-script .cgi .py
    AllowOverride None
    Require all granted
</Directory>

And make sure, the user www-data is allowed to modify the file.

In general add cgitb.enable() to your python scripts, so for html 500 errors you will get a detailed error message in the /var/log/apache2/error.log file

For receiving data the following Solution was found: The Python script was unfortunately owned by root and therefore cound not be executed. I changed the permissions.

The receiving html in the wordpress has been rewritten, too:

<iframe src="/cgi-bin/apfautostartval.py" width="100" height="29.5" frameborder="0" marginwidth="8" marginheight="0" scrolling="no" align="bottom"></iframe>

It's now an iframe and displays whatever is returned.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ???? ???????
Solution 2