3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 # FIXME rewrite to use non-blocking IO and put limits on waiting
21 #fcntl(HANDLE, F_GETFL, $flags)
22 # or die "Couldn't get flags for HANDLE : $!\n";
23 #$flags |= O_NONBLOCK;
24 #fcntl(HANDLE, F_SETFL, $flags)
25 # or die "Couldn't set flags for HANDLE: $!\n";
27 #Once a filehandle is set for non-blocking I/O, the sysread or syswrite calls that would block will instead return undef and
33 use vars qw($output_path $g_filename $flags $buffer $the_end $refills_at_end $content_length $bytes_written $progress_written $bytes_left $boundary);
35 $output_path = $ARGV[0];
41 $bytes_left = 4000; # if the headers are bigger than this... too bad
42 # 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
48 $size = length $buffer;
49 if($the_end == 1 || $bytes_left - $size < 1) {
51 if($refills_at_end > 10) {
52 die('refill_buffer called too many times (11) after EOF was reached');
56 return unless $size < 1000;
57 $max_read = (1100 - $size);
58 if($max_read > ($bytes_left - $size)) {
59 $max_read = ($bytes_left - $size);
61 $ret = sysread STDIN, $buffer, $max_read, $size;
64 } elsif($ret == undef) {
65 die("read returned: " . $!);
69 # remove x bytes from buffer and return them
70 # read_line doesn't use this, but keeps bytes_count anyway
74 $str = substr $buffer, 0, $count;
75 $buffer = substr $buffer, $count;
76 $bytes_left -= $count;
80 # mark the entire buffer as used
82 $bytes_left -= length $buffer;
86 # returns the next line from the input stream (not including the trailing crlf)
92 $size = length $buffer;
93 $crlf_index = index $buffer, "\r\n";
95 die("expected a line, but didn't find a CRLF for $size characters (bytes_left: $bytes_left)");
97 $line = substr $buffer, 0, $crlf_index;
98 $buffer = substr $buffer, ($crlf_index + 2);
99 $bytes_left -= $crlf_index + 2;
103 sub parse_main_headers {
108 $i = index($line, '/');
110 $line = substr($line, $i + 1);
111 $i = index($line, ' ');
113 $line = substr($line, 0, $i);
117 die('no filename passed');
121 $line =~ s/[^a-z0-9.-]/_/g;
130 if(substr(lc($line), 0, 16) eq 'content-length: ') {
131 $content_length = substr($line, 16);
132 } elsif(substr(lc($line), 0, 14) eq 'content-type: ') {
133 $i = index(lc($line), 'boundary=');
135 die('no boundary= in content-type header');
137 $boundary = substr $line, ($i + 9);
138 } elsif($line eq '') {
139 if($content_length == -1) {
140 die('No Content-Length header');
142 if($boundary eq "") {
143 die('No boundary found in headers');
145 $boundary = '--' . $boundary;
146 $bytes_left = $content_length;
152 # pass int from 0-1000
153 sub progress_bar_update {
156 if($pct > $progress_written) {
157 syswrite(PROGRESS_FD, '............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................', $pct - $progress_written);
158 $progress_written = $pct;
162 sub progress_bar_start {
163 my $progress_filename = shift; # global
164 $progress_written = 0;
166 open PROGRESS_FD, ">$progress_filename";
169 sub progress_bar_finish {
170 progress_bar_update(1000);
175 # save bytes past and update progress bar
182 $bytes_written += length($out);
183 $prog = $bytes_written / $content_length; # FIXME off by size of headers. do we care?
184 $prog = int($prog * 999 + .99);
185 progress_bar_update($prog);
188 sub save_to_next_boundary {
189 my $filename = shift;
191 my $crlfboundary = "\r\n$boundary";
192 open FD, ">$output_path/partial/$filename";
193 progress_bar_start("$output_path/progress/$filename");
196 $i = index $buffer, $crlfboundary;
202 output(read_buff($i));
204 read_buff(2); # remove crlf between content and boundary #FIXME make sure this exists
206 progress_bar_finish();
220 $line = lc(read_line());
222 return save_to_next_boundary($g_filename);
224 #if(substr($line, 0, 21) eq 'content-disposition: ') {
225 # $i = index($line, 'filename="');
227 # die('no filename=" in content-disposition sub-header');
229 # $i2 = index($line, '"', ($i + 10));
231 # die('no filename=" in content-disposition sub-header');
233 # $filename = lc(substr($line, ($i + 10), ($i2 - ($i + 10))));
234 # $filename =~ s/[^a-z0-9.-]/_/g;
235 # $filename =~ s/^[.-]/_/;
236 #} elsif($line eq '') {
237 # if($filename eq "") {
238 # die('No filename found in headers on part');
240 # return save_to_next_boundary($filename);
246 print "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 8\r\n\r\nReceived";
255 if($line eq $boundary) {
257 } elsif($line eq ($boundary . '--')) {
260 die("Expecting boundary \"$boundary\" but got: \"$line\"");
267 #fcntl(STDIN, F_GETFL, $flags)
268 # or die "Couldn't get flags for STDIN : $!\n";
269 #$flags |= O_NONBLOCK;
270 #fcntl(STDIN, F_SETFL, $flags)
271 # or die "Couldn't set flags for STDIN: $!\n";