###TIMEOUT_INACT;\r
 ###UNLOCK_PROXY_HOST;\r
 \r
-$VERSION     = 0.000003;\r
+$VERSION     = 0.000004;\r
 @ISA         = qw(Exporter);\r
 @EXPORT      = ();\r
-@EXPORT_OK   = qw(access divideurl entitydecode formatheader getcgi joinurl path2url url2path path2urldiv readconfigfile urldecode urldiv2path);\r
+@EXPORT_OK   = qw(access divideurl entitydecode formatheader getcgi joinurl path2url url2path path2urldiv readconfigfile readheaderfile urldecode urldiv2path);\r
 %EXPORT_TAGS = ();\r
 \r
 # This function checks if the user has unlocked the proxy. Nonzero means yes.\r
        return $t;\r
 }\r
 \r
+# Function for decoding html entities; by number decimal, haeadecimal or by name\r
 sub entitydecode {\r
        my $t = $_[0];\r
        $t =~ s/&(#?[a-zA-Z0-9]+);/entitydecode1ch($1)/eg;\r
        return $t;\r
 }\r
 \r
+# Function for decoding one html entity, called from entitydecode().\r
 sub entitydecode1ch {\r
        my $t = $_[0];\r
+       # decode decimal number\r
        if ($t =~ /^#([0-9]+)$/) {\r
                return chr($1);\r
        }\r
+       # decode hexadecimal number\r
        elsif ($t =~ /^#x([0-9A-Fa-f]+)$/) {\r
                return chr(hex($1));\r
        }\r
+       # decode entity name\r
        elsif ($t =~ /^([A-Za-z0-9]+)$/) {\r
                return entitycode->{$1};\r
        }\r
        return $t;\r
 }\r
 \r
-# Function to convert URL to archive path. Also creates required directories\r
-# if $mkdir true.\r
+# Function to convert URL (divided) to archive path. Also creates required\r
+# directories if $mkdir true.\r
 # Returns the path on success and undef on fail.\r
 # Inspired by the MIRA browser.\r
 sub urldiv2path {\r
                # character parts ending with '-' until the last one is not longer than 240.\r
                # Characters that are not letters or numbers or '_' or '.' are encoded. Like\r
                # in URL-encoding but with '@' instead of '%'.\r
-               # When segment is longer than 120 characters it's divided into 64 character\r
-               # parts ending with '-' until the last one is not longer than 120.\r
                # The '?' at the beginning is not part of the query string.\r
                # For example:\r
                # ?a=1&b=%25%5E%26 becomes ... /a@3D1@26b@3D@2525@255E@2526\r
        return $archpath;\r
 }\r
 \r
+# Function to convert URL (one string) to archive path\r
 sub url2path {\r
        return urldiv2path(divideurl($_[0]));\r
 }\r
 \r
+# Function to convert archive path to URL (divided)\r
 sub path2urldiv {\r
        my $archpath = $_[0];\r
        my $prot;\r
        return ($prot, $host, $port, $path, $query);\r
 }\r
 \r
+# Function to join parts of URL to one string\r
 sub joinurl {\r
        (my $prot, my $host, my $port, my $path, my $query) = @_;\r
        my $url;\r
        return $url;\r
 }\r
 \r
+# Function to convert archive path to URL (one string)\r
 sub path2url {\r
        return joinurl(path2urldiv($_[0]));\r
 }\r
 \r
+# Function to read http headers. It reads data from a file containing a http\r
+# header (see: https://tools.ietf.org/html/rfc2616#section-4.2). One exception:\r
+# the status line is not special. Instead the status is just another header\r
+# field with the name 'Status' (like in a CGI header)\r
+# \r
+# Returns a hash containing the values.\r
+# Names are case sensitive and are converted to lowercase\r
+#\r
+# Argument can be a path or a file handle. In case of a file handle it will just\r
+# read the file. In case of path it opens the file before reading and closes\r
+# after. On failure (file not open) returns empty hash.\r
+# \r
+sub readheaderfile {\r
+       (my $headerpath) = @_;\r
+       my $headerfile;\r
+       my %header;\r
+       \r
+       # check if $headerpath is actually a path or maybe a filehandle\r
+       # filehandles are references.\r
+       if(ref($headerpath)) {\r
+               $headerfile=$headerpath;\r
+       }\r
+       else {\r
+               unless (open ($headerfile, "<", $headerpath)) {\r
+                       return %header;\r
+               }\r
+       }\r
+       \r
+       # The name of header field in previous line. Required for header fields that\r
+       # occupy multiple lines.\r
+       my $lastname='';\r
+       \r
+       while (defined(my $line = <$headerfile>)) {\r
+               $line =~ s/[\r\n]$//g;\r
+               my $headname='';\r
+               my $headval='';\r
+               \r
+               # Line starts with whitespace. It's a continuation of the previous line.\r
+               # Concatenate the field value.\r
+               if($line =~ /^[ \t]+([^ \t](.*[^ \t])?)[ \t]*$/){\r
+                       if($lastname ne '') {\r
+                               $header{$lastname}.=$1;\r
+                       }\r
+               }\r
+               # Line starts with a name followed by colon.\r
+               elsif ($line =~ /^([^:]+):[ \t]*([^ \t](.*[^ \t])?)[ \t]*$/) {\r
+                       $headname = lc($1);\r
+                       $headval = $2;\r
+                       # If there already was a header field with the same name then the value\r
+                       # is concantenated, separated by comma.\r
+                       if ($header{$headname} ne '') {\r
+                               $header{$headname}.=', '.$headval;\r
+                       }\r
+                       # otherwise just save the value\r
+                       else {\r
+                               $header{$headname}=$headval;\r
+                       }\r
+                       $lastname = $headname;\r
+               }\r
+       }\r
+       \r
+       # If argument was a path the file must be closed. \r
+       unless (ref($headerpath)) {\r
+               close ($headerfile);\r
+       }\r
+       \r
+       return %header;\r
+}\r
+\r
+# Function to read configuration files.\r
+# In each line the '#' and everything after it is treated as a comment and\r
+# ignored.\r
+# The format is:\r
+#  name = value\r
+# There can be whitespaces (space, tab) before after or between the name, value\r
+# and '='. Leading and trailing whitespaces are not part of the value or name.\r
+# Name can be made of letters, numbers, '_', '-', and '.'. Names are case\r
+# sensitive.\r
+#   \r
+# In some cases it may not possible to save the required data in this\r
+# format. There may be a need to change this format in the future.\r
+# \r
+# Returns a hash containing the values.\r
+# \r
+# Argument can be a path or a file handle. In case of a file handle it will just\r
+# read the file. In case of path it opens the file before reading and closes\r
+# after. On failure (file not open) returns empty hash.\r
+# \r
+# This function is duplicated in configure.pl. configure.pl can't use a function\r
+# from a file that it generates. That would create a dependency loop.\r
+# \r
 sub readconfigfile {\r
        (my $configpath) = @_;\r
        my $configfile;\r
        my %config;\r
        \r
-       if (open ($configfile, "<", $configpath)) {\r
-               while (defined(my $line = <$configfile>)) {\r
-                       $line =~ s/[\r\n]//g;\r
-                       $line =~ s/#.*$//;\r
-                       if ($line =~ /^ *([a-zA-Z0-9_\-\.]+) *= *(.*)$/){\r
-                               my $name=$1;\r
-                               my $value=$2;\r
-                               $value =~ s/ *$//;\r
-                               $config{$name}=$value;\r
-                       }\r
+       # check if $configpath is actually a path or maybe a filehandle\r
+       # filehandles are references.\r
+       if(ref($configpath)) {\r
+               $configfile=$configpath;\r
+       }\r
+       else {\r
+               unless (open ($configfile, "<", $configpath)) {\r
+                       return %config;\r
                }\r
+       }\r
+       \r
+       while (defined(my $line = <$configfile>)) {\r
+               $line =~ s/[\r\n]//g;\r
+               $line =~ s/#.*$//; #comment\r
+               if ($line =~ /^[ \t]*([a-zA-Z0-9_\-\.]+)[ \t]*=[ \t]*([^ \t](.*[^ \t])?)[ \t]*$/){\r
+                       my $name=$1;\r
+                       my $value=$2;\r
+                       $config{$name}=$value;\r
+               }\r
+       }\r
+       \r
+       # If argument was a path the file must be closed. \r
+       unless (ref($configpath)) {\r
                close ($configfile);\r
        }\r
        return %config;\r