Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
7.5 KiB

  1. use Strict;
  2. use HTTP::Daemon;
  3. use HTTP::Headers;
  4. use HTTP::Response;
  5. use URI;
  6. use IO::File;
  7. use File::stat;
  8. my $d = HTTP::Daemon->new( Listen => 10, LocalPort => 8080 ) || die;
  9. print "Please contact me at: <URL:", $d->url, ">\n";
  10. while (my $c = $d->accept) {
  11. while (my $r = $c->get_request) {
  12. print "\n";
  13. handleGET($r, $c) if ($r->method eq 'GET');
  14. handleHEAD($r, $c) if ($r->method eq 'HEAD');
  15. handleBITS_POST($r, $c) if ($r->method eq 'BITS_POST');
  16. }
  17. $c->close;
  18. undef($c);
  19. }
  20. sub handleBITS_POST {
  21. my ($req, $conn) = @_;
  22. #
  23. # interpret request
  24. #
  25. print "BITS_POST request =================================\n";
  26. print $req->headers()->as_string();
  27. handleCreateSession( $req, $conn ) if ($req->header('Bits-Packet-Type') eq 'Create-Session');
  28. handlePing( $req, $conn ) if ($req->header('Bits-Packet-Type') eq 'Ping');
  29. handleFragment( $req, $conn ) if ($req->header('Bits-Packet-Type') eq 'Fragment');
  30. handleCancelSession( $req, $conn ) if ($req->header('Bits-Packet-Type') eq 'Cancel-Session');
  31. handleCloseSession( $req, $conn ) if ($req->header('Bits-Packet-Type') eq 'Close-Session');
  32. print "end of request =====================================\n";
  33. }
  34. sub handleCreateSession {
  35. my ($req, $conn) = @_;
  36. #
  37. # generate reply
  38. #
  39. my $response = new HTTP::Response;
  40. $response->protocol('HTTP/1.1');
  41. $response->code(200);
  42. $response->header("Bits-Packet-Type" => 'Ack' );
  43. $response->header("Bits-Protocol" => '{7df0354d-249b-430f-820d-3d2a9bef4931}' );
  44. $response->header("Bits-Session-Id" => '{78d08036-4166-4bb2-b1fb-ac7288355913}' );
  45. $response->header("Content-Length" => 0 );
  46. # $response->header("Bits-Host-Id" => '10.0.0.1' );
  47. print "create-session reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  48. print $response->as_string();
  49. $conn->send_response($response);
  50. }
  51. sub handlePing {
  52. my ($req, $conn) = @_;
  53. my $sessionid = $req->header('Bits-Session-Id');
  54. #
  55. # generate reply
  56. #
  57. my $response = new HTTP::Response;
  58. $response->protocol('HTTP/1.1');
  59. $response->code(200);
  60. $response->header("Bits-Packet-Type" => 'Ack' );
  61. $response->header("Bits-Session-Id" => $sessionid );
  62. $response->header("Content-Length" => 0 );
  63. print "ping reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  64. print $response->as_string();
  65. $conn->send_response($response);
  66. }
  67. sub handleFragment {
  68. my ($req, $conn) = @_;
  69. my $sessionid = $req->header('Bits-Session-Id');
  70. my $file_length;
  71. my $end_offset;
  72. my $start_offset;
  73. # parse the incoming range
  74. #
  75. $_ = $req->header('Content-Range');
  76. ( $start_offset, $end_offset, $file_length ) = /bytes (\d+)\-(\d+)\/(\d+)/;
  77. #
  78. # generate reply
  79. #
  80. my $response = new HTTP::Response;
  81. $response->protocol('HTTP/1.1');
  82. $response->header("Bits-Packet-Type" => 'Ack' );
  83. $response->header("Bits-Session-Id" => $sessionid );
  84. $response->header("BITS-Received-Content-Range" => $end_offset+1 );
  85. $response->header("Content-Length" => 0 );
  86. #
  87. # success
  88. #
  89. $response->code(200);
  90. if ($end_offset+1 eq $file_length) {
  91. $response->header("Bits-Reply-Url" => '/foo' );
  92. }
  93. print "fragment reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  94. print $response->as_string();
  95. $conn->send_response($response);
  96. }
  97. sub handleCloseSession {
  98. my ($req, $conn) = @_;
  99. my $sessionid = $req->header('Bits-Session-Id');
  100. #
  101. # generate reply
  102. #
  103. my $response = new HTTP::Response;
  104. $response->protocol('HTTP/1.1');
  105. $response->code(500);
  106. $response->header("Bits-Packet-Type" => 'Ack' );
  107. $response->header("Bits-Session-Id" => $sessionid );
  108. $response->header("Content-Length" => 0 );
  109. print "close reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  110. print $response->as_string();
  111. $conn->send_response($response);
  112. }
  113. sub handleCancelSession {
  114. my ($req, $conn) = @_;
  115. my $sessionid = $req->header('Bits-Session-Id');
  116. #
  117. # generate reply
  118. #
  119. my $response = new HTTP::Response;
  120. $response->protocol('HTTP/1.1');
  121. $response->code(200);
  122. $response->header("Bits-Packet-Type" => 'Ack' );
  123. $response->header("Bits-Session-Id" => $sessionid );
  124. $response->header("Content-Length" => 0 );
  125. print "cancel reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  126. print $response->as_string();
  127. $conn->send_response($response);
  128. }
  129. sub handleHEAD {
  130. my ($req, $conn) = @_;
  131. print "HEAD request ================================\n";
  132. print $req->uri, "\n";
  133. print $req->headers()->as_string();
  134. #
  135. # Learn file size.
  136. #
  137. my $uri = new URI( $req->uri );
  138. my $path = $uri->path;
  139. my $filename = "c:\\$path";
  140. print "file name is ", $filename, "\n";
  141. $sb = stat($filename);
  142. my $response = new HTTP::Response;
  143. $response->protocol('HTTP/1.5');
  144. $response->code(200);
  145. $response->header("Content-Length" => $sb->size );
  146. # $response->header("Last-Modified" => "foo" );
  147. $response->headers()->last_modified( $sb->mtime );
  148. #
  149. # success
  150. #
  151. print "HEAD reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  152. print $response->as_string();
  153. $conn->send_response($response);
  154. print "end of request ================================\n";
  155. }
  156. sub handleGET {
  157. my ($req, $conn) = @_;
  158. print "GET request ================================\n";
  159. print $req->protocol," ", $req->uri, "\n";
  160. print $req->headers()->as_string();
  161. #
  162. # Interpret the requested range.
  163. #
  164. my $start_offset;
  165. my $end_offset;
  166. $_ = $req->header('Range');
  167. ( $start_offset, $end_offset ) = /bytes=(\d+)\-(\d+)/;
  168. my $offset = $start_offset;
  169. my $len = $end_offset - $start_offset+1;
  170. print("range is $start_offset to $end_offset, length is $len\n");
  171. #
  172. # Create the response.
  173. #
  174. my $response = new HTTP::Response;
  175. $response->protocol('HTTP/1.5');
  176. #
  177. # Open the file.
  178. #
  179. my $uri = new URI( $req->uri );
  180. my $path = $uri->path;
  181. my $filename = "c:\\$path";
  182. print "file name is ", $filename, "\n";
  183. open(fh, "< $filename") or die "Can't open : $!";
  184. binmode( fh );
  185. #
  186. # success
  187. #
  188. $sb = stat( $filename );
  189. my $file_length = $sb->size;
  190. seek( fh, $offset, SEEK_SET );
  191. my $buf;
  192. $count = sysread( fh, $buf, $len );
  193. if (!defined($count)) {
  194. print("error $! occurred in read\n");
  195. }
  196. if ($count eq $len) {
  197. $response->code(206);
  198. $response->header("Content-Length" => $len);
  199. $response->header("Content-Range" => "bytes $start_offset-$end_offset/$file_length");
  200. $response->headers()->last_modified( $sb->mtime );
  201. $response->content($buf);
  202. } else {
  203. print("read only ", $count, "bytes\n");
  204. $response->code(400);
  205. }
  206. print "GET reply - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
  207. print $response->headers()->as_string();
  208. $conn->send_response($response);
  209. print "end of request ================================\n";
  210. }