2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-21 07:56:03 +00:00

02_HTTPAPI.pm: syntax check extended, device attributes disable and ignore now lock the command execution

git-svn-id: https://svn.fhem.de/fhem/trunk@26272 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klaus.schauer 2022-07-29 16:32:39 +00:00
parent e4598cf2c9
commit a99778137d

View File

@ -34,28 +34,47 @@ sub HTTPAPI_Initialize($) {
$hash->{ReadFn} = "HTTPAPI_Read"; $hash->{ReadFn} = "HTTPAPI_Read";
$hash->{UndefFn} = "HTTPAPI_Undef"; $hash->{UndefFn} = "HTTPAPI_Undef";
$hash->{AttrList} = "disable:0,1 devicesCtrl " . $readingFnAttributes; $hash->{AttrList} = "disable:0,1 devicesCtrl " . $readingFnAttributes;
$hash->{parseParams} = 1;
return undef; return undef;
} }
sub HTTPAPI_Define($$) { sub HTTPAPI_Define($$) {
my ($hash, $def) = @_; my ($hash, $a, $h) = @_;
my @param = split("[ \t][ \t]*", $def); my $name = $a->[0];
my ($name, $type, $apiName, $pport, $global) = split("[ \t]+", $def); if (defined $a->[2]) {
my $port; $hash->{INFIX} = $a->[2];
if (defined $pport) { $infix = $a->[2];
$port = $pport; } elsif (exists $h->{infix}) {
$port =~ s/^IPV6://; $hash->{INFIX} = $h->{infix};
return "Usage: define <name> HTTPAPI [<infix>] [[IPV6:]<tcp-portnr>] [global|local|<hostname>]" if ($port !~ m/^\d+$/); $infix = $h->{infix};
} else {
$hash->{INFIX} = $infix;
}
# check if valid folder name
if ($hash->{INFIX} !~ /^[^\\\/\?\*\"\'\>\<\:\|]*$/) {
return "HTTPAPI: wrong syntax, correct is: define <name> HTTPAPI [infix=]<infix> [port=][[IPV6:]<port>] [global=][global|local|<hostname>]";
}
my ($pport, $port);
if (defined $a->[3]) {
$pport = $a->[3];
} elsif (exists $h->{port}) {
$pport = $h->{port};
} else { } else {
$port = $tcpServPort;
$pport = $tcpServPort; $pport = $tcpServPort;
} }
$global = $global // $tcpServAdr; $port = $pport;
$global = undef if ($global eq 'local'); $port =~ s/^IPV6://;
$infix = $apiName if (defined $apiName); return "HTTPAPI: wrong syntax, correct is: define <name> HTTPAPI [infix=]<infix> [port=][[IPV6:]<port>] [global=][global|local|<hostname>]" if ($port !~ m/^\d+$/);
$hash->{INFIX} = $infix; if (defined $a->[4]) {
$hash->{GLOBAL} = $a->[4];
} elsif (exists $h->{global}) {
$hash->{GLOBAL} = $h->{global};
} else {
$hash->{GLOBAL} = $tcpServAdr;
}
# open TCP server for HTTP API service # open TCP server for HTTP API service
my $ret = TcpServer_Open($hash, $pport, $global); my $ret = TcpServer_Open($hash, $pport, (($hash->{GLOBAL} eq 'local') ? undef : $hash->{GLOBAL}));
if($ret && !$init_done) { if($ret && !$init_done) {
Log3 $name, 1, "HTTPAPI $ret already exists"; Log3 $name, 1, "HTTPAPI $ret already exists";
exit(1); exit(1);
@ -101,7 +120,7 @@ sub HTTPAPI_CGI($$$) {
$fhemDevName = substr(($1 // $2), 1); $fhemDevName = substr(($1 // $2), 1);
# url decoding # url decoding
$fhemDevName =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; $fhemDevName =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
if (defined $defs{$fhemDevName}) { if (IsDevice($fhemDevName) && !IsDisabled($fhemDevName) && !IsIgnored($fhemDevName)) {
# Control of the device allowed? # Control of the device allowed?
my $devicesCtrl = AttrVal($name, 'devicesCtrl', undef); my $devicesCtrl = AttrVal($name, 'devicesCtrl', undef);
my $allowedDev; my $allowedDev;
@ -195,7 +214,7 @@ sub HTTPAPI_CGI($$$) {
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > action $apiCmd unknown")) return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > action $apiCmd unknown"))
} }
} else { } else {
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > device $fhemDevName unknown")) return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > device $fhemDevName unknown, disabled or ignored by the user"))
} }
} else { } else {
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute device missing")) return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute device missing"))
@ -210,7 +229,7 @@ sub HTTPAPI_CGI($$$) {
sub HTTPAPI_CommandRef($) { sub HTTPAPI_CommandRef($) {
my ($hash) = @_; my ($hash) = @_;
my $fileName = $gPath . '/02_HTTPAPI.pm'; my $fileName = $gPath . '/02_HTTPAPI.pm';
my ($err, @contents) = FileRead($fileName); my ($err, @contents) = FileRead({FileName => $fileName, ForceType => 'file'});
return ($hash, 404, 'close', "text/plain; charset=utf-8", encode($encoding, "error=404 Not Found, file $fileName not found")) if ($err); return ($hash, 404, 'close', "text/plain; charset=utf-8", encode($encoding, "error=404 Not Found, file $fileName not found")) if ($err);
my $contents = join("\n", @contents); my $contents = join("\n", @contents);
$contents =~ /\n=begin.html([\s\S]*)\n=end.html/gs; $contents =~ /\n=begin.html([\s\S]*)\n=end.html/gs;
@ -342,16 +361,16 @@ sub HTTPAPI_Undef($) {
<a id="HTTPAPI-define"></a> <a id="HTTPAPI-define"></a>
<b>Define</b> <b>Define</b>
<ul> <ul>
<code>define &lt;name&gt; HTTPAPI [&lt;infix&gt;] [[IPV6:]&lt;ip-port&gt;] [global|local|&lt;hostname&gt;]</code><br><br> <code>define &lt;name&gt; HTTPAPI [infix=][&lt;apiName&gt;] [port=][[IPV6:]&lt;port&gt;] [global=][global|local|&lt;hostname&gt;]</code><br><br>
Defines the HTTP API server.<br> Defines the HTTP API server.<br>
<ul> <ul>
<li> <li>
<code>&lt;infix&gt;</code> is the portion behind the base URL (usually <code>http://&lt;hostname&gt;:&lt;ip-port&gt;/&lt;infix&gt;</code>).<br> <code>&lt;apiName&gt;</code> is the portion behind the base URL (usually <code>http://&lt;hostname&gt;:&lt;port&gt;/&lt;apiName&gt;</code>).<br>
<code>[&lt;infix&gt] = api</code> is default. <code>[&lt;apiName&gt] = api</code> is default.
</li> </li>
<li> <li>
<code>[[IPV6:]&lt;ip-port&gt;] = 8087</code> is default.<br> <code>[[IPV6:]&lt;port&gt;] = 8087</code> is default.<br>
To use IPV6, specify the portNumber as <code>IPV6:&lt;number&gt;</code>, in this case the perl module IO::Socket:INET6 will be requested. To use IPV6, specify the portNumber as <code>IPV6:&lt;number&gt;</code>, in this case the perl module IO::Socket:INET6 will be requested.
On Linux you may have to install it with <code>cpan -i IO::Socket::INET6</code> or <code>apt-get libio-socket-inet6-perl</code>. On Linux you may have to install it with <code>cpan -i IO::Socket::INET6</code> or <code>apt-get libio-socket-inet6-perl</code>.
</li> </li>
@ -366,6 +385,8 @@ sub HTTPAPI_Undef($) {
Example: Example:
<ul> <ul>
<code>define httpapi HTTPAPI api 8087 global</code><br> <code>define httpapi HTTPAPI api 8087 global</code><br>
or<br>
<code>define httpapi HTTPAPI infix=api1 port=8089 global=local</code><br>
</ul> </ul>
</ul> </ul>
<br><br> <br><br>
@ -441,9 +462,10 @@ sub HTTPAPI_Undef($) {
<b>Usage information</b> <b>Usage information</b>
<ul> <ul>
All links are relative to <code>http://&lt;ip-addr&gt;:&lt;ip-port&gt;/</code>.<br> <li>All links are relative to <code>http://&lt;ip-addr&gt;:&lt;port&gt;/</code>.</li>
The <code>http://&lt;ip-addr&gt;:&lt;ip-port&gt;/&lt;apiName&gt;/</code> command displays the module-specific commandref.<br> <li>Commands are not executed if the disable or ignore attribute of the device is set. See also <a href="#HTTPAPI-attr-devicesCtrl">devicesCtrl</a>.</li>
The response message is encoded to UTF-8. <li>The <code>http://&lt;ip-addr&gt;:&lt;port&gt;/&lt;apiName&gt;/</code> command displays the module-specific commandref.</li>
<li>The response message is encoded to UTF-8.</li>
</ul> </ul>
<br><br> <br><br>