I'm facing a frustrating problem right now and I can't see any reason why this doesn't work since is pure Unity developer copy paste code.
I can't send data from Unity to website. Every Unity sent parameter is taken as empty.
That's how my [Web.cs] looks like:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Networking;
public class Web : MonoBehaviour
{
public IEnumerator Login(string Username, string Password)
{
Debug.Log(Username);
Debug.Log(Password);
WWWForm Form = new WWWForm();
Form.AddField("loginUser", Username);
Form.AddField("loginPass", Password);
UnityWebRequest www = UnityWebRequest.Post("http://localhost/Login.php", Form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
Debug.Log(www.error);
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.text);
}
}
}
And I'm calling it via Login.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Login : MonoBehaviour
{
public InputField UserName;
public InputField Password;
public Button myButton;
private void Start()
{
myButton.onClick.AddListener(() =>
{
StartCoroutine(Main.Instance.Web.Login(UserName.text, Password.text));
});
}
}
The php code looks like:
<?php
$UserName = $_GET["loginUser"];
$Password = $_GET["loginPass"];
$myfile = fopen("testfile.txt", "a");
fwrite($myfile, "Username: $UserName\nPassowrd: $Password\n\n");
?>
So, when I manually acces the path link, I get the expected results:
http://localhost/Login.php?loginUser=Test&loginPass=Ok
https://i.imgur.com/s0bP5tJ.png
But when I do it with Unity, XAMPP writes the parameters as empty.
A debug photo:
https://i.imgur.com/r1IUTy2.png
It appears you're sending a POST request to a GET request.
Try this: UnityWebRequest.Get(...)
#Kale, thank you, I kinda still don't understand what's the difference between post and get methods :-?
For future searchers, that's how I managed to resolve the issue:
public class Web : MonoBehaviour
{
public IEnumerator Login(string Username, string Password)
{
WWWForm Form = new WWWForm();
string Link = "http://localhost/Login.php?loginUser=" + Username + "&loginPass=" + Password;
UnityWebRequest www = UnityWebRequest.Get(Link);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
Debug.Log(www.error);
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.text);
}
}
}
Related
I want to send data from my game to the Database on the server. In this case, I develop locally but when I click the spacebar button The Database is created but With empty data. No data is sent from my game.
I have to try to improve my code also try to implement the pre statements.
I am not able to use the unitywebrequest because my version of UNITY3D does not have it my version is 5.0.0f4
When I try to insert the data by hand on fields in the editor and then start the preview, and click the spacebar to send the data, but when I click the database create a row but with empty data, what I fail here, can't find the problem
Also, i have aply the debug.log to see if there is any info send from my app to the script and the data is there but i continue not understand why is my code not work correctly, i also provide the prints of the app and database.
I also edit again to make the password hash changes i just did but i dont know if is correct like this
!https://imgur.com/J5R56Xf
!https://imgur.com/pzd7t4e
!https://imgur.com/x9VRK6P
This is my unity code below.
using UnityEngine;
using System.Collections;
public class DataInserter : MonoBehaviour {
public string inputUserName;
public string inputPassword;
public string inputEmail;
public string regdata;
string CreateUserURL = "localhost/InsertUser.php";
// Use this for initialization
void Start () {
//regdata = System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.Space)) CreateUser(inputUserName, inputPassword, inputEmail, regdata);
}
public void CreateUser(string username, string password, string email, string regdata){
WWWForm form = new WWWForm();
form.AddField("usernamePost", username);
form.AddField("passwordPost", password);
form.AddField("emailPost", email);
form.AddField("regdataPost", regdata);
WWW www = new WWW(CreateUserURL, form);
}
}
And This is my New PHP code below.
//Variables for the connection
$servername = "localhost";
$server_username = "root";
$server_password = "mysql";
$dbName = "wizard2019";
$saveuser = "INSERT INTO users (username, email, password, regdata)
VALUES ('".$username."','".$email."','".$password."','".$regdata."')";
//Variable from the user
$username = $_POST["usernamePost"];
$email = $_POST["emailPost"];
$password = password_hash($_POST["passwordPost"], PASSWORD_DEFAULT);
$regdata = $_POST["regdataPost"];
//$username = "helder";
//$email = "test email";
//$password = "123456";
//$regdata = "20201123";
//Make Connection
$conn = new mysqli($servername, $server_username, $server_password, $dbName);
//Check Connection
if(!$conn){
die("Connection Failed. ". mysqli_connect_error());
}
$sql = $saveuser;
$result = mysqli_query($conn ,$sql);
if(!$result) echo "there was an error";
else echo "Registration Sucessfull";
?>
First of all WWW class has been obsolete. Look at this docs of unity here.
Also you need to use 'Coroutine' to wait until you get a response from WWW. See the code below:
void Start () {
string url = "http://www.example.com/";
WWW www = new WWW(url);
StartCoroutine(WaitForRequest(www));
}
IEnumerator WaitForRequest(WWW www)
{
yield return www;
// check for errors
if (www.error == null)
{
Debug.Log("Success: " + www.data);
} else {
Debug.Log("WWW Error: "+ www.error);
}
}
Check this amazing tutorial of Unity with PHP MySQLi here if you really want to stick with your approach.
I recommend you to use UnityWebRequest to POST or GET data. See this official docs here.
For Example:**
IEnumerator Upload()
{
WWWForm form = new WWWForm();
form.AddField("myField", "myData");
using (UnityWebRequest www = UnityWebRequest.Post("http://www.my-server.com/myform", form))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
}
For about a month, I have been trying to figure out why my code will not return anything after posting a wwwForm (I have also tried the newer equivalent of this function but I had no luck with that either.) The nameField and passwordField are taken from text boxes within the game and the code used in my login script is copied and pasted from a Register script but I have changed the file location to the login.php file. The register script works fine and I can add new users to my database but the login script only outputs "Form Sent." and not the "present" that should return when the form is returned and it never gets any further than that point meaning that it lets the user through with no consequence if they use an invalid name because the script never returns an answer. What should I do to fix this?
Thanks,
Unity Code:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
public class Login : MonoBehaviour
{
public InputField nameField;
public InputField passwordField;
public Button acceptSubmissionButton;
public void CallLogInCoroutine()
{
StartCoroutine(LogIn());
}
IEnumerator LogIn()
{
WWWForm form = new WWWForm();
form.AddField("username", nameField.text);
form.AddField("password", passwordField.text);
WWW www = new WWW("http://localhost/sqlconnect/login.php", form);
Debug.Log("Form Sent.");
yield return www;
Debug.Log("Present");
if (www.text[0] == '0')
{
Debug.Log("Present2");
DatabaseManager.username = nameField.text;
DatabaseManager.score = int.Parse(www.text.Split('\t')[1]);
Debug.Log("Log In Success.");
}
else
{
Debug.Log("User Login Failed. Error #" + www.text);
}
}
public void Validation()
{
acceptSubmissionButton.interactable = nameField.text.Length >= 7 && passwordField.text.Length >= 8;
}
}
login.php:
<?php
echo "Test String2";
$con = mysqli_connect('localhost', 'root', 'root', 'computer science coursework');
// check for successful connection.
if (mysqli_connect_errno())
{
echo "1: Connection failed"; // Error code #1 - connection failed.
exit();
}
$username = mysqli_escape_string($con, $_POST["username"]);
$usernameClean = filter_var($username, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
$password = $_POST["password"];
if($username != $usernameClean)
{
echo "7: Illegal Username, Potential SQL Injection Query. Access Denied.";
exit();
}
// check for if the name already exists.
$namecheckquery = "SELECT username, salt, hash, score FROM players WHERE username='" . $usernameClean . "';";
$namecheck = mysqli_query($con, $namecheckquery) or die("2: Name check query failed"); // Error code # 2 - name check query failed.
if (mysqli_num_rows($namecheck) != 1)
{
echo "5: No User With Your Log In Details Were Found Or More Than One User With Your Log In Details Were Found"; // Error code #5 - other than 1 user found with login details
exit();
}
// get login info from query
$existinginfo = mysqli_fetch_assoc($namecheck);
$salt = $existinginfo["salt"];
$hash = $existinginfo["hash"];
$loginhash = crypt($password, $salt);
if ($hash != $loginhash)
{
echo "6: Incorrect Password"; // error code #6 - password does not hash to match table
exit;
}
echo "Test String2";
echo"0\t" . $existinginfo["score"];
?>
This problem was solved by changing the IENumerator LogIn() to IENumerator Start(). The program ran correctly when it was started at the beginning of a scene but not when it was triggered by a button being pressed. Weirdly, the Register() function in another script (which shares a lot of its code with this one) ran fine when triggered from a button. I'm not sure why this is.
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
public class Login : MonoBehaviour
{
public InputField nameField;
public InputField passwordField;
public Button acceptSubmissionButton;
IEnumerator Start()
{
WWWForm form = new WWWForm();
form.AddField("username", nameField.text);
form.AddField("password", passwordField.text);
WWW www = new WWW("http://localhost/sqlconnect/login.php", form);
Debug.Log("Form Sent.");
yield return www;
Debug.Log("Present");
if (www.text[0] == '0')
{
Debug.Log("Present2");
DatabaseManager.username = nameField.text;
DatabaseManager.score = int.Parse(www.text.Split('\t')[1]);
Debug.Log("Log In Success.");
}
else
{
Debug.Log("User Login Failed. Error #" + www.text);
}
}
public void Validation()
{
acceptSubmissionButton.interactable = nameField.text.Length >= 7 && passwordField.text.Length >= 8;
}
}
It seems that I am having trouble running an SQL query on the server via PHP on Input change. Could someone please take a look on my code and assist me?
The service that is responsible for handling the http request to the server:
import { Injectable } from '#angular/core';
import { HttpClient } from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class CrudService {
public url = 'http://localhost/web_api/';
constructor(private http: HttpClient) { }
registerNormal(data)
{
return this.http.post(this.url + 'registerNormal.php', data);
}
accountExists(data)
{
return this.http.get(this.url + 'existingAccounts.php', data);
}
}
The function responsible for passing the data
CheckAccountAvailability(values)
{
const registerNormalFormData = new FormData();
registerNormalFormData.append('username', values.username);
if (this.registerNormal.get('username').valid)
this.crudService.accountExists(registerNormalFormData).subscribe(result => {console.log(result)});
}
The PHP file works fine since I have tested it with postman and also the registerNormal() function works perfectly fine.
I don't seem to pinpoint the issue exactly.
Many thanks!
EDIT:
Below is the html code for the component that calls the function. The function gets called but the result returned by angular is NULL however the PHP API returns the result fine with postman
<input matInput placeholder="User Name" formControlName="username" required (input)="CheckAccountAvailability(registerNormal.value)">
EDIT 2:
Below is the php code for existingAccounts.php
<?php
if ($_GET)
{
// include database connection
include 'config/database.php';
try
{
// check if account exists in database
$q_normalAccountExists = "SELECT * FROM normal_accounts WHERE username=:username";
// $q_bandAccountExists = "SELECT * FROM band_accounts WHERE username=:username";
// prepare queries to check if accounts exist in database
$checkNormalAccount = $con->prepare($q_normalAccountExists);
// $checkBandAccount = $con->prepare($q_bandAccountExists);
// GET username
$username = $_GET['username'];
// bind parameters to check if username exists in database
$checkNormalAccount->bindParam(':username', $username);
// $checkBandAccount->bindParam(':username', $username);
// execute username exists in database query
$checkNormalAccount->execute();
// $checkBandAccount->execute();
if ($checkNormalAccount->rowCount() == 0/* && $checkBandAccount->rowCount() == 0*/)
{
echo json_encode(array('result'=>false));
}
else
{
echo json_encode(array('result'=>true));
}
}
// show error
catch(PDOException $exception)
{
die('ERROR: ' . $exception->getMessage());
}
}
?>
EDIT 3:
It seems that changing the GET request to a POST request sorted the issue. However, could anyone tell me why GET requests won't work?
I am creating a form login with ExtJS, and sending JSON data to do authentification within Zend Framework. The problem is, no matter what username and password I fill, login always succeed. Here's the related code :
Submit Function for Ext JS Form, where we send JSON data contained username and password.
var doLogin = function () {
if (formPanel.getForm().isValid()) {
formPanel.getForm().submit({
method: 'POST',
url: '/zend/public/auth/valid',
waitMsg: 'Processing Request',
success: function (form, action) {
document.location = '/zend/public/guestbook';
},
failure: function (form, action) {
if (action.failureType = 'server') {
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Login Failed', obj.errors.reason);
} else {
Ext.Msg.alert('Warning!', 'Authentification server is uneachable : ' + action.response.responseText);
}
formPanel.getForm().reset
}
})
}
}
The Controller, we have ValidAction function to receive and send JSON data, and process to do the authentification.
public function validAction()
{
if(!isset($this->session->isLogin)){
$username = mysql_escape_string($_POST['username']);
$password = mysql_escape_string($_POST['password']);
$formdata = array('username'=>$username, 'password'=>$password);
if ($this->_process($formdata)) {
$this->session->setExpirationSeconds(3600);
$msg = '{success:true, result:{message:\'Welcome, '.$username.'!\'}}';
} else {
$msg = '{success:false, errors:{reason:\'Login failed, try again.\'}}';
}
}
protected function _process($values) {
// Get our authentication adapter and check credentials
$adapter = $this->_getAuthAdapter();
$adapter->setIdentity($values['username']);
$adapter->setCredential($values['password']);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
$user = $adapter->getResultRowObject();
$auth->getStorage()->write($user);
return true;
}
return false;
}
The problem lies in validAction, and weirdly I do var_dump to $this->process($formdata) and returns false, yet it always go to if function, message Success. Any ideas? Appreciated fellas.
UPDATE :
The var_dump :
Uncaught Error: You're trying to decode an invalid JSON String:
array(2) {
["username"]=>
string(2) "ad"
["password"]=>
string(4) "pass"
}
bool(false)
string(59) "{success:false, errors:{reason:'Login failed, try again.'}}"
Backend problem
You are outputting invalid JSON.
PHP provides json_encode to save you having to manually create json:
$response=array();
$response['success']=false;
$response['result']=array();
$response['message']='Welcome '.$username;
$msg = json_encode($response);
If you really don't want to use this you should add double quotes to your keys, and change to double quotes for your string properties too:
$msg = '{"success":true, "result":{"message":"Welcome, '.$username.'!"}}';
Front end problem
You are using success and failure methods, but I can't see anything in your back end code to send status headers.
The failure method will only get called when a response returns with a non 200 status code. So you may need to either add this to your back end code, and/or also decode the response inside your success method to make sure that you have sent success:true as part of your json before redirecting.
To send the header in PHP 5.4 or newer:
http_response_code(401);
in 5.3 or older you have to use header method instead - but if you are running this version you should upgrade immediately so I wont include an example.
I have a GWT app with inputs (let's say Name, Address, Email). After user input all the required fields and press submit button, a PHP page will display the inputs from the GWT app. How can I connect my GWT app to php? I'm using Request Builder now. Do I still have to use XML to pass the GWT inputs to PHP? Please help. I'm just starting to learn GWT here.
Thanks in advance.
You actually don't need RequestBuilder for something like that.
It would be sufficient if you redirect to the PHP url and append your inputs as GET parameters.
So for example in the click handler you can do something like that:
submitButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
String linkURL = "somePage.php?name="+name+"&address="+address+"&email="+email;
Window.Location.assign(linkURL);
}
});
and then in the PHP page you can retrieve the parameters in this way:
$name = $_GET['name'];
$address = $_GET['address'];
$email = $_GET['email'];
Update
If you want to use RequetBuilder you have to do something like that:
submitButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
RequestBuilder request = new RequestBuilder(POST,PHP_URL);
JSONObject jsonValue = new JSONObject();
jsonValue.put("name", new JSONString(name));
jsonValue.put("address", new JSONString(address));
jsonValue.put("email", new JSONString(email));
request.setHeader("Content-Type", "application/json");
request.sendRequest(jsonValue.toString(),new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
//retrieve a uniqueid or so and redirect to the PHP page which displays the infos
} else {
// displayError("Couldn't retrieve
}
}
#Override
public void onError(Request request, Throwable exception) {
//displayError("Couldn't retrieve JSON");
}
});
}
});
On the server you just access the global $_POST variable to get the values:
$name = #_POST['name']