File: httpd

package info (click to toggle)
libnet-server-perl 0.87-3sarge1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 400 kB
  • ctags: 215
  • sloc: perl: 2,787; sh: 347; makefile: 46
file content (177 lines) | stat: -rwxr-xr-x 3,847 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/perl -w -T

###----------------------------------------###
###     httpd server class                 ###
###----------------------------------------###
package MyHTTPD;

use vars qw(@ISA);
use strict;

### what type of server is this - we could
### use multi type when we add command line
### parsing to this http server to allow
### for different configurations
use Net::Server::PreFork;
@ISA = qw(Net::Server::PreFork);

### run the server
MyHTTPD->run();
exit;



### set up some server parameters
sub configure_hook {
  my $self = shift;

  $self->{server}->{port}   = ['*:80']; # port and addr to bind
  $self->{server}->{chdir}  = '/';      # chdir to root
  $self->{server}->{user}   = 'nobody'; # user to run as
  $self->{server}->{group}  = 'nobody'; # group to run as
  $self->{server}->{setsid} = 1;        # daemonize

  open(STDIN, '</dev/null') || die "Can't close STDIN [$!]";
  open(STDOUT,'>/dev/null') || die "Can't close STDOUT [$!]";
#  open(STDERR,'>&STDOUT')   || die "Can't close STDERR [$!]";


  $self->{document_root} = "/home/httpd/www";

  $self->{default_index} = [ qw(index.html index.htm main.htm) ];

  $self->{mime_types} = {
    html => 'text/html',
    htm  => 'text/html',
    gif  => 'image/gif',
    jpg  => 'image/jpeg',
  };
  $self->{mime_default} = 'text/plain';

}


### process the request
sub process_request {
  my $self = shift;

  local %ENV = ();

  ### read the first line of response
  my $line = <STDIN>;
  $line =~ s/[\r\n]+$//;
  unless( $line =~ /^ (\w+) \ + (\S+) \ + (HTTP\/1.\d) $ /x ){
    return error(400, "Bad request");
  }
  my ($method,$req,$protocol) = ($1,$2,$3);

  ### read in other headers
  $self->read_headers || return error(400, "Strange headers");

  ### do we support the type
  unless( $method =~ /GET|POST|HEAD/ ){
    return error(400, "Unsupported Method");
  }

  ### can we read that request
  unless( $req =~ m%^ (?:http://[^/]+)? (.*) $%x ){
    return error(400, "Malformed URL");
  }
  $ENV{REQUEST_URI} = $1;

  ### parse out the uri and query string
  my $uri = '';
  $ENV{QUERY_STRING} = '';
  if( $ENV{REQUEST_URI} =~ m%^ ([^\?]+) (?:\?(.+))? $%x ){
    $ENV{QUERY_STRING} = defined($2) ? $2 : '';
    $uri = $1;
  }

  ### clean up uri
  if( $uri=~/[\ \;]/ ){
    return error(400, "Malformed URL");
  }
  $uri =~ s/%(\w\w)/chr(hex($1))/eg;
  1 while $uri =~ s|^\.\./+||; # can't go below doc root

  
  ### at this point the uri should be ready to use
  $uri = "$self->{document_root}$uri";

  ### see if there's an index page
  if( -d $uri ){
    foreach (@{ $self->{default_index} }){
      if( -e "$uri/$_" ){
        $uri = "$uri/$_";
        last;
      }
    }
  }

  ### error 404
  if( !-e $uri ){
    return error(404, "file not found");

  ### directory listing
  }elsif( -d $uri ){
    ### need work on this
    print content_type('text/html'),"\r\n";
    print "Directory listing not supported";

  ### spit it out
  }elsif( open(FILE, "<$uri") ){
    
    my ($type) = $uri =~ m/([^\.]+)$/;
    $type = exists($self->{mime_types}->{$type})
      ? $self->{mime_types}->{$type} : $self->{mime_default};

    print status(200), content_type( $type ), "\r\n";

    print STDOUT $_ while (<FILE>);
    close(FILE);

  }else{
    return error(500, "Can't open file [$!]");
  }

}

sub read_headers {
  my $self = shift;

  $self->{headers} = {};

  while(<STDIN>){
    s/[\r\n]+$//;
    last unless length $_;
    unless( /^([\w\-]+) :[\ \t]+ (.+) $/x ){
      return 0;
    }
    my $key = "HTTP_" . uc($1);
    $key =~ tr/-/_/;
    $self->{headers}->{$key} = $2;
  }
  
  return 1;
}

sub content_type {
  my $type = shift;
  return "Content-type: $type\r\n";
}

sub error{
  print &status;
  
  print "\r\n";
  #,shift();
}

sub status {
  my $number = shift;
  my $msg    = shift || '';
  return "Status $number: $msg\r\n";
}

1;