diff --git a/fhem/FHEM/02_HTTPAPI.pm b/fhem/FHEM/02_HTTPAPI.pm index 5b1706a28..60ed46a43 100644 --- a/fhem/FHEM/02_HTTPAPI.pm +++ b/fhem/FHEM/02_HTTPAPI.pm @@ -34,28 +34,47 @@ sub HTTPAPI_Initialize($) { $hash->{ReadFn} = "HTTPAPI_Read"; $hash->{UndefFn} = "HTTPAPI_Undef"; $hash->{AttrList} = "disable:0,1 devicesCtrl " . $readingFnAttributes; + $hash->{parseParams} = 1; return undef; } sub HTTPAPI_Define($$) { - my ($hash, $def) = @_; - my @param = split("[ \t][ \t]*", $def); - my ($name, $type, $apiName, $pport, $global) = split("[ \t]+", $def); - my $port; - if (defined $pport) { - $port = $pport; - $port =~ s/^IPV6://; - return "Usage: define HTTPAPI [] [[IPV6:]] [global|local|]" if ($port !~ m/^\d+$/); + my ($hash, $a, $h) = @_; + my $name = $a->[0]; + if (defined $a->[2]) { + $hash->{INFIX} = $a->[2]; + $infix = $a->[2]; + } elsif (exists $h->{infix}) { + $hash->{INFIX} = $h->{infix}; + $infix = $h->{infix}; + } else { + $hash->{INFIX} = $infix; + } + # check if valid folder name + if ($hash->{INFIX} !~ /^[^\\\/\?\*\"\'\>\<\:\|]*$/) { + return "HTTPAPI: wrong syntax, correct is: define HTTPAPI [infix=] [port=][[IPV6:]] [global=][global|local|]"; + } + my ($pport, $port); + if (defined $a->[3]) { + $pport = $a->[3]; + } elsif (exists $h->{port}) { + $pport = $h->{port}; } else { - $port = $tcpServPort; $pport = $tcpServPort; } - $global = $global // $tcpServAdr; - $global = undef if ($global eq 'local'); - $infix = $apiName if (defined $apiName); - $hash->{INFIX} = $infix; + $port = $pport; + $port =~ s/^IPV6://; + return "HTTPAPI: wrong syntax, correct is: define HTTPAPI [infix=] [port=][[IPV6:]] [global=][global|local|]" if ($port !~ m/^\d+$/); + 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 - my $ret = TcpServer_Open($hash, $pport, $global); + my $ret = TcpServer_Open($hash, $pport, (($hash->{GLOBAL} eq 'local') ? undef : $hash->{GLOBAL})); if($ret && !$init_done) { Log3 $name, 1, "HTTPAPI $ret already exists"; exit(1); @@ -101,7 +120,7 @@ sub HTTPAPI_CGI($$$) { $fhemDevName = substr(($1 // $2), 1); # url decoding $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? my $devicesCtrl = AttrVal($name, 'devicesCtrl', undef); 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")) } } 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 { 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($) { my ($hash) = @_; 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); my $contents = join("\n", @contents); $contents =~ /\n=begin.html([\s\S]*)\n=end.html/gs; @@ -342,16 +361,16 @@ sub HTTPAPI_Undef($) { Define
    - define <name> HTTPAPI [<infix>] [[IPV6:]<ip-port>] [global|local|<hostname>]

    + define <name> HTTPAPI [infix=][<apiName>] [port=][[IPV6:]<port>] [global=][global|local|<hostname>]

    Defines the HTTP API server.
    • - <infix> is the portion behind the base URL (usually http://<hostname>:<ip-port>/<infix>).
      - [<infix>] = api is default. + <apiName> is the portion behind the base URL (usually http://<hostname>:<port>/<apiName>).
      + [<apiName>] = api is default.
    • - [[IPV6:]<ip-port>] = 8087 is default.
      + [[IPV6:]<port>] = 8087 is default.
      To use IPV6, specify the portNumber as IPV6:<number>, in this case the perl module IO::Socket:INET6 will be requested. On Linux you may have to install it with cpan -i IO::Socket::INET6 or apt-get libio-socket-inet6-perl.
    • @@ -366,6 +385,8 @@ sub HTTPAPI_Undef($) { Example:
        define httpapi HTTPAPI api 8087 global
        + or
        + define httpapi HTTPAPI infix=api1 port=8089 global=local


    @@ -441,9 +462,10 @@ sub HTTPAPI_Undef($) { Usage information
      - All links are relative to http://<ip-addr>:<ip-port>/.
      - The http://<ip-addr>:<ip-port>/<apiName>/ command displays the module-specific commandref.
      - The response message is encoded to UTF-8. +
    • All links are relative to http://<ip-addr>:<port>/.
    • +
    • Commands are not executed if the disable or ignore attribute of the device is set. See also devicesCtrl.
    • +
    • The http://<ip-addr>:<port>/<apiName>/ command displays the module-specific commandref.
    • +
    • The response message is encoded to UTF-8.