404 } |
404 } |
405 |
405 |
406 // anything on POST? |
406 // anything on POST? |
407 $postdata = ''; |
407 $postdata = ''; |
408 $_POST = array(); |
408 $_POST = array(); |
|
409 $_FILES = array(); |
409 if ( $method == 'POST' ) |
410 if ( $method == 'POST' ) |
410 { |
411 { |
411 // read POST data |
412 // read POST data |
412 if ( isset($_SERVER['HTTP_CONTENT_LENGTH']) ) |
413 if ( isset($_SERVER['HTTP_CONTENT_TYPE']) && preg_match('#^multipart/form-data; ?boundary=([A-z0-9_-]+)$#i', $_SERVER['HTTP_CONTENT_TYPE'], $match) ) |
413 { |
414 { |
414 $postdata = socket_read($remote, intval($_SERVER['HTTP_CONTENT_LENGTH']), PHP_BINARY_READ); |
415 // this is a multipart request |
|
416 $boundary =& $match[1]; |
|
417 $mode = 'data'; |
|
418 $last_line = ''; |
|
419 $i = 0; |
|
420 while ( $data = socket_read($remote, 8388608, PHP_NORMAL_READ) ) |
|
421 { |
|
422 $data_trim = trim($data, "\r\n"); |
|
423 if ( $mode != 'data' ) |
|
424 { |
|
425 $data = str_replace("\r", '', $data); |
|
426 } |
|
427 if ( ( $data_trim === "--$boundary" || $data_trim === "--$boundary--" ) && $i > 0 ) |
|
428 { |
|
429 // trim off the first LF and the last CRLF |
|
430 $currval_data = substr($currval_data, 1, strlen($currval_data)-3); |
|
431 |
|
432 // this is the end of a part of the message; parse it into either $_POST or $_FILES |
|
433 if ( is_string($have_a_file) ) |
|
434 { |
|
435 |
|
436 // write data to a temporary file |
|
437 $errcode = UPLOAD_ERR_OK; |
|
438 $tempfile = tempnam('phpupload', ( function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp' )); |
|
439 if ( $fh = @fopen($tempfile, 'w') ) |
|
440 { |
|
441 if ( empty($have_a_file) ) |
|
442 { |
|
443 $errcode = UPLOAD_ERR_NO_FILE; |
|
444 } |
|
445 else |
|
446 { |
|
447 fwrite($fh, $currval_data); |
|
448 } |
|
449 fclose($fh); |
|
450 } |
|
451 else |
|
452 { |
|
453 $errcode = UPLOAD_ERR_CANT_WRITE; |
|
454 } |
|
455 $_FILES[$currval_name] = array( |
|
456 'name' => $have_a_file, |
|
457 'type' => $currval_type, |
|
458 'size' => filesize($tempfile), |
|
459 'tmp_name' => $tempfile, |
|
460 'error' => $errcode |
|
461 ); |
|
462 } |
|
463 else |
|
464 { |
|
465 $_POST[$currval_name] = $currval_data; |
|
466 } |
|
467 } |
|
468 |
|
469 if ( $data_trim === "--$boundary" ) |
|
470 { |
|
471 // switch from "data" mode to "headers" mode |
|
472 $currval_name = ''; |
|
473 $currval_data = ''; |
|
474 $currval_type = ''; |
|
475 $have_a_file = false; |
|
476 $mode = 'headers'; |
|
477 } |
|
478 else if ( $data_trim === "--$boundary--" ) |
|
479 { |
|
480 // end of request |
|
481 break; |
|
482 } |
|
483 else if ( ( empty($data_trim) && empty($last_line) ) && $mode == 'headers' ) |
|
484 { |
|
485 // start of data |
|
486 $mode = 'data'; |
|
487 } |
|
488 else if ( $mode == 'headers' ) |
|
489 { |
|
490 // read header |
|
491 // we're only looking for Content-Disposition and Content-Type |
|
492 if ( preg_match('#^Content-Disposition: form-data; name="([^"\a\t\r\n]+)"(?:; filename="([^"\a\t\r\n]+)")?#i', $data_trim, $match) ) |
|
493 { |
|
494 // content-disposition header, set name and mode. |
|
495 $currval_name = $match[1]; |
|
496 if ( isset($match[2]) ) |
|
497 { |
|
498 $have_a_file = $match[2]; |
|
499 } |
|
500 else |
|
501 { |
|
502 $have_a_file = false; |
|
503 } |
|
504 } |
|
505 else if ( preg_match('#^Content-Type: ([a-z0-9-]+/[a-z0-9/-]+)$#i', $data_trim, $match) ) |
|
506 { |
|
507 $currval_type = $match[1]; |
|
508 } |
|
509 } |
|
510 else if ( $mode == 'data' ) |
|
511 { |
|
512 $currval_data .= $data; |
|
513 } |
|
514 $last_line = $data_trim; |
|
515 $i++; |
|
516 } |
415 } |
517 } |
416 else |
518 else |
417 { |
519 { |
418 $postdata = socket_read($remote, 8388608, PHP_NORMAL_READ); |
520 if ( isset($_SERVER['HTTP_CONTENT_LENGTH']) ) |
419 } |
521 { |
420 if ( preg_match_all('/(^|&)([a-z0-9_\.\[\]-]+)(=[^ &]+)?/', $postdata, $matches) ) |
522 $postdata = socket_read($remote, intval($_SERVER['HTTP_CONTENT_LENGTH']), PHP_BINARY_READ); |
421 { |
523 } |
422 if ( isset($matches[1]) ) |
524 else |
423 { |
525 { |
424 foreach ( $matches[0] as $i => $_ ) |
526 $postdata = socket_read($remote, 8388608, PHP_NORMAL_READ); |
|
527 } |
|
528 if ( preg_match_all('/(^|&)([a-z0-9_\.\[\]-]+)(=[^ &]+)?/', $postdata, $matches) ) |
|
529 { |
|
530 if ( isset($matches[1]) ) |
425 { |
531 { |
426 $_POST[$matches[2][$i]] = ( !empty($matches[3][$i]) ) ? urldecode(substr($matches[3][$i], 1)) : true; |
532 foreach ( $matches[0] as $i => $_ ) |
|
533 { |
|
534 $_POST[$matches[2][$i]] = ( !empty($matches[3][$i]) ) ? urldecode(substr($matches[3][$i], 1)) : true; |
|
535 } |
427 } |
536 } |
428 } |
537 } |
429 } |
538 } |
430 } |
539 } |
431 |
540 |
511 continue; |
624 continue; |
512 } |
625 } |
513 } |
626 } |
514 |
627 |
515 $this->send_standard_response($remote, $handler, $uri, $params); |
628 $this->send_standard_response($remote, $handler, $uri, $params); |
|
629 |
|
630 // now that we're done sending the response, delete any temporary uploaded files |
|
631 if ( !empty($_FILES) ) |
|
632 { |
|
633 foreach ( $_FILES as $file_data ) |
|
634 { |
|
635 if ( file_exists($file_data['tmp_name']) ) |
|
636 { |
|
637 @unlink($file_data['tmp_name']); |
|
638 } |
|
639 } |
|
640 } |
516 |
641 |
517 if ( !$this->in_keepalive && defined('HTTPD_WS_CHILD') ) |
642 if ( !$this->in_keepalive && defined('HTTPD_WS_CHILD') ) |
518 { |
643 { |
519 // if ( defined('HTTPD_WS_CHILD') ) |
644 // if ( defined('HTTPD_WS_CHILD') ) |
520 // status('Closing connection'); |
645 // status('Closing connection'); |
759 $result = @call_user_func($handler['function'], $this, $socket); |
884 $result = @call_user_func($handler['function'], $this, $socket); |
760 $this->in_scriptlet = false; |
885 $this->in_scriptlet = false; |
761 $output = ob_get_contents(); |
886 $output = ob_get_contents(); |
762 ob_end_clean(); |
887 ob_end_clean(); |
763 } |
888 } |
|
889 // throw an HttpExceptionFatal when you need to break out of an in-progress scriptlet due to an error, use it in place of die() or exit() |
|
890 catch ( HttpExceptionFatal $e ) |
|
891 { |
|
892 restore_error_handler(); |
|
893 $this->send_http_error($socket, 500, "A handler crashed reporting a fatal exception; see the command line for details."); |
|
894 if ( function_exists('status') ) |
|
895 status("fatal exception in handler {$handler['id']}:\n$e"); |
|
896 return true; |
|
897 } |
764 catch ( Exception $e ) |
898 catch ( Exception $e ) |
765 { |
899 { |
766 restore_error_handler(); |
900 restore_error_handler(); |
767 $this->send_http_error($socket, 500, "A handler crashed with an exception; see the command line for details."); |
901 $this->send_http_error($socket, 500, "There was an uncaught exception during the execution of a scripted handler function. See the command line for details."); |
768 if ( function_exists('status') ) |
902 if ( function_exists('status') ) |
769 status("caught exception in handler {$handler['id']}:\n$e"); |
903 status("uncaught exception in handler {$handler['id']}:\n$e"); |
770 return true; |
904 return true; |
771 } |
905 } |
772 restore_error_handler(); |
906 restore_error_handler(); |
773 |
907 |
774 // the handler function should return this magic string if it writes its own headers and socket data |
908 // the handler function should return this magic string if it writes its own headers and socket data |