3 # FIXME rewrite to use non-blocking IO and put limits on waiting
8 #fcntl(HANDLE, F_GETFL, $flags)
9 # or die "Couldn't get flags for HANDLE : $!\n";
10 #$flags |= O_NONBLOCK;
11 #fcntl(HANDLE, F_SETFL, $flags)
12 # or die "Couldn't set flags for HANDLE: $!\n";
14 #Once a filehandle is set for non-blocking I/O, the sysread or syswrite calls that would block will instead return undef and
20 use vars qw($output_path $g_filename $flags $buffer $the_end $refills_at_end $content_length $bytes_written $progress_written $bytes_left $boundary);
22 $output_path = $ARGV[0];
28 $bytes_left = 4000; # if the headers are bigger than this... too bad
29 # FIXME if the entire request (including file contents) is less than 4000 this causes the program to hang. This happens with firefox when the file is deleted before hitting submit
35 $size = length $buffer;
36 if($the_end == 1 || $bytes_left - $size < 1) {
38 if($refills_at_end > 10) {
39 die('refill_buffer called too many times (11) after EOF was reached');
43 return unless $size < 1000;
44 $max_read = (1100 - $size);
45 if($max_read > ($bytes_left - $size)) {
46 $max_read = ($bytes_left - $size);
48 $ret = sysread STDIN, $buffer, $max_read, $size;
51 } elsif($ret == undef) {
52 die("read returned: " . $!);
56 # remove x bytes from buffer and return them
57 # read_line doesn't use this, but keeps bytes_count anyway
61 $str = substr $buffer, 0, $count;
62 $buffer = substr $buffer, $count;
63 $bytes_left -= $count;
67 # mark the entire buffer as used
69 $bytes_left -= length $buffer;
73 # returns the next line from the input stream (not including the trailing crlf)
79 $size = length $buffer;
80 $crlf_index = index $buffer, "\r\n";
82 die("expected a line, but didn't find a CRLF for $size characters (bytes_left: $bytes_left)");
84 $line = substr $buffer, 0, $crlf_index;
85 $buffer = substr $buffer, ($crlf_index + 2);
86 $bytes_left -= $crlf_index + 2;
90 sub parse_main_headers {
95 $i = index($line, '/');
97 $line = substr($line, $i + 1);
98 $i = index($line, ' ');
100 $line = substr($line, 0, $i);
104 die('no filename passed');
108 $line =~ s/[^a-z0-9.-]/_/g;
117 if(substr(lc($line), 0, 16) eq 'content-length: ') {
118 $content_length = substr($line, 16);
119 } elsif(substr(lc($line), 0, 14) eq 'content-type: ') {
120 $i = index(lc($line), 'boundary=');
122 die('no boundary= in content-type header');
124 $boundary = substr $line, ($i + 9);
125 } elsif($line eq '') {
126 if($content_length == -1) {
127 die('No Content-Length header');
129 if($boundary eq "") {
130 die('No boundary found in headers');
132 $boundary = '--' . $boundary;
133 $bytes_left = $content_length;
139 # pass int from 0-1000
140 sub progress_bar_update {
143 if($pct > $progress_written) {
144 syswrite(PROGRESS_FD, '............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................', $pct - $progress_written);
145 $progress_written = $pct;
149 sub progress_bar_start {
150 my $progress_filename = shift; # global
151 $progress_written = 0;
153 open PROGRESS_FD, ">$progress_filename";
156 sub progress_bar_finish {
157 progress_bar_update(1000);
162 # save bytes past and update progress bar
169 $bytes_written += length($out);
170 $prog = $bytes_written / $content_length; # FIXME off by size of headers. do we care?
171 $prog = int($prog * 999 + .99);
172 progress_bar_update($prog);
175 sub save_to_next_boundary {
176 my $filename = shift;
178 my $crlfboundary = "\r\n$boundary";
179 open FD, ">$output_path/partial/$filename";
180 progress_bar_start("$output_path/progress/$filename");
183 $i = index $buffer, $crlfboundary;
189 output(read_buff($i));
191 read_buff(2); # remove crlf between content and boundary #FIXME make sure this exists
193 progress_bar_finish();
207 $line = lc(read_line());
209 return save_to_next_boundary($g_filename);
211 #if(substr($line, 0, 21) eq 'content-disposition: ') {
212 # $i = index($line, 'filename="');
214 # die('no filename=" in content-disposition sub-header');
216 # $i2 = index($line, '"', ($i + 10));
218 # die('no filename=" in content-disposition sub-header');
220 # $filename = lc(substr($line, ($i + 10), ($i2 - ($i + 10))));
221 # $filename =~ s/[^a-z0-9.-]/_/g;
222 # $filename =~ s/^[.-]/_/;
223 #} elsif($line eq '') {
224 # if($filename eq "") {
225 # die('No filename found in headers on part');
227 # return save_to_next_boundary($filename);
233 print "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 8\r\n\r\nReceived";
242 if($line eq $boundary) {
244 } elsif($line eq ($boundary . '--')) {
247 die("Expecting boundary \"$boundary\" but got: \"$line\"");
254 #fcntl(STDIN, F_GETFL, $flags)
255 # or die "Couldn't get flags for STDIN : $!\n";
256 #$flags |= O_NONBLOCK;
257 #fcntl(STDIN, F_SETFL, $flags)
258 # or die "Couldn't set flags for STDIN: $!\n";