?
Solved

Error in POST request through fsocket

Posted on 2005-04-11
15
Medium Priority
?
409 Views
Last Modified: 2010-08-05
This really applies more to the POST request than actually php, but because the script is implemented in php, i believe you people are my best help.  Probably small syntax problem, thus low points, sorry.  also open source project = not too important, just fun.

Again, i am back with my mirror admin script, but this is to try to allow automated syncroization from a file upload to a separate php script that takes the file and moves it to a directory there.  to do this, i am trying to get the mirror_admin script to POST through an fsocket to the remote script.  

I would prefer not to use cURL if avoidable for i want this very generic.

This is the current POST request (line 830 in the code)
$content_string = "
POST $dir HTTP/1.0
Host: $host
Keep-Alive: 300
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
Conteht-Length: $total_length
-----------------------------265001916915724
Content-Disposition: form-data; name=\"pass\"

$pass
-----------------------------265001916915724
Content-Disposition: form-data; name=\"filename\"

$filename
-----------------------------265001916915724
Content-Disposition: form-data; name=\"hash\"

$file_hash
-----------------------------265001916915724
Content-Disposition: form-data; name=\"file\"; filename=\"$local_file\"
Content-Length: $file_len
Content-Type: $file_mime

$file_contents
-----------------------------265001916915724--\r\n\r\n";

this is recieved by the following script (all vars set above):
if($_POST[pass]===$PASSWORD){
      // upload file
      $local_file=$_FILES[file][tmp_name];
      $filename = $_POST[filename];
      $hash = $_POST[hash];
      if($hash != md5_file($local_file)){
            // failed hash, error code 1
            die('1');
      }
      // you could check if this works and ouput if it does.  currently does not
      if(move_uploaded_file($local_file,$DIRECTORY.$filename)){
            if($CONFIRM_UPLOAD){
                  // admin must confirm, error code 3
                  mail($ADMIN_EMAIL,'File Uploaded',"File $filename was just uploaded, please verify and move to proper directory");
                  die('3');
            } else {
                  // all good, error code 0
                  die('0');
            }
      } else {
            // failed to move, error code 2
            die('2');
            if($ADMIN_EMAIL){
                  mail($ADMIN_EMAIL,'Failed Upload',"File $filename just failed to upload.  check permissions on $DIRECTORY.");
            }
      }
}

the full sourcecode of mirror_admin.php (first script) can be found @ http://quad341.com/mirror_v2/test.php and i'll update the archive of all the files if requested.

thanks again.  person who assists will get credit in readme file

0
Comment
Question by:quad341
  • 7
  • 6
  • 2
15 Comments
 
LVL 6

Expert Comment

by:peyox
ID: 13759310
At the first glance:

if($_POST[pass]===$PASSWORD){

should be:

if($_POST[pass]==$PASSWORD){
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13764385
review your $content_string construction, POST $dir HTTP/1.0 should be POST $dir HTTP/1.0\r\n, same for Host: $host wich should be Host: $host\r\n
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13764763
do not forget \r\n (CRLF) on the end of your lines
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 6

Author Comment

by:quad341
ID: 13767761
peyox, === means exactly equal to.  it stops implicit conversions.

adding \r\n to every line made no difference. i'll mess with the link above to see why it's ignoring my period
0
 
LVL 6

Expert Comment

by:peyox
ID: 13768289
I know what === operator means. The problem is, that === requires both variables to be in the same type. If they are not (this is possible problem I sugested) this comparison will fail.

Do you get anything in print_r($_POST); ? Does it triggers your script?
0
 
LVL 6

Expert Comment

by:peyox
ID: 13768387
typo:
Conteht-Length: $total_length
      ----

Content, does it help?
0
 
LVL 6

Accepted Solution

by:
peyox earned 600 total points
ID: 13768855
Brand new code... I spent some time to figuring it out. I had to simulate your environment to get this done, but now it seems to work:
The following bugs were corrected:
- typo in content length header
- incorrect Content-Length calculation (it should be length of everything in data section, not only length of actual variables)

Here's the code (you can add additional headers if needed):

$headers  = "POST $dir HTTP/1.1\r\n";
$headers .= "Accept: */*\r\n";
$headers .= "Content-Type: multipart/form-data; boundary=---------------------------7d52521ec0a0a\r\n";
$headers .= "Host: $host\r\n";
$headers .= "Connection: Keep-Alive\r\n";

$postVars  = "-----------------------------7d52521ec0a0a\r\n";
$postVars .= "Content-Disposition: form-data; name=\"pass\"\r\n\r\n";
$postVars .= $pass."\r\n";
$postVars .= "-----------------------------7d52521ec0a0a\r\n";
$postVars .= "Content-Disposition: form-data; name=\"filename\"\r\n\r\n";
$postVars .= $filename."\r\n";
$postVars .= "-----------------------------7d52521ec0a0a\r\n";
$postVars .= "Content-Disposition: form-data; name=\"hash\"\r\n\r\n";
$postVars .= $file_hash."\r\n";
$postVars .= "-----------------------------7d52521ec0a0a\r\n";
$postVars .= "Content-Disposition: form-data; name=\"file\"; filename=\"$local_file\"\r\n\r\n";
$postVars .= "Content-Length: $file_len\r\n";
$postVars .= "Content-Type: $file_mime\r\n\r\n";
$postVars .= $file_contents."\r\n";
$postVars .= "-----------------------------7d52521ec0a0a--\r\n\r\n";

$total_length = strlen($postVars);
$headers .= "Content-Length: $total_length\r\n\r\n";

$content_string = $headers.$postVars;
0
 
LVL 6

Author Comment

by:quad341
ID: 13768878
good catch peyox for the typo, but no go.  i added a form to test it yesterday and sent it through a browser without a problem, so i know all the tests work.

when telnetting to the server on port 80, everything gets sent after the first \r\n\r\n (2 link feeds, end of headers) and it doesn't seem to listen to the rest of the transmission.  if i understood why this was, i could probably apply the same solution to this script.  the telnet session would generate error 400 from the server (local or remote) even when i sent the exact same query as the Live HTTP Headers extension in FireFox caught.

any ideas on this?  (peyox:  you will get some points for the typo find and credit in readme, but this is not completely working)

full system with all the current files (including the form in mirror_postscript.php) is available at http://quad341.com/projects/mirror_project.zip (the previous version i had posted is now at http://quad341.com/projects/mirrof_project_v.5.zip )
0
 
LVL 6

Expert Comment

by:peyox
ID: 13768881
One more thing:

Server responds like this:
HTTP/1.1 404 Not Found

So this part of the code will give the letter "H" instead of first digit of error code (you have to change it):
$error_code=fread($socket,1);
0
 
LVL 6

Author Comment

by:quad341
ID: 13768893
didn't see peyox's last post before i commented.  tried code and had same result.  

zip updated to have his code in it though.  points increased to 100
0
 
LVL 6

Expert Comment

by:peyox
ID: 13768956
This is my code (create two files getpost.php and test.php):

FILE: getpost.php
--------------------------------------------------------------------
<?
        print_r ($_REQUEST);
?>


FILE: test.php:
--------------------------------------------------------------------
<?
    $host = "localhost";
    $dir = "/ee/getpost.php";
    $filename="c:\\test.txt";
    $pass = "samplepassword";



    $pass_len = strlen($pass);
    $filename_len=strlen($filename);

    $local_file = $filename;
    // content for the password is constructed.
    // now try to send the file.  first will try to determine
    // mime type
    $file_mime = "text/plain";
    // now length
    $file_len = filesize($local_file);
    // hash the file
    $file_hash = md5_file($local_file);
    // need that length
    $hash_len = strlen($file_hash);
    // now read the file
    $file_handle = fopen($local_file,'r');
    $file_contents = fread($file_handle,$file_len);
    fclose($file_handle);
    // need total length
    $total_length = $pass_len + $filename_len + $hash_len + $file_len+300;
    // now build the header

    $headers  = "POST $dir HTTP/1.1\r\n";
    $headers .= "Accept: */*\r\n";
    $headers .= "Content-Type: multipart/form-data; boundary=---------------------------7d52521ec0a0a\r\n";
    $headers .= "Host: $host\r\n";
    $headers .= "Connection: Keep-Alive\r\n";


    $postVars  = "-----------------------------7d52521ec0a0a\r\n";
    $postVars .= "Content-Disposition: form-data; name=\"pass\"\r\n\r\n";
    $postVars .= $pass."\r\n";
    $postVars .= "-----------------------------7d52521ec0a0a\r\n";
    $postVars .= "Content-Disposition: form-data; name=\"filename\"\r\n\r\n";
    $postVars .= $filename."\r\n";
    $postVars .= "-----------------------------7d52521ec0a0a\r\n";
    $postVars .= "Content-Disposition: form-data; name=\"hash\"\r\n\r\n";
    $postVars .= $file_hash."\r\n";
    $postVars .= "-----------------------------7d52521ec0a0a\r\n";
    $postVars .= "Content-Disposition: form-data; name=\"file\"; filename=\"$local_file\"\r\n\r\n";
    $postVars .= "Content-Length: $file_len\r\n";
    $postVars .= "Content-Type: $file_mime\r\n\r\n";
    $postVars .= $file_contents."\r\n";
    $postVars .= "-----------------------------7d52521ec0a0a--\r\n\r\n";

    $total_length = strlen($postVars);
    $headers .= "Content-Length: $total_length\r\n\r\n";

    $content_string = $headers.$postVars;

    $socket = fsockopen($host, 80,$soc_err_no,$soc_err,5);

    print "<!-- $content_string -->";
    // now write this to the remote server
    fwrite($socket,$content_string);
    // get error code
    $error_code=fread($socket,1000);
    // close socket
    fclose($socket);



    // display the results
    echo "<pre>";
    echo "POST:<BR>".$content_string;
    echo "<br>";
    echo "Server response:<BR>".$error_code;
    echo "</pre>";
?>

OUTPUT:
--------------------------------------------------------------------
POST:
POST /ee/getpost.php HTTP/1.1
Accept: */*
Content-Type: multipart/form-data; boundary=---------------------------7d52521ec0a0a
Host: localhost
Connection: Keep-Alive
Content-Length: 564

-----------------------------7d52521ec0a0a
Content-Disposition: form-data; name="pass"

samplepassword
-----------------------------7d52521ec0a0a
Content-Disposition: form-data; name="filename"

c:\test.txt
-----------------------------7d52521ec0a0a
Content-Disposition: form-data; name="hash"

590a9d9ec06e39fdc57490cd9a119e6d
-----------------------------7d52521ec0a0a
Content-Disposition: form-data; name="file"; filename="c:\test.txt"

Content-Length: 11
Content-Type: text/plain

THIS A TEST
-----------------------------7d52521ec0a0a--

Server response:HTTP/1.1 200 OK
Date: Wed, 13 Apr 2005 02:44:50 GMT
Server: Apache/1.3.12 (Win32)
X-Powered-By: PHP/4.3.8
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

74
Array
(
    [pass] => samplepassword
    [filename] => c:\test.txt
    [hash] => 590a9d9ec06e39fdc57490cd9a119e6d
)

0
 
LVL 6

Author Comment

by:quad341
ID: 13769122
peyox has been an incredible help.

here's the final breakdown of what was wrong:  misspelling of content, miscalculation of length, misread of the response for the error code.

the error code is 1, meaning mis hash.  now here's my final question:  why would the file hash differently?  they both md5_file() the file, but come up with 2 different hashes.  did the file fail to transfer correctly or what?  it's supposed to protect against failed transfers, and it seems to be, but why is the transfer faileing (i'm testing with the readme file that is contained in the zip.  it's text and medium sized)
0
 
LVL 6

Author Comment

by:quad341
ID: 13769144
points updated.  they're going to peyox.  his help is amazing.

i found it:  the boundary is appended to the bottom of the file making the filesize and hash different.

how do i stop this?
0
 
LVL 6

Author Comment

by:quad341
ID: 13769171
found it.  there was an error after filename=\"[whatever]\"  in peyox's code:  he ends that line with \r\n\r\n when it should be \r\n because that is not the end of the headers.  it works perfect now.  thank you so much
0
 
LVL 6

Expert Comment

by:peyox
ID: 13769245
You are right it should be single CRLF. My mistake.
Thanks for the points.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to dynamically set the form action using jQuery.
Suggested Courses
Course of the Month15 days, 2 hours left to enroll

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question