mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 09:16:53 +00:00
- GET / POST / COOKIE finished in test version (no comments, ..)
git-svn-id: https://svn.fhem.de/fhem/trunk@4151 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
62340d90e8
commit
4a59d0207c
@ -1,6 +1,6 @@
|
|||||||
########################################################################################
|
########################################################################################
|
||||||
#
|
#
|
||||||
# 01_YAF.pm
|
# YAFWebserver.pm
|
||||||
#
|
#
|
||||||
# YAF - Yet Another Floorplan
|
# YAF - Yet Another Floorplan
|
||||||
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
|
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
|
||||||
@ -27,12 +27,9 @@ package main;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
# load zlib if possible
|
use FindBin;
|
||||||
my $zlib_active = 1;
|
use lib "$FindBin::Bin/FHEM/YAF/libs";
|
||||||
eval "require Compress::Zlib;";
|
use YAFWebserver;
|
||||||
if ($@) {
|
|
||||||
$zlib_active = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
#
|
#
|
||||||
@ -47,6 +44,10 @@ sub YAFWebserver_Initialize($) {
|
|||||||
$hash->{DefFn} = "YAFWebserver_Define";
|
$hash->{DefFn} = "YAFWebserver_Define";
|
||||||
$hash->{UndefFn} = "YAFWebserver_Undefine";
|
$hash->{UndefFn} = "YAFWebserver_Undefine";
|
||||||
$hash->{ReadFn} = "YAFWebserver_Read";
|
$hash->{ReadFn} = "YAFWebserver_Read";
|
||||||
|
|
||||||
|
# init new webserver instance
|
||||||
|
$hash->{YAFWEBSERVER} = YAFWebserver->new;
|
||||||
|
$hash->{HEADER_FIELD_HASHMAP} = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
########################################################################################
|
########################################################################################
|
||||||
@ -60,8 +61,8 @@ sub YAFWebserver_Initialize($) {
|
|||||||
sub YAFWebserver_Define($@) {
|
sub YAFWebserver_Define($@) {
|
||||||
my ($hash, $def) = @_;
|
my ($hash, $def) = @_;
|
||||||
my ($name, $type, $port) = split("[ \t]+", $def);
|
my ($name, $type, $port) = split("[ \t]+", $def);
|
||||||
# Starting Listening for Webserver Request
|
# Open new tcp listening on defined port
|
||||||
my $ret = TcpServer_Open($hash, $port, "global");
|
my $ret = TcpServer_Open($hash, $port, "");
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ sub YAFWebserver_Define($@) {
|
|||||||
|
|
||||||
sub YAFWebserver_Undefine($@) {
|
sub YAFWebserver_Undefine($@) {
|
||||||
my ($hash, $arg) = @_;
|
my ($hash, $arg) = @_;
|
||||||
|
# Close tcp listening
|
||||||
return TcpServer_Close($hash);
|
return TcpServer_Close($hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,58 +90,92 @@ sub YAFWebserver_Undefine($@) {
|
|||||||
|
|
||||||
sub YAFWebserver_Read($) {
|
sub YAFWebserver_Read($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
my $requested_uri;
|
my $requestedUrl;
|
||||||
|
|
||||||
# New ServerSocket
|
# Accept new server sockets
|
||||||
if($hash->{SERVERSOCKET}) {
|
if($hash->{SERVERSOCKET}) {
|
||||||
TcpServer_Accept($hash, "YAFWebserver");
|
TcpServer_Accept($hash, "YAFWebserver");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Received chars stored in $c
|
||||||
my $c = $hash->{CD};
|
my $c = $hash->{CD};
|
||||||
my $buf;
|
|
||||||
|
|
||||||
# Read 1024 Byte of data
|
# Read 1024 byte of data
|
||||||
|
my $buf;
|
||||||
my $ret = sysread($hash->{CD}, $buf, 1024);
|
my $ret = sysread($hash->{CD}, $buf, 1024);
|
||||||
|
|
||||||
# When there is an error in connection return
|
# When there is an error in connection return
|
||||||
if(!defined($ret) || $ret <= 0) {
|
if (!defined($ret) || $ret <= 0) {
|
||||||
CommandDelete(undef, $hash->{NAME});
|
CommandDelete(undef, $hash->{NAME});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# New Request
|
########
|
||||||
|
# State: new request / read header
|
||||||
|
########
|
||||||
if (!defined($hash->{HTTPSTATE}) || ($hash->{HTTPSTATE} eq "NewRequest")) {
|
if (!defined($hash->{HTTPSTATE}) || ($hash->{HTTPSTATE} eq "NewRequest")) {
|
||||||
# Check if new Request is GET or POST else => break connection
|
# Check if new Request is GET or POST else => break connection
|
||||||
if (($buf =~ m/\n\n.*/) || ($buf =~ m/\r\n\r\n.*/)) {
|
if (($buf =~ m/\n\n.*/) || ($buf =~ m/\r\n\r\n.*/)) {
|
||||||
my $position_end_of_header = 0;
|
my $position = 0;
|
||||||
# Search trim position,to cut header from content
|
# Search trim position,to cut header from content
|
||||||
if ($buf =~ m/\n\n.*/) {
|
if ($buf =~ m/\n\n.*/) {
|
||||||
$position_end_of_header = index($buf,"\n\n")+2; # +2 for \n\n
|
$position = index($buf,"\n\n")+2; # +2 for \n\n
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$position_end_of_header = index($buf, "\r\n\r\n")+4;# +4 for \r\n\r\n
|
$position = index($buf, "\r\n\r\n")+4;# +4 for \r\n\r\n
|
||||||
}
|
|
||||||
# Hole header is read. Remove header from buffer.
|
|
||||||
$hash->{HTTPHEADER} .= substr($buf, 0, $position_end_of_header);
|
|
||||||
$buf = substr($buf, $position_end_of_header);
|
|
||||||
# Split header in lines (\r\n)
|
|
||||||
my @header_array = split("[\r\n]", $hash->{HTTPHEADER});
|
|
||||||
# look for requested url
|
|
||||||
my @requested_uri = grep /GET/, @header_array;
|
|
||||||
my @requested_uri_parts = split(" ", $requested_uri[0]);
|
|
||||||
$requested_uri = $requested_uri_parts[1];
|
|
||||||
# Read Content-Length when available
|
|
||||||
my @content_length_array = grep /Content-Length/, @header_array;
|
|
||||||
my $content_length = 0;
|
|
||||||
if (scalar(@content_length_array) > 0) {
|
|
||||||
$content_length = substr($content_length_array[0],16);
|
|
||||||
}
|
}
|
||||||
|
# header is read. Remove header from buffer.
|
||||||
|
$hash->{HTTPHEADER} .= substr($buf, 0, $position);
|
||||||
|
$buf = substr($buf, $position);
|
||||||
|
# split header in lines in hashmap
|
||||||
|
# example header line: Accept-Encoding: gzip,deflate,sdch
|
||||||
|
# $hash->{HTTPHEADER_VALUEMAP}->{key} => value
|
||||||
|
my @header_field = split("[\r\n][\r\n]", $hash->{HTTPHEADER});
|
||||||
|
my @header_field_line_splitted;
|
||||||
|
for (my $array_pos = 1; $array_pos < scalar(@header_field); $array_pos++) {
|
||||||
|
@header_field_line_splitted = split(":",$header_field[$array_pos]);
|
||||||
|
$hash->{HTTPHEADER_VALUEMAP}->{"$header_field_line_splitted[0]"} = trim($header_field_line_splitted[1]);
|
||||||
|
}
|
||||||
|
# look for request line
|
||||||
|
# GET / HTTP/1.1
|
||||||
|
my @header_field_request_splitted = split(" ", $header_field[0]);
|
||||||
|
$hash->{HTTPHEADER_METHOD} = $header_field_request_splitted[0];
|
||||||
|
$hash->{HTTPHEADER_URI} = $header_field_request_splitted[1];
|
||||||
|
$hash->{HTTPHEADER_VERSION} = $header_field_request_splitted[2];
|
||||||
|
# consume uri
|
||||||
|
# \path\to\file.php ? test = 1 & test = 2
|
||||||
|
# $hash->{GET}->{key} => value
|
||||||
|
my @header_field_uri_splitted = split(/\?/, $hash->{HTTPHEADER_URI});
|
||||||
|
if (scalar(@header_field_uri_splitted) > 1) {
|
||||||
|
my @attributes_array = split("&",$header_field_uri_splitted[1]);
|
||||||
|
my @attribute_pair;
|
||||||
|
foreach (@attributes_array) {
|
||||||
|
@attribute_pair = split("=",$_);
|
||||||
|
$hash->{GET}->{"$attribute_pair[0]"} = $attribute_pair[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# cookie
|
||||||
|
if ($hash->{HTTPHEADER_VALUEMAP}->{"Cookie"}) {
|
||||||
|
my @cookies_array = split(";", $hash->{HTTPHEADER_VALUEMAP}->{"Cookie"});
|
||||||
|
my @cookies_array_pair;
|
||||||
|
foreach (@cookies_array) {
|
||||||
|
@cookies_array_pair = split("=",$_);
|
||||||
|
my $name = trim($cookies_array_pair[0]);
|
||||||
|
$hash->{COOKIE}->{"$name"} = $cookies_array_pair[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
# set content-length
|
# set content-length
|
||||||
$hash->{HTTPCONTENTLENGTH} = $content_length;
|
if ($hash->{HTTPHEADER_VALUEMAP}->{"Content-Length"}) {
|
||||||
|
$hash->{HTTPCONTENT_LENGTH} = $hash->{HTTPHEADER_VALUEMAP}->{"Content-Length"};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$hash->{HTTPCONTENT_LENGTH} = 0;
|
||||||
|
}
|
||||||
# clear HTTPCONTENT
|
# clear HTTPCONTENT
|
||||||
$hash->{HTTPCONTENT} = "";
|
$hash->{HTTPCONTENT} = "";
|
||||||
$hash->{HTTPSTATE} = "ReadData";
|
$hash->{HTTPSTATE} = "ReadData";
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$hash->{HTTPHEADER} .= $buf;
|
$hash->{HTTPHEADER} .= $buf;
|
||||||
@ -147,42 +183,70 @@ sub YAFWebserver_Read($) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Read Data
|
########
|
||||||
|
# State: consume content
|
||||||
|
########
|
||||||
if (defined($hash->{HTTPSTATE}) && ($hash->{HTTPSTATE} eq "ReadData")) {
|
if (defined($hash->{HTTPSTATE}) && ($hash->{HTTPSTATE} eq "ReadData")) {
|
||||||
$hash->{HTTPCONTENT} .= $buf;
|
$hash->{HTTPCONTENT} .= $buf;
|
||||||
# Read hole HTTPCONTENT
|
# Read hole HTTPCONTENT
|
||||||
if (length($hash->{HTTPCONTENT}) >= $hash->{HTTPCONTENTLENGTH}) {
|
if (length($hash->{HTTPCONTENT}) >= $hash->{HTTPCONTENT_LENGTH}) {
|
||||||
$hash->{HTTPSTATE} = "DoResponse";
|
$hash->{HTTPSTATE} = "DoResponse";
|
||||||
|
# content finish
|
||||||
|
# prepare post var
|
||||||
|
if (($hash->{HTTPHEADER_VALUEMAP}->{"Content-Type"}) && ($hash->{HTTPHEADER_VALUEMAP}->{"Content-Type"} eq "application/x-www-form-urlencoded")) {
|
||||||
|
my @attributes_array = split("&",$hash->{HTTPCONTENT});
|
||||||
|
my @attribute_pair;
|
||||||
|
foreach (@attributes_array) {
|
||||||
|
@attribute_pair = split("=",$_);
|
||||||
|
$hash->{POST}->{"$attribute_pair[0]"} = $attribute_pair[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif (($hash->{HTTPHEADER_VALUEMAP}->{"Content-Type"}) && ($hash->{HTTPHEADER_VALUEMAP}->{"Content-Type"} =~ m/multipart\/form-data; boundary=*/)) {
|
||||||
|
$hash->{POST_DIVISOR} = $hash->{HTTPHEADER_VALUEMAP}->{"Content-Type"};
|
||||||
|
$hash->{POST_DIVISOR} =~ s/multipart\/form-data; boundary=//g;
|
||||||
|
# add prefix
|
||||||
|
$hash->{POST_DIVISOR} = "--".$hash->{POST_DIVISOR};
|
||||||
|
my @post_field_splitted = split($hash->{POST_DIVISOR},$hash->{HTTPCONTENT});
|
||||||
|
# for every post field
|
||||||
|
for (my $array_pos = 1; $array_pos < scalar(@post_field_splitted)-1; $array_pos++) {
|
||||||
|
my @entry_splitted = split("\r\n\r\n",$post_field_splitted[$array_pos]);
|
||||||
|
# remove last return in value
|
||||||
|
$entry_splitted[1] = substr($entry_splitted[1],0,length($entry_splitted[1])-2);
|
||||||
|
# get name
|
||||||
|
$entry_splitted[0] =~ m/.*name="(.*)".*/;
|
||||||
|
$hash->{POST}->{"$1"} = $entry_splitted[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Answer Request
|
########
|
||||||
|
# State: do response
|
||||||
|
########
|
||||||
if (defined($hash->{HTTPSTATE}) && ($hash->{HTTPSTATE} eq "DoResponse")) {
|
if (defined($hash->{HTTPSTATE}) && ($hash->{HTTPSTATE} eq "DoResponse")) {
|
||||||
my ($contentType, $content) = YAF_Request($requested_uri);
|
my $header = $hash->{HTTPHEADER};
|
||||||
|
my $content = $hash->{HTTPCONTENT};
|
||||||
|
|
||||||
|
|
||||||
|
my $test3 = "no";
|
||||||
|
my $response = "header lines: $hash->{HTTPCONTENT_LENGTH}\r\n####################\r\n$header####################\r\n$content\r\n##################\r\n$test3";
|
||||||
|
|
||||||
# files over 30000 chars getting compressed
|
|
||||||
my $header_compressed = "";
|
|
||||||
if (($zlib_active == 1) && (length($content) > 30000)) {
|
|
||||||
$content = Compress::Zlib::memGzip($content);
|
|
||||||
$header_compressed = "Content-Encoding: gzip\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# send response to client
|
|
||||||
print $c "HTTP/1.1 200 OK\r\n",
|
print $c "HTTP/1.1 200 OK\r\n",
|
||||||
"Content-Length: ".length($content)."\r\n",
|
"Content-Type: text/plain\r\n",
|
||||||
$header_compressed,
|
# "Set-Cookie: test=test4\r\n",
|
||||||
"Content-Type: $contentType\r\n\r\n",
|
"Content-Length: ".length($response)."\r\n\r\n",
|
||||||
$content;
|
$response;
|
||||||
|
|
||||||
# Waiting for new Request
|
# Waiting for new Request
|
||||||
$hash->{HTTPHEADER} = "";
|
$hash->{HTTPHEADER} = "";
|
||||||
$hash->{HTTPCONTENT} = "";
|
$hash->{HTTPCONTENT} = "";
|
||||||
$hash->{HTTPSTATE} = "NewRequest";
|
$hash->{HTTPSTATE} = "NewRequest";
|
||||||
# End of Request
|
# End of Request
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user