12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826 |
- #!/usr/bin/env perl
- BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s,/[^/]+$,/,;
- unshift @INC, $srcdir;
- }
- use strict;
- use IO::Socket;
- use Test::More tests => 176;
- use LightyTest;
- my $tf = LightyTest->new();
- my $t;
- ok($tf->start_proc == 0, "Starting lighttpd") or die();
- ## Basic Request-Handling
- $t->{REQUEST} = ( <<EOF
- GET / HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Valid HTTP/1.0 Request') or die();
- $t->{REQUEST} = ( <<EOF
- OPTIONS * HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'OPTIONS');
- $t->{REQUEST} = ( <<EOF
- OPTIONS / HTTP/1.1
- Host: www.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'OPTIONS');
- $t->{REQUEST} = ( <<EOF
- GET /index.html%00 HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'URL-encoding, %00');
- $t->{REQUEST} = ( <<EOF
- POST /12345.txt HTTP/1.0
- Host: 123.example.org
- Content-Length: 2147483648
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 413 } ];
- ok($tf->handle_http($t) == 0, 'Content-Length > max-request-size');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
- ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg');
- $t->{REQUEST} = ( <<EOF
- GET /image.JPG HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
- ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg (upper case)');
- $t->{REQUEST} = ( <<EOF
- GET /Foo.txt HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'uppercase filenames');
- $t->{REQUEST} = ( <<EOF
- GET /foobar?foobar HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'file not found + querystring');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain' } ];
- ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype text/plain');
- $t->{REQUEST} = ( <<EOF
- GET /12345.html HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/html' } ];
- ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype text/html');
- $t->{REQUEST} = ( <<EOF
- POST / HTTP/1.0
- Content-type: application/x-www-form-urlencoded
- Content-length: 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST request, empty request-body');
- $t->{REQUEST} = ( <<EOF
- HEAD / HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => ''} ];
- ok($tf->handle_http($t) == 0, 'HEAD request, no content');
- $t->{REQUEST} = ( <<EOF
- HEAD /12345.html HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
- ok($tf->handle_http($t) == 0, 'HEAD request, mimetype text/html, content-length');
- $t->{REQUEST} = ( <<EOF
- HEAD http://123.example.org/12345.html HTTP/1.1
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
- ok($tf->handle_http($t) == 0, 'Hostname in first line, HTTP/1.1');
- $t->{REQUEST} = ( <<EOF
- HEAD https://123.example.org/12345.html HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-HTTP-Content' => '', 'Content-Type' => 'text/html', 'Content-Length' => '6'} ];
- ok($tf->handle_http($t) == 0, 'Hostname in first line as https url');
- $t->{REQUEST} = ( <<EOF
- HEAD /foobar?foobar HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, '-HTTP-Content' => '' } ];
- ok($tf->handle_http($t) == 0, 'HEAD request, file-not-found, query-string');
- # (expect 200 OK instead of 100 Continue since request body sent with request)
- # (if we waited to send request body, would expect 100 Continue, first)
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Content-Length: 4
- Expect: 100-continue
- 123
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Continue, Expect');
- # note Transfer-Encoding: chunked tests will fail with 411 Length Required if
- # server.stream-request-body != 0 in lighttpd.conf
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- a
- 0123456789
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked, lc hex');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- A
- 0123456789
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked, uc hex');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- 10
- 0123456789abcdef
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked, two hex');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- a
- 0123456789
- 0
- Test-Trailer: testing
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked, with trailer');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- a; comment
- 0123456789
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked, chunked header comment');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- az
- 0123456789
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked; bad chunked header');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- a
- 0123456789xxxxxxxx
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked; mismatch chunked header size and chunked data size');
- $t->{REQUEST} = ( <<EOF
- POST /cgi.pl?post-len HTTP/1.1
- Host: www.example.org
- Connection: close
- Content-Type: application/x-www-form-urlencoded
- Transfer-Encoding: chunked
- a ; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- 0123456789
- 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'POST via Transfer-Encoding: chunked; chunked header too long');
- ## ranges
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0-3
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => '1234' } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 0-3');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=-3
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => '45'."\n" } ];
- ok($tf->handle_http($t) == 0, 'GET, Range -3');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=3-
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => '45'."\n" } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 3-');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0-1,3-4
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => '12345' } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 0-1,3-4 (ranges merged)');
- $t->{REQUEST} = ( <<EOF
- GET /100.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0-1,97-98
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => <<EOF
- --fkj49sn38dcn3\r
- Content-Type: text/plain\r
- Content-Range: bytes 0-1/100\r
- \r
- 12\r
- --fkj49sn38dcn3\r
- Content-Type: text/plain\r
- Content-Range: bytes 97-98/100\r
- \r
- hi\r
- --fkj49sn38dcn3--\r
- EOF
- } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 0-1,97-98 (ranges not merged)');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0-
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'Content-Range' => 'bytes 0-5/6' } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 0-');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0--
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 416 } ];
- ok($tf->handle_http($t) == 0, 'GET, Range 0--');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=-2-3
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 416 } ];
- ok($tf->handle_http($t) == 0, 'GET, Range -2-3');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=-0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 416, 'HTTP-Content' => <<EOF
- <?xml version="1.0" encoding="iso-8859-1"?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>416 Range Not Satisfiable</title>
- </head>
- <body>
- <h1>416 Range Not Satisfiable</h1>
- </body>
- </html>
- EOF
- } ];
- ok($tf->handle_http($t) == 0, 'GET, Range -0');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=25-
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 416, 'HTTP-Content' => <<EOF
- <?xml version="1.0" encoding="iso-8859-1"?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <title>416 Range Not Satisfiable</title>
- </head>
- <body>
- <h1>416 Range Not Satisfiable</h1>
- </body>
- </html>
- EOF
- } ];
- ok($tf->handle_http($t) == 0, 'GET, Range start out of range');
- $t->{REQUEST} = ( <<EOF
- GET /range.pdf HTTP/1.1
- Host: 123.example.org
- Range: bytes=0-
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'GET, Range with range-requests-disabled');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: 0
- Range: bytes=0-3
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => "12345\n" } ];
- ok($tf->handle_http($t) == 0, 'GET, Range invalid range-unit (first)');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- Range: bytes=0-3
- Range: 0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206 } ];
- ok($tf->handle_http($t) == 0, 'GET, Range ignore invalid range (second)');
- $t->{REQUEST} = ( <<EOF
- OPTIONS / HTTP/1.0
- Content-Length: 4
- 1234
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'OPTIONS with Content-Length');
- $t->{REQUEST} = ( <<EOF
- OPTIONS rtsp://221.192.134.146:80 RTSP/1.1
- Host: 221.192.134.146:80
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'OPTIONS for RTSP');
- my $nextyr = (gmtime(time()))[5] + 1900 + 1;
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- If-Modified-Since2: Sun, 01 Jan $nextyr 00:00:03 GMT
- If-Modified-Since: Sun, 01 Jan $nextyr 00:00:02 GMT
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
- ok($tf->handle_http($t) == 0, 'Similar Headers (bug #1287)');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- If-Modified-Since: Sun, 01 Jan $nextyr 00:00:02 GMT
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, '-Content-Length' => '', 'Content-Type' => 'text/html' } ];
- ok($tf->handle_http($t) == 0, 'Status 304 has no Content-Length (#1002)');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain' } ];
- $t->{SLOWREQUEST} = 1;
- ok($tf->handle_http($t) == 0, 'GET, slow \\r\\n\\r\\n (#2105)');
- undef $t->{SLOWREQUEST};
- $t->{REQUEST} = ( <<EOF
- GET /www/abc/def HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'pathinfo on a directory');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: ,close
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain', 'Connection' => 'close' } ];
- ok($tf->handle_http($t) == 0, 'Connection-header, leading comma');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: close,,TE
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain', 'Connection' => 'close' } ];
- ok($tf->handle_http($t) == 0, 'Connection-header, no value between two commas');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: close, ,TE
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain', 'Connection' => 'close' } ];
- ok($tf->handle_http($t) == 0, 'Connection-header, space between two commas');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: close,
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain', 'Connection' => 'close' } ];
- ok($tf->handle_http($t) == 0, 'Connection-header, comma after value');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: close,
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/plain', 'Connection' => 'close' } ];
- ok($tf->handle_http($t) == 0, 'Connection-header, comma and space after value');
- ## Low-Level Response-Header Parsing - HTTP/1.1
- $t->{REQUEST} = ( <<EOF
- GET / HTTP/1.1
- Host: www.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '+Date' => '' } ];
- ok($tf->handle_http($t) == 0, 'Date header');
- ## Low-Level Response-Header Parsing - Content-Length
- $t->{REQUEST} = ( <<EOF
- GET /12345.html HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
- ok($tf->handle_http($t) == 0, 'Content-Length for text/html');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
- ok($tf->handle_http($t) == 0, 'Content-Length for text/plain');
- ## Low-Level Response-Header Parsing - Location
- $t->{REQUEST} = ( <<EOF
- GET /dummydir HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/dummydir/' } ];
- ok($tf->handle_http($t) == 0, 'internal redirect in directory');
- $t->{REQUEST} = ( <<EOF
- GET /dummydir?foo HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/dummydir/?foo' } ];
- ok($tf->handle_http($t) == 0, 'internal redirect in directory + querystring');
- $t->{REQUEST} = ( <<EOF
- GET /~test%20ä_ HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/~test%20%C3%A4_/' } ];
- ok($tf->handle_http($t) == 0, 'internal redirect in directory with special characters');
- $t->{REQUEST} = ( <<EOF
- GET /~test%20ä_?foo HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => '/~test%20%C3%A4_/?foo' } ];
- ok($tf->handle_http($t) == 0, 'internal redirect in directory with special characters + querystring');
- ## simple-vhost
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Host: no-simple.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => '6' } ];
- ok($tf->handle_http($t) == 0, 'disabling simple-vhost via conditionals');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Host: simple.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'simple-vhost via conditionals');
- ## keep-alive
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Connection: keep-alive
- Host: 123.example.org
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.0 Keep-Alive');
- undef $t->{RESPONSE};
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Connection: keep-alive
- Host: 123.example.org
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.0 Keep-Alive');
- undef $t->{RESPONSE};
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.0
- Connection: keep-alive
- Host: 123.example.org
- GET /12345.txt HTTP/1.0
- Host: 123.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.0 Keep-Alive');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Connection: keep-alive
- Host: 123.example.org
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Explicit HTTP/1.1 Keep-Alive');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.1 Keep-Alive');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.1 Keep-Alive w/ extra blank b/w requests');
- $t->{REQUEST} = ( <<EOF
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- GET /12345.txt HTTP/1.1
- Host: 123.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'Implicit HTTP/1.1 Keep-Alive w/ excess blank b/w requests');
- ## 404 handlers
- $t->{REQUEST} = ( <<EOF
- GET /static/notfound HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => "static not found\n" } ];
- ok($tf->handle_http($t) == 0, '404 handler => static');
- $t->{REQUEST} = ( <<EOF
- GET /dynamic/200/notfound HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => "found here\n" } ];
- ok($tf->handle_http($t) == 0, '404 handler => dynamic(200)');
- $t->{REQUEST} = ( <<EOF
- GET /dynamic/302/notfound HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 302, 'Location' => "http://www.example.org/" } ];
- ok($tf->handle_http($t) == 0, '404 handler => dynamic(302)');
- $t->{REQUEST} = ( <<EOF
- GET /dynamic/404/notfound HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'HTTP-Content' => "Not found here\n" } ];
- ok($tf->handle_http($t) == 0, '404 handler => dynamic(404)');
- $t->{REQUEST} = ( <<EOF
- GET /dynamic/redirect_status/ HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'HTTP-Content' => "REDIRECT_STATUS\n" } ];
- ok($tf->handle_http($t) == 0, 'error handler => dynamic(REDIRECT_STATUS)');
- $t->{REQUEST} = ( <<EOF
- GET /dynamic/nostatus/notfound HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => "found here\n" } ];
- ok($tf->handle_http($t) == 0, '404 handler => dynamic(nostatus)');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?send404 HTTP/1.0
- Host: errors.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'HTTP-Content' => "send404\n" } ];
- ok($tf->handle_http($t) == 0, '404 generated by CGI should stay 404');
- ## config conditions
- $t->{REQUEST} = ( <<EOF
- GET /nofile.png HTTP/1.0
- Host: referer.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'condition: Referer - no referer');
- $t->{REQUEST} = ( <<EOF
- GET /nofile.png HTTP/1.0
- Host: referer.example.org
- Referer: http://referer.example.org/
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'condition: Referer - referer matches regex');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'condition: Referer - no referer');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: www.example.org
- Referer: http://referer.example.org/
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'condition: Referer - referer matches regex');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: www.example.org
- Referer: http://evil-referer.example.org/
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'condition: Referer - referer doesn\'t match');
- $t->{REQUEST} = ( <<EOF
- GET /nofile HTTP/1.1
- Host: bug255.example.org
- GET /nofile HTTP/1.1
- Host: bug255.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 403 }, { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'remote ip cache (#255)');
- $t->{REQUEST} = ( <<EOF
- GET /empty-ref.noref HTTP/1.0
- Cookie: empty-ref
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer is no set');
- $t->{REQUEST} = ( <<EOF
- GET /empty-ref.noref HTTP/1.0
- Cookie: empty-ref
- Referer:
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer is empty');
- $t->{REQUEST} = ( <<EOF
- GET /empty-ref.noref HTTP/1.0
- Cookie: empty-ref
- Referer: foobar
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'condition: $HTTP["referer"] == "" and Referer: foobar');
- ## case-insensitive filesystem policy
- ## check if lower-casing works
- $t->{REQUEST} = ( <<EOF
- GET /image.JPG HTTP/1.0
- Host: lowercase-allow
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'uppercase access');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: lowercase-allow
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'lowercase access');
- ## check that mod_auth works
- $t->{REQUEST} = ( <<EOF
- GET /image.JPG HTTP/1.0
- Host: lowercase-auth
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'uppercase access');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: lowercase-auth
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'lowercase access');
- ## check that mod_staticfile exclude works
- $t->{REQUEST} = ( <<EOF
- GET /image.JPG HTTP/1.0
- Host: lowercase-exclude
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: lowercase-exclude
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'lowercase access');
- ## check that mod_access exclude works
- $t->{REQUEST} = ( <<EOF
- GET /image.JPG HTTP/1.0
- Host: lowercase-deny
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
- $t->{REQUEST} = ( <<EOF
- GET /image.jpg HTTP/1.0
- Host: lowercase-deny
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'lowercase access');
- ## symlink policy
- my $docroot = $tf->{'TESTDIR'}."/tmp/lighttpd/servers/www.example.org/pages";
- sub init_testbed {
- return 0 unless eval { symlink("",""); 1 };
- my $f = "$docroot/index.html";
- my $l = "$docroot/index.xhtml";
- my $rc = undef;
- unless (-l $l) {
- return 0 unless symlink($f,$l);
- };
- $f = "$docroot/expire";
- $l = "$docroot/symlinked";
- $rc = undef;
- unless (-l $l) {
- return 0 unless symlink($f,$l);
- }
- return 1;
- };
- SKIP: {
- skip "perl does not support symlinking or setting up the symlinks failed.", 8 unless init_testbed;
- # allow case
- # simple file
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: symlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'allow: simple file');
- # symlinked file
- $t->{REQUEST} = ( <<EOF
- GET /index.xhtml HTTP/1.0
- Host: symlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'allow: symlinked file');
- # directly symlinked dir
- $t->{REQUEST} = ( <<EOF
- GET /symlinked/ HTTP/1.0
- Host: symlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'allow: directly symlinked dir');
- # symlinked dir in path
- $t->{REQUEST} = ( <<EOF
- GET /symlinked/access.txt HTTP/1.0
- Host: symlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'allow: symlinked dir in path');
- # deny case
- # simple file
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: nosymlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'deny: simple file');
- # symlinked file
- $t->{REQUEST} = ( <<EOF
- GET /index.xhtml HTTP/1.0
- Host: nosymlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'deny: symlinked file');
- # directly symlinked dir
- $t->{REQUEST} = ( <<EOF
- GET /symlinked/ HTTP/1.0
- Host: nosymlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'deny: directly symlinked dir');
- # symlinked dir in path
- $t->{REQUEST} = ( <<EOF
- GET /symlinked/access.txt HTTP/1.0
- Host: nosymlink.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
- ok($tf->handle_http($t) == 0, 'deny: symlinked dir in path');
- };
- ## mod_auth
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Missing Auth-token');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Basic \x80mFuOmphb
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid base64 Auth-token');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Basic bm90Oml0Cg==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Wrong Auth-token');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Basic amFuOmphbg==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - plain');
- SKIP: {
- skip "no crypt-des under openbsd", 2 if $^O eq 'openbsd';
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic ZGVzOmRlcw==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des)');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: basic ZGVzOmRlcw==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des) (lowercase)');
- }
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic c2hhOnNoYQ==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (sha)');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic c2hhOnNoYg==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (sha, wrong password)');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic YXByLW1kNTphcHItbWQ1
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (apr-md5)');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic YXByLW1kNTphcHItbWQ2
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (apr-md5, wrong password)');
- SKIP: {
- skip "no crypt-md5 under cygwin", 1 if $^O eq 'cygwin';
- skip "no crypt-md5 under darwin", 1 if $^O eq 'darwin';
- skip "no crypt-md5 under openbsd",1 if $^O eq 'openbsd';
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-htpasswd.example.org
- Authorization: Basic bWQ1Om1kNQ==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (crypt-md5)');
- }
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Basic bWQ1Om1kNA==
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token');
- ## this should not crash
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- User-Agent: Wget/1.9.1
- Authorization: Digest username="jan", realm="jan", nonce="9a5428ccc05b086a08d918e73b01fc6f",
- uri="/server-status", response="ea5f7d9a30b8b762f9610ccb87dea74f"
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
- ok($tf->handle_http($t) == 0, 'Digest-Auth: missing qop, no crash');
- # (Note: test case is invalid; mismatch between request line and uri="..."
- # is not what is intended to be tested here, but that is what is invalid)
- # https://redmine.lighttpd.net/issues/477
- ## this should not crash
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- User-Agent: Wget/1.9.1
- Authorization: Digest username="jan", realm="jan",
- nonce="b1d12348b4620437c43dd61c50ae4639",
- uri="/MJ-BONG.xm.mpc", qop=auth, noncecount=00000001",
- cnonce="036FCA5B86F7E7C4965C7F9B8FE714B7",
- response="29B32C2953C763C6D033C8A49983B87E"
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'Digest-Auth: missing nc (noncecount instead), no crash');
- $t->{REQUEST} = ( <<EOF
- GET /server-config HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Basic =
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid Base64');
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Digest username="jan", realm="download archiv",
- nonce="b3b26457000000003a9b34a3cd56d26e48a52a498ac9765d4b",
- uri="/server-status", qop=auth, nc=00000001,
- algorithm="md5-sess", response="049b000fb00ab51dddea6f093a96aa2e"
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
- ok($tf->handle_http($t) == 0, 'Digest-Auth: md5-sess + missing cnonce');
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Digest username="jan", realm="download archiv",
- nonce="b3b26457000000003a9b34a3cd56d26e48a52a498ac9765d4b",
- uri="/server-status", qop=auth, nc=00000001, cnonce="65ee1b37",
- algorithm="md5", response="049b000fb00ab51dddea6f093a96aa2e"
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401, 'WWW-Authenticate' => '/, stale=true$/' } ];
- ok($tf->handle_http($t) == 0, 'Digest-Auth: stale nonce');
- $t->{REQUEST} = ( <<EOF
- GET /server-status HTTP/1.0
- Host: auth-plain.example.org
- Authorization: Digest username = "jan", realm = "download archiv",
- nonce = "b3b26457000000003a9b34a3cd56d26e48a52a498ac9765d4b",
- uri = "/server-status", qop = auth, nc = 00000001, cnonce = "65ee1b37",
- algorithm = "md5", response = "049b000fb00ab51dddea6f093a96aa2e"
- EOF
- ); # note: trailing whitespace at end of request line above is intentional
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401, 'WWW-Authenticate' => '/, stale=true$/' } ];
- ok($tf->handle_http($t) == 0, 'Digest-Auth: BWS, trailing WS, stale nonce');
- ## mod_cgi
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'perl via cgi');
- if ($^O ne "cygwin") {
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl%20%20%20 HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'No source retrieval');
- } else {
- ok(1, 'No source retrieval; skipped on cygwin; see response.c');
- }
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl/foo?env=SCRIPT_NAME HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/cgi.pl' } ];
- ok($tf->handle_http($t) == 0, 'perl via cgi + pathinfo');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?internal-redir HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'perl via cgi and internal redirect from CGI');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?xsendfile HTTP/1.0
- Host: cgi.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Length' => 4348 } ];
- ok($tf->handle_http($t) == 0, 'X-Sendfile');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?external-redir HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 302, 'Location' => 'http://www.example.org:2048/' } ];
- ok($tf->handle_http($t) == 0, 'Status + Location via FastCGI');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl/?external-redir HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 302, 'Location' => 'http://www.example.org:2048/' } ];
- ok($tf->handle_http($t) == 0, 'Trailing slash as path-info (#1989: workaround broken operating systems)');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?nph=30 HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 502 } ];
- ok($tf->handle_http($t) == 0, 'NPH + perl, invalid status-code (#14)');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?nph=304 HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
- ok($tf->handle_http($t) == 0, 'NPH + perl, setting status-code (#1125)');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?nph=200 HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'NPH + perl, setting status-code');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=GATEWAY_INTERFACE HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'CGI/1.1' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: GATEWAY_INTERFACE');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?query_string HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'query_string', 'Content-Type' => 'text/plain' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: QUERY_STRING');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=SCRIPT_NAME HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/cgi.pl' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: SCRIPT_NAME');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl/path/info?env=SCRIPT_NAME HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/cgi.pl' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: SCRIPT_NAME w/ PATH_INFO');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl/path/info?env=PATH_INFO HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/path/info' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: PATH_INFO');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=HTTP_XX_YY123 HTTP/1.0
- xx-yy123: foo
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: quoting headers with numbers');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=HTTP_HOST HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'www.example.org' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=HTTP_HOST HTTP/1.1
- Host: www.example.org
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '+Content-Length' => '' } ];
- ok($tf->handle_http($t) == 0, 'cgi-env: HTTP_HOST');
- # broken header crash
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?crlfcrash HTTP/1.0
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 302, 'Location' => 'http://www.example.org/' } ];
- ok($tf->handle_http($t) == 0, 'broken header via perl cgi');
- ## mod_deflate
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: deflate.example.org
- Accept-Encoding: deflate
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '' } ];
- ok($tf->handle_http($t) == 0, 'Vary is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Accept-Encoding: deflate
- Host: deflate.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1288', '+Content-Encoding' => '' } ];
- ok($tf->handle_http($t) == 0, 'deflate - Content-Length and Content-Encoding is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Accept-Encoding: deflate
- Host: deflate-cache.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1288', '+Content-Encoding' => '' } ];
- ok($tf->handle_http($t) == 0, 'deflate - Content-Length and Content-Encoding is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Accept-Encoding: gzip
- Host: deflate.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1306', '+Content-Encoding' => '' } ];
- ok($tf->handle_http($t) == 0, 'gzip - Content-Length and Content-Encoding is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Accept-Encoding: gzip
- Host: deflate-cache.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Length' => '1306', '+Content-Encoding' => '' } ];
- ok($tf->handle_http($t) == 0, 'gzip - Content-Length and Content-Encoding is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.txt HTTP/1.0
- Host: deflate.example.org
- Accept-Encoding: gzip, deflate
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', '+Content-Encoding' => '' } ];
- ok($tf->handle_http($t) == 0, 'gzip, deflate - Content-Length and Content-Encoding is set');
- $t->{REQUEST} = ( <<EOF
- GET /index.txt HTTP/1.0
- Host: deflate.example.org
- Accept-Encoding: gzip, deflate
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', '+Content-Encoding' => '', 'Content-Type' => "text/plain; charset=utf-8" } ];
- ok($tf->handle_http($t) == 0, 'Content-Type is from the original file');
- $t->{REQUEST} = ( <<EOF
- GET /index.txt HTTP/1.0
- Host: deflate.example.org
- Accept-encoding:
- X-Accept-encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0
- User-Agent: MYOB/6.66 (AN/ON)
- Connection: close
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '-Content-Encoding' => '', 'Content-Type' => "text/plain; charset=utf-8" } ];
- ok($tf->handle_http($t) == 0, 'Empty Accept-Encoding');
- $t->{REQUEST} = ( <<EOF
- GET /index.txt HTTP/1.0
- Accept-Encoding: bzip2, gzip, deflate
- Host: deflate-cache.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Vary' => '', 'Content-Encoding' => 'gzip', 'Content-Type' => "text/plain; charset=utf-8" } ];
- ok($tf->handle_http($t) == 0, 'bzip2 requested but disabled');
- ## mod_extforward
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=REMOTE_ADDR HTTP/1.0
- Host: www.example.org
- X-Forwarded-For: 127.0.10.1
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.10.1' } ];
- ok($tf->handle_http($t) == 0, 'expect 127.0.10.1, from single ip');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=REMOTE_ADDR HTTP/1.0
- Host: www.example.org
- X-Forwarded-For: 127.0.10.1, 127.0.20.1
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ];
- ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from two ips');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=REMOTE_ADDR HTTP/1.0
- Host: www.example.org
- X-Forwarded-For: 127.0.10.1, 127.0.20.1, 127.0.30.1
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ];
- ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from chained proxies');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=REMOTE_ADDR HTTP/1.0
- Host: www.example.org
- Forwarded: for=127.0.10.1, for=127.0.20.1;proto=https, for=127.0.30.1;proto=http
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '127.0.20.1' } ];
- ok($tf->handle_http($t) == 0, 'expect 127.0.20.1, from chained proxies');
- ## mod_proxy
- do {
- my $tf_proxy = LightyTest->new();
- $tf_proxy->{CONFIGFILE} = 'proxy.conf';
- local $ENV{EPHEMERAL_PORT} = $tf->{PORT};
- ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or last;
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf_proxy->handle_http($t) == 0, 'valid request');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'lighttpd-1.4.x' } ];
- ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
- $t->{REQUEST} = ( <<EOF
- GET /rewrite/all/some+test%3axxx%20with%20space HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '/some+test%3Axxx%20with%20space' } ];
- ok($tf_proxy->handle_http($t) == 0, 'rewrited urls work with encoded path');
- ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
- } while (0);
- ## mod_secdownload
- use Digest::MD5 qw(md5_hex);
- use Digest::SHA qw(hmac_sha1 hmac_sha256);
- use MIME::Base64 qw(encode_base64url);
- my $secret = "verysecret";
- my ($f, $thex, $m);
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'skipping secdownload - direct access');
- ## MD5
- $f = "/index.html";
- $thex = sprintf("%08x", time);
- $m = md5_hex($secret.$f.$thex);
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'secdownload (md5)');
- $thex = sprintf("%08x", time - 1800);
- $m = md5_hex($secret.$f.$thex);
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 410 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - gone (timeout) (md5)');
- $t->{REQUEST} = ( <<EOF
- GET /sec$f HTTP/1.0
- Host: vvv.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - direct access (md5)');
- $f = "/noexists";
- $thex = sprintf("%08x", time);
- $m = md5_hex($secret.$f.$thex);
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - timeout (md5)');
- if (!$tf->has_crypto()) {
- for (1..4) { ok(1, "secdownload (hmac-sha1) (skipped) - (missing SSL support)"); }
- for (1..5) { ok(1, "secdownload (hmac-sha256) (skipped) - (missing SSL support)"); }
- }
- else {
- ## HMAC-SHA1
- $f = "/index.html";
- $thex = sprintf("%08x", time);
- $m = encode_base64url(hmac_sha1("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha1.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'secdownload (hmac-sha1)');
- $thex = sprintf("%08x", time - 1800);
- $m = encode_base64url(hmac_sha1("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha1.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 410 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - gone (timeout) (hmac-sha1)');
- $t->{REQUEST} = ( <<EOF
- GET /sec$f HTTP/1.0
- Host: vvv-sha1.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - direct access (hmac-sha1)');
- $f = "/noexists";
- $thex = sprintf("%08x", time);
- $m = encode_base64url(hmac_sha1("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha1.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - timeout (hmac-sha1)');
- ## HMAC-SHA256
- $f = "/index.html";
- $thex = sprintf("%08x", time);
- $m = encode_base64url(hmac_sha256("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha256.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'secdownload (hmac-sha256)');
- ## HMAC-SHA256
- $f = "/index.html?qs=1";
- $thex = sprintf("%08x", time);
- $m = encode_base64url(hmac_sha256("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha256.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
- ok($tf->handle_http($t) == 0, 'secdownload (hmac-sha256) with hash-querystr');
- $thex = sprintf("%08x", time - 1800);
- $m = encode_base64url(hmac_sha256("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha256.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 410 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - gone (timeout) (hmac-sha256)');
- $t->{REQUEST} = ( <<EOF
- GET /sec$f HTTP/1.0
- Host: vvv-sha256.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - direct access (hmac-sha256)');
- $f = "/noexists";
- $thex = sprintf("%08x", time);
- $m = encode_base64url(hmac_sha256("/$thex$f", $secret));
- $t->{REQUEST} = ( <<EOF
- GET /sec/$m/$thex$f HTTP/1.0
- Host: vvv-sha256.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
- ok($tf->handle_http($t) == 0, 'secdownload - timeout (hmac-sha256)');
- } # SKIP if lighttpd built without crypto algorithms (e.g. without openssl)
- ## mod_setenv
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=TRAC_ENV HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'tracenv' } ];
- ok($tf->handle_http($t) == 0, 'query first setenv');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=SETENV HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'setenv' } ];
- ok($tf->handle_http($t) == 0, 'query second setenv');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=NEWENV HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'newenv' } ];
- ok($tf->handle_http($t) == 0, 'query set-environment');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=HTTP_FOO HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo' } ];
- ok($tf->handle_http($t) == 0, 'query add-request-header');
- $t->{REQUEST} = ( <<EOF
- GET /cgi.pl?env=HTTP_FOO2 HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'foo2' } ];
- ok($tf->handle_http($t) == 0, 'query set-request-header');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'BAR' => 'foo' } ];
- ok($tf->handle_http($t) == 0, 'query add-response-header');
- $t->{REQUEST} = ( <<EOF
- GET /index.html HTTP/1.0
- Host: www.example.org
- EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'BAR2' => 'bar2' } ];
- ok($tf->handle_http($t) == 0, 'query set-response-header');
- ok($tf->stop_proc == 0, "Stopping lighttpd");
|