0

I want to receive a POST request from a JS client with a json body (i.e. this is not form data), and save the .gigs (javascript) array to a file, after checking the .password field. This is all my code (based on Receive JSON POST with PHP)

$json_params = file_get_contents("php://input");

if (strlen($json_params) > 0 && isValidJSON($json_params)){
    /* json_decode(..., true) returns an 'array', not an 'object'
   * Working combination: json_decode($json_params) WITH $inp->password
   */
  $inp = json_decode($json_params);
} else {
    echo "could not decode POST body";
    return;
}

$password = $inp->password;
// echo $password;

if ($password == "****") {
  $gigs = $inp['gigs'];
  // WAS $res = file_put_contents('gigs.json', json_encode($gigs), TEXT_FILE);
  $res = file_put_contents('gigs.json', json_encode($gigs));

  if ($res > 0) {
    echo "Success";
    return;
  } else {
    if (!$res) {
      http_response_code(500);
      echo "file_put_contents error:".$res;
      return;
    } else {
      http_response_code(500);
      echo "Error: saved zero data!";
      return;
    }
  }
} 
else {
  // http_response_code(403);      // (2)
  echo "Password invalid";
  return;
}

What I find is that

  • if I comment out the if statement and uncomment echo $password; then the right password is there
  • if I uncomment line 2, which I want to do, then I get back a 500 and the error logs refer an Illegal string offset 'password' in line (1) above. Without that I get back a "Success" (all for the same password).

I don't understand what is happening, nor how to get 200, 403 and 500 error messages safely.

Simon H
  • 20,332
  • 14
  • 71
  • 128
  • why you say `POST request` while you are reading `php://input`? Also `$inp = "I never got set";` -> that's what `null` is usually for. – Marcin Orlowski Apr 17 '17 at 14:56
  • That may be an abuse of words by my. I am sending an ajax POST from the client. I don't understand PHP at all, so I may well be doing something very wrong. – Simon H Apr 17 '17 at 14:56
  • Well, you are doing most things wrong there – Marcin Orlowski Apr 17 '17 at 14:57
  • If you use `true` in `json_decode()` it returns an array, not an object. – Jay Blanchard Apr 17 '17 at 15:05
  • I've tried with and without `true`. When I toggle, I see that I need different ways to access the json content, but in either case I still get problems if I uncomment line (2) – Simon H Apr 17 '17 at 15:18

1 Answers1

1

Note

$json_params = file_get_contents("php://input");

If your scripts are running upon regular HTTP requests, passing data like it comes from HTML form, them you should consider using $_POST for your content, not php://input. If you expect JSON in request body, then I'd be fine, yet I'd also check content type for application/json.

Next:

$inp = "I never got set";

if (strlen($json_params) > 0 && isValidJSON($json_params)){
  $inp = json_decode($json_params, true);
}

$password = $inp->password;
$password = $inp['password'];

This is pretty broken. First, see json_decode() arguments (2nd) -> you are decoding to array (true), not object (false), so only $password = $inp['password']; will work in your case. Also the whole code will fail when your input data is invalid as in that case $np is rubbish string, not the array you try to read later on. Use null as default value and check for that prior further use.

Next:

$res = file_put_contents('gigs.json', json_encode($gigs), FILE_TEXT);

there's no FILE_TEXT option for file_put_contents(). Nor you'd need one.

Once you correct these you'd be fine. Also print_r() and var_dump() may be the functions you wish to get familiar with for your further debugging.

In general http://php.net/ -> lookup for functions you are about to use.

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
  • Thanks - your advice regarding `php://input` contradicts the majority of comments on SO I found, but I will try it if I can work out how to use it (php.net seems to be unreachable at present) – Simon H Apr 17 '17 at 15:15
  • Do you suggest using - or not using - `true` in the json_decode? I know that my one of my two `$password =` must be wrong but which is the better way to do it? – Simon H Apr 17 '17 at 15:23
  • 1
    `$_POST` can only be used with standard form encodings (`application/x-www-form-urlencoded` and `multipart/form-data`). I believe the OP is expecting JSON as request body, so `php://input` should be fine. – Álvaro González Apr 17 '17 at 15:26
  • If your whole code is OOP, then I'd personally prefer having JSON object too, but in your particular case it does not matter really. Choose what you like better. – Marcin Orlowski Apr 17 '17 at 15:27