| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- #
- #
- # 02_HTTPSRV.pm
- # written by Dr. Boris Neubert 2012-08-27
- # e-mail: omega at online dot de
- #
- ##############################################
- # $Id: 02_HTTPSRV.pm 13976 2017-04-12 13:35:44Z neubert $
- package main;
- use strict;
- use warnings;
- use vars qw(%data);
- use HttpUtils;
- my $HTTPSRV_matchlink = "^\/?(([^\/]*(\/[^\/]+)*)\/?)\$";
- #########################
- sub
- HTTPSRV_addExtension($$$$) {
- my ($name,$func,$link,$friendlyname)= @_;
- # do some cleanup on link/url
- # link should really show the link as expected to be called (might include trailing / but no leading /)
- # url should only contain the directory piece with a leading / but no trailing /
- # $1 is complete link without potentially leading /
- # $2 is complete link without potentially leading / and trailing /
- $link =~ /$HTTPSRV_matchlink/;
- my $url = "/".$2;
- my $modlink = $1;
- Log3 $name, 3, "Registering HTTPSRV $name for URL $url and assigned link $modlink ...";
- $data{FWEXT}{$url}{deviceName}= $name;
- $data{FWEXT}{$url}{FUNC} = $func;
- $data{FWEXT}{$url}{LINK} = $modlink;
- $data{FWEXT}{$url}{NAME} = $friendlyname;
- }
- sub
- HTTPSRV_removeExtension($) {
- my ($link)= @_;
- # do some cleanup on link/url
- # link should really show the link as expected to be called (might include trailing / but no leading /)
- # url should only contain the directory piece with a leading / but no trailing /
- # $1 is complete link without potentially leading /
- # $2 is complete link without potentially leading / and trailing /
- $link =~ /$HTTPSRV_matchlink/;
- my $url = "/".$2;
- my $name= $data{FWEXT}{$url}{deviceName};
- Log3 $name, 3, "Unregistering HTTPSRV $name for URL $url...";
- delete $data{FWEXT}{$url};
- }
- ##################
- sub
- HTTPSRV_Initialize($) {
- my ($hash) = @_;
- $hash->{DefFn} = "HTTPSRV_Define";
- $hash->{DefFn} = "HTTPSRV_Define";
- $hash->{UndefFn} = "HTTPSRV_Undef";
- #$hash->{AttrFn} = "HTTPSRV_Attr";
- $hash->{AttrList} = "directoryindex " .
- "readings";
- $hash->{AttrFn} = "HTTPSRV_Attr";
- #$hash->{SetFn} = "HTTPSRV_Set";
- return undef;
- }
- ##################
- sub
- HTTPSRV_Define($$) {
- my ($hash, $def) = @_;
- my @a = split("[ \t]+", $def, 5);
- return "Usage: define <name> HTTPSRV <infix> <directory> <friendlyname>" if(int(@a) != 5);
- my $name= $a[0];
- my $infix= $a[2];
- my $directory= $a[3];
- my $friendlyname= $a[4];
- $hash->{fhem}{infix}= $infix;
- $hash->{fhem}{directory}= $directory;
- $hash->{fhem}{friendlyname}= $friendlyname;
- Log3 $name, 3, "$name: new ext defined infix:$infix: dir:$directory:";
- HTTPSRV_addExtension($name, "HTTPSRV_CGI", $infix, $friendlyname);
-
- $hash->{STATE} = $name;
- return undef;
- }
- ##################
- sub
- HTTPSRV_Undef($$) {
- my ($hash, $name) = @_;
- HTTPSRV_removeExtension($hash->{fhem}{infix});
- return undef;
- }
- ##################
- sub
- HTTPSRV_Attr(@)
- {
- my ($cmd,$name,$aName,$aVal) = @_;
- if ($cmd eq "set") {
- if ($aName =~ "readings") {
- if ($aVal !~ /^[A-Z_a-z0-9\,]+$/) {
- Log3 $name, 3, "$name: Invalid reading list in attr $name $aName $aVal (only A-Z, a-z, 0-9, _ and , allowed)";
- return "Invalid reading name $aVal (only A-Z, a-z, 0-9, _ and , allowed)";
- }
- addToDevAttrList($name, $aName);
- }
- }
- return undef;
- }
- ##################
- #
- # here we answer any request to http://host:port/fhem/$infix and below
- sub HTTPSRV_CGI() {
- my ($request) = @_; # /$infix/filename
- # Debug "request= $request";
-
- # Match request first without trailing / in the link part
- if($request =~ m,^(/[^/]+)(/(.*)?)?$,) {
- my $link= $1;
- my $filename= $3;
- my $name;
- # If FWEXT not found for this make a second try with a trailing slash in the link part
- if(! $data{FWEXT}{$link}) {
- $link = $link."/";
- return("text/plain; charset=utf-8", "Illegal request: $request") if(! $data{FWEXT}{$link});
- }
-
- # get device name
- $name= $data{FWEXT}{$link}{deviceName};
- # Debug "link= $link";
- # Debug "filename= $filename";
- # Debug "name= $name";
- # return error if no such device
- return("text/plain; charset=utf-8", "No HTTPSRV device for $link") unless($name);
- my $fullName = $filename;
- foreach my $reading (split (/,/, AttrVal($name, "readings", ""))) {
- my $value = "";
- if ($fullName =~ /^([^\?]+)\?(.*)($reading)=([^;&]*)([&;].*)?$/) {
- $filename = $1;
- $value = $4;
- Log3 $name, 5, "$name: set Reading $reading = $value";
- readingsSingleUpdate($defs{$name}, $reading, $value, 1);
- }
- };
-
- # set directory index
- $filename= AttrVal($name,"directoryindex","index.html") unless($filename);
- $filename =~ s/\?.*//;
- my $MIMEtype= filename2MIMEType($filename);
- my $directory= $defs{$name}{fhem}{directory};
- $filename= "$directory/$filename";
- #Debug "read filename= $filename";
- my @contents;
- if(open(INPUTFILE, $filename)) {
- binmode(INPUTFILE);
- @contents= <INPUTFILE>;
- close(INPUTFILE);
- return("$MIMEtype; charset=utf-8", join("", @contents));
- } else {
- return("text/plain; charset=utf-8", "File not found: $filename");
- }
- } else {
- return("text/plain; charset=utf-8", "Illegal request: $request");
- }
-
- }
-
-
- ####
- 1;
- =pod
- =item device
- =item summary rudimentary HTTP server that accepts parameters as readings
- =item summary_DE rudimentärer HTTP-Server, der auch Parameter als Readings akzeptiert
- =begin html
- <a name="HTTPSRV"></a>
- <h3>HTTPSRV</h3>
- <ul>
- Provides a mini HTTP server plugin for FHEMWEB. It serves files from a given directory.
- It optionally accepts a query string to set readings of this device if an attribute allows the given reading<p>
- HTTPSRV is an extension to <a href="HTTPSRV">FHEMWEB</a>. You must install FHEMWEB to use HTTPSRV.</p>
- <a name="HTTPSRVdefine"></a>
- <b>Define</b>
- <ul>
- <code>define <name> <infix> <directory> <friendlyname></code><br><br>
- Defines the HTTP server. <code><infix></code> is the portion behind the FHEMWEB base URL (usually
- <code>http://hostname:8083/fhem</code>), <code><directory></code> is the absolute path the
- files are served from, and <code><friendlyname></code> is the name displayed in the side menu of FHEMWEB.<p><p>
- Example:
- <ul>
- <code>define myJSFrontend HTTPSRV jsf /usr/share/jsfrontend My little frontend</code><br>
- or <br>
- <code>
- define kindleweb HTTPSRV kindle /opt/fhem/kindle Kindle Web<br>
- attr kindleweb readings KindleBatt
- </code><br>
- </ul>
- <br>
- </ul>
- <a name="HTTPSRVset"></a>
- <b>Set</b>
- <ul>
- n/a
- </ul>
- <br><br>
- <a name="HTTPSRVattr"></a>
- <b>Attributes</b>
- <br><br>
- <ul>
- <li>directoryindex: if the request is sent with no filename, i.e. the infix (with or without trailing slash) only, the file given in this attribute is loaded. Defaults to <code>index.html</code>.</li>
- <li>readings: a comma separated list of reading names. If the request ends with a querystring like <code>?Batt=43</code> and an attribute is set like <code>attr kindleweb readings Batt</code>, then a reading with the Name of this Attribute (here Batt) is created with the value from the request.</li>
- </ul>
- <br><br>
- <b>Usage information</b>
- <br><br>
- <ul>
- The above example on <code>http://hostname:8083/fhem</code> will return the file
- <code>/usr/share/jsfrontend/foo.html</code> for <code>http://hostname:8083/fhem/jsf/foo.html</code>.
- If no filename is given, the filename prescribed by the <code>directoryindex</code> attribute is returned.<p>
- Notice: All links are relative to <code>http://hostname:8083/fhem</code>.
- </ul>
- <br><br>
- </ul>
- =end html
- =cut
|