Difference between revisions of "HTTP Post request to a PHP server"

From Second Life Wiki
Jump to navigation Jump to search
Line 23: Line 23:
  integer SECRET_STRING="XD4@5#-m";
  integer SECRET_STRING="XD4@5#-m";
   
   
xrequest(string url, list l)
xrequest(list l)
{
{
    integer i;
    integer i;
    integer len=llGetListLength(l) & 0xFFFE; // makes the list count even
    string body;
    string body;
    integer len=llGetListLength(l) & 0xFFFE; // make it even
     for (i=0;i<len;i+=2)
     for (i=0;i<len;i+=2)
     {
     {
        string varname=llList2String(l,i);
        string varname=llList2String(l,i);
        string varvalue=llList2String(l,i + 1);
        string varvalue=llList2String(l,i + 1);
        if (i>0) body+="&";
        if (i>0) body+="&";
        body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
        body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
    }
    }
    string hash=llMD5String(body+SECRET_STRING,SECRET_NUMBER);
    string hash=llMD5String(body+llEscapeURL(SECRET_STRING),SECRET_NUMBER);
    http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
    http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
}
}
</lsl>
</lsl>


Line 64: Line 63:


<php>
<php>
  <?php
<?php
   // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
   // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
   function llEscapeURL($s)
   function llEscapeURL($s)
   {
   {
  return str_replace(
    $s=str_replace(
  array("+","-",".","_"),
      array(" ","+","-",".","_"),
  array("%20","%2D","%2E","%5F"),
      array("%20","%20","%2D","%2E","%5F"),
  urlencode($s));
      urlencode($s));
    return $s;
   }   
   }   
    
    
Line 77: Line 77:
   function checkHash()
   function checkHash()
   {
   {
  global $body;
    global $body;
  $hash=$_GET["hash"];
    $hash=$_GET["hash"];
  $body="";
    $body="";
  $cpt=0;
    $cpt=0;
  $SECRET_NUMBER=123456789;
    $SECRET_NUMBER=123456789;
        $SECRET_STRING="XD4@5#-m";
    $SECRET_STRING="XD4@5#-m";


  foreach ($_POST as $name => $value) {
    foreach ($_POST as $name => $value) {
  if ($cpt++>0) $body.="&";
      if ($cpt++>0) $body.="&";
  $body.=llEscapeURL($name)."=".llEscapeURL($value);
      $body.=llEscapeURL($name)."=".llEscapeURL($value);
  }
    }
  $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
    $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
  if ($hash!=$calcHash)  
    if ($hash!=$calcHash)  
  {
    {
  sleep(2); // slow down the requests
      sleep(2); // slow down the requests
  echo "result=FAIL\nMSG=Invalid hash"; + $body="";  
      echo "result=FAIL\nMSG=Invalid request.";  
  die;
      die;
  }
    }
   }
   }
 
 
 
   checkHash();
   checkHash();
   // You can use the parameters here by simply using $_POST["parameter_name"]  
   // You can use the parameters here by simply using $_POST["parameter_name"]  
   echo "OK";
   echo "OK";
  ?>
?>
</php>
</php>



Revision as of 14:09, 2 July 2008

Second life allow script to make requests to a web site. This now works quite well but scripters need to be careful of potential attacks.

In any scenario, it is safe to check that the request comes from one of your scripts only.

So I made a little function called xrequest, this function will make a request to a PHP page using your own secure SECRET_NUMBER password. The PHP script can check that the password is right before processing the request.

This is simple and uses a good algorithm present in both LSL and PHP.

How to use

The second life script

In the beginning of your script you must copy the xrequest function and also choose a SECRET_NUMBER and a SECRET_STRING. In SL you should also make sure that the script is not visible to other people than yourself (this is the default access right).

<lsl>

integer SECRET_NUMBER=123456789;
integer SECRET_STRING="XD4@5#-m";

xrequest(list l) {

   integer i;
   string body;
   integer len=llGetListLength(l) & 0xFFFE; // make it even
   for (i=0;i<len;i+=2)
   {
       string varname=llList2String(l,i);
       string varvalue=llList2String(l,i + 1);
       if (i>0) body+="&";
       body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
   }
   string hash=llMD5String(body+llEscapeURL(SECRET_STRING),SECRET_NUMBER);
   http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);

} </lsl>

To make a call to the function you have to provide 2 parameters:

For example:

xrequest("http://www.yourserver.com/your_page.php",["parameter1",123,"parameter2","parameter2 value"]);

The first parameter is the address of the webpage which will process your request. I assume, you own a website which supports PHP (about any version).

The second parameter is a list containing the parameters you want to pass to the page. They will be sent to the page as if they had been type in a WebForm. The list can be empty [] or contain any number of 'variable name','variable value' pairs.

The PHP Page

The php page must contains the function below, if you're a PHP wiz, you also include it inside another file.

Note that the page must be modified to contain your own SECRET_NUMBER. Your page will then use the function checkHash() to make sure the correct password was used. If the password is wrong, the page won't run any further.

If the password is right you can then read the content of the parameters using a simple $_POST["parameter_name"]

<php> <?php

 // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
 function llEscapeURL($s)
 {
   $s=str_replace(
     array(" ","+","-",".","_"),
     array("%20","%20","%2D","%2E","%5F"),
     urlencode($s));
   return $s;
 }   
 
 // this my main SL page XML-RPC page
 function checkHash()
 {
   global $body;
   $hash=$_GET["hash"];
   $body="";
   $cpt=0;
   $SECRET_NUMBER=123456789;
   $SECRET_STRING="XD4@5#-m";
   foreach ($_POST as $name => $value) {
     if ($cpt++>0) $body.="&";
     $body.=llEscapeURL($name)."=".llEscapeURL($value);
   }
   $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
   if ($hash!=$calcHash) 
   {
     sleep(2); // slow down the requests
     echo "result=FAIL\nMSG=Invalid request."; 
     die;
   }
 }
 checkHash();
 // You can use the parameters here by simply using $_POST["parameter_name"] 
 echo "OK";

?> </php>

I hope it helps. Don't hesitate to ask any question to Corto Maltese or improve this page.