Uploading file over https with cordova filetransfer - php

I've got a problem with the file transfer plugin that i can't seem to figure out. My code works when i'm using http, but when I try to upload over https it seems that it doesn't send the parameters to my api but it does reach my api. only the the file is missing, the x-session-token header is present and valid. This is the code i use for uploading the file:
$scope.options = {};
$scope.options.fileKey = "file";
$scope.options.fileName = $scope.img.substr($scope.img.lastIndexOf('/') + 1);
$scope.options.mimeType = "image/jpeg";
$scope.options.headers = {
'x-session-token' : window.localStorage.auth
};
// parameters: source, filePath, options
$cordovaFile.uploadFile("https:/****/api.php/profielpic/", $scope.img, $scope.options, true).then(function(result) {
console.log(result);
$cordovaToast.showShortTop('Uploaden gelukt!').then(function(success) {
$ionicLoading.hide();
$state.go('tab.profiel');
}, function (error) {
$ionicLoading.hide();
$state.go('tab.profiel');
});
}, function(err) {
console.log(err);
$ionicLoading.hide();
});
This is the code i use Server side to see if there's anything:
$app->post('/profielpic/', function () use ($app) {
$auth = new api\src\Auth;
$users = new api\src\Users;
$authdata = json_decode($app->request->headers->get('x-session-token'));
$data = json_decode($app->request->getBody());
$userid = $authdata->userID ;
$session_token = $authdata->session_token;
$userdata = $data->userdata;
$alertsarray = array();
$message = null;
$isValid = true;
$authresult = $auth->authenticate($userid, $session_token);
$imgname = time();
print_r(json_encode($authdata));
print_r(json_encode($_FILES));
print_r(json_encode($_POST));
print_r(json_encode($data));
print_r(json_encode(file_get_contents("php://input")));
/*
if($authresult === true) {
$res = $users->updateUserPicture($userid, $_FILES['file']);
if($res === false) {
$isValid = false;
$message = "Er ging iets mis.";
}else{
$message = $res;
}
}else {
$isValid = true;
$message = $authresult;
}*/
$dataArray = array(
'isValid' => $isValid,
'message' => $message
);
echo ")]}',\n".json_encode($dataArray);
});
but everything is empty with https:// if i upload to http:// it works
Does anyone know why http works but https isn't working? the only case where https isn't working is with file uploads. the rest of my api routes work with https.
It happens on iOS devices and Android devices so the problem is more likely to be with the slim api i'd guess
Api response:
{
"bytesSent": 32889,
"responseCode": 200,
"response": "{\"userID\":\"2\",\"session_token\":\"****"
} {\
"file\":{\"name\":\"modified.jpg?1427448587960\",\"type\":\"image\\/jpeg\",\"tmp_name\":\"\\/tmp\\/phpABKyF2\",\"error\":0,\"size\":37491}}[]null\"\")]}',\n{\"isValid\":true,\"message\":null}",
"objectId": ""
}

Make sure you are using a valid SSL certificate. If your app is reaching the API but not sending the data, its likely that your app has realised the connection is unsafe. It will only send data once it establishes a secure connection to a server it can trust.
A self signed certificate will not be trusted.

Related

how to submit input data along with ng2 file upload angular ionic

Please I want to send some text data with file upload(ng2 file upload) in angular ionic. I am new to angular and ionic as well. I have tried so many options but I don't seem to get a way out. I am using Php as a backend.I am able to send the file only but not the input data like username. Meanwhile I am able to log the input data that's username on the console but the server response is null. And it never inserts in my database. This is my code.
public fileUploader: FileUploader = new FileUploader({});
ngOnInit() {
this.fileUploader = new FileUploader({ url: "http://localhost/paat/server/post.php"});
this.fileUploader.onBuildItemForm = (fileItem: any, form: FormData): any => {
form.append('body', this.body);
form.append('username', this.username);
// Add file to upload
form.append('file', fileItem);
fileItem.withCredentials = false;
return { fileItem, form };
};
}
fileOverBase(event): void {
this.hasBaseDropZoneOver = event;
}
//return files from ng2 upload
getFiles(): FileLikeObject[] {
return this.fileUploader.queue.map((fileItem) => {
return fileItem.file;
});
}
// the upload method where the post to server is made
uploadFiles() {
let bodys = {
body:this.body,
username:this.username,
};
let files = this.getFiles();
let requests = [];
files.forEach((file) => {
let formData = new FormData();
formData.append('file' , file.rawFile, file.name);
formData.append('body' , this.body);
formData.append('username' , this.username);
requests.push(this.uploadingService.uploadFormData(formData));
});
concat(...requests).subscribe(
(res) => {
console.log(res);
console.log(this.body);
console.log(this.username);
console.log(this.file.name);
},
(err) => {
console.log(err);
}
);
}
this is my uploadservice.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class UploadingService {
API_SERVER: string = "http://localhost/paat/server/post.php";
constructor(private http: HttpClient) { }
public uploadFormData(formData) {
return this.http.post<any>(`${this.API_SERVER}`, formData);
}
}
This is my backend code:
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods:POST,GET,PUT,DELETE");
header("Access-Control-Max-Age:86400");
header("Access-Control-Allow-Headers: Content-Type,Access-Control-Allow-Headers,Authorization,X-Requested-With");
$con = mysqli_connect("localhost", "root", "", "social");
$postjson = json_decode(file_get_contents('php://input'), true);
$filename = $_FILES['file']['name'];
$meta = $_POST;
$targetDir = "assets/images/posts/";
$destination = $targetDir . $filename;
move_uploaded_file( $_FILES['file']['tmp_name'] , $destination );
$body = $postjson['body'];
$date_added = date("Y-m-d H:i:s");
//get username
$added_by = $postjson['username'];
//if user is on own profile, user_to is 'none'
$targetfile = $destination;
$user_to ="none";
$query = mysqli_query($con,"INSERT INTO posts VALUES(NULL, '$body', '$added_by', '$user_to', '$date_added', 'no', 'no', '0', '$targetfile')");
What am I doing wrong? Please help.
I have found out what I was doing wrong. The problem was with my backend code. It was the way I was retrieving the formdata values from the request. So I changed
$body = $postjson['body'];
$added_by = $postjson['username'];
to
$body = $_POST['body'];
$added_by = $_POST['username'];
Also I modified my ngOnInit() method and the instance of fileuploader method to
public fileUploader: FileUploader = new FileUploader({ url: "http://localhost/paat/server/post.php"});
ngOnInit() {
this.fileUploader.onBuildItemForm = (fileItem: any, form: FormData): any => {
form.append('body', this.body);
// Add file to upload
form.append('file', fileItem);
form.append('username', this.username);
fileItem.withCredentials = false;
return { fileItem, form };
};
}
and it now works.

Http failure during parsing for - angular http post to php

I am able to consume the php endpoint from postman. I try to do the same from angular post, I get this error - Http failure during parsing for. Even though everything looks perfect to me, the problem is surprising. Here is my snippet
php file
<?php
header('Access-Control-Allow-Origin: *');
// check for post
if ($_SERVER['REQUEST_METHOD']=='POST') {
$name = $_POST['name'];
$email = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];
// include db connect class
require_once __DIR__ . '/db_connect.php';
// connecting to db
$conn = new db_CONNECT();
$cone=$conn->con;
//escpae the strings to be inserted to DB
$escapedname = mysqli_real_escape_string($cone, $name);
$escapedemail = mysqli_real_escape_string($cone, $email);
$escapedsubject= mysqli_real_escape_string($cone, $subject);
$escapedmessage = mysqli_real_escape_string($cone, $message);
// mysql inserting a new row
$sql = "INSERT INTO contacts(name, email, subject, message) VALUES ('$escapedname', '$escapedemail', '$escapedsubject', '$escapedmessage')";
// $result= $cone -> query($sql);
// $affected = $cone -> affected_rows;
if (mysqli_query($cone,$sql)) {
echo "Information saved successfully.";
} else {
echo "Not successful";
}
} else {
echo "Some field missing.";
}
?>
here is the angular snippet
saveContactDetails = function () {
this.proceed = true;
this.success = false;
const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
data.append('name', this.contactDeJson.name);
data.append('email', this.contactDeJson.email);
data.append('subject', this.contactDeJson.subject);
data.append('message', this.contactDeJson.message);
this.http
.post('http://localhost:80/'+'api/create_contact.php', data.toString(), {headers: myheader})
Please why am I getting this error
{"headers":{"normalizedNames":{},"lazyUpdate":null},"status":200,"statusText":"OK","url":"http://localhost/api/create_contact.php","ok":false,"name":"HttpErrorResponse","message":"Http failure during parsing for http://localhost/api/create_contact.php",
I believe the issue is that your angular script is expecting a json response (the default responseType), but not receiving the correct headers or data. In stead of just echoing out your result in php, I would make a function that can handle sending the response. Something like this:
function sendJsonResponse(data, status = 200) {
header('Content-Type: application/json', true, status);
echo json_encode($data);
exit();
}
In stead of of doing this:
echo "Not successful";
You can now do this:
sendJsonResponse("Not successful", 500);
This should give you more valuable information in the frontend. And the response should now be formatted correctly, and no longer produce the parse error in angular that you are getting now.
I believe you are trying to send some query parameters using data variable. You could actually send a JS object as the parameters. Try the following
private saveContactDetails() {
this.proceed = true;
this.success = false;
const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
const data = {
'name': this.contactDeJson.name,
'email': this.contactDeJson.email,
'subject': this.contactDeJson.subject,
'message': this.contactDeJson.message
}
this.http.post('http://localhost:80/'+'api/create_contact.php', { params: data }, { headers: myheader })
}

Webhook always failed authentication in Authorize.Net

In Authorize.Net created the subscription and recurring events handling using webhook. When I test using the web hook account authentication works but in actual webhook notification always failed authentication
if (isset($this->header['x-anet-signature'])) {
$json = Json::encode($this->body);
if ($json) {
//To check the header and signature is true
if (hash_equals(strtolower($this->header['x-anet-signature']),
'sha512=' . hash_hmac('sha512',$json, $secret))
) {
}else{
yii::info($json,'webhookhNotifications');
throw new \yii\web\ServerErrorHttpException('Authentication failed in Webhook');
return false;
}
}
}
Webhook JSON
{
"notificationId":"4bbba8fb-1d32-46b6-a513-a9ca2fed885c",
"eventType":"net.authorize.customer.subscription.created",
"eventDate":"2019-11-27T06:20:36.3621687Z",
"webhookId":"a2929d59-147e-4400-a2bb-b3bd25a0311d",
"payload":{
"name":"Test subscription",
"amount":290.00,
"status":"active",
"profile":{
"customerProfileId":1921894828,
"customerPaymentProfileId":1834842681,
"customerShippingAddressId":1879009509
},
"entityName":"subscription",
"id":"6168233"
}
}
Secret key
F7B582AFFA9372866965456CFAC0D1B1219258F955FD5266D1A96BF9BE3C85F7D54C7CDFF9EF3EE7D3916EACB5EE920167F557BBB307288C17FBD169F0257AB4
x-anet-signature
sha512=FDE5518801C115C4886311877B4C37F6C26ABACE01ADB973EF372FB51C8F1E5321A83717161AD7DEFFD46F5013900E68B6220F3B25E9302A4208A9C673D32749
Your code should work. I simplified it a bit for testing purposes but using the values you provided above it does indeed validate successfully:
$signature = 'sha512=FDE5518801C115C4886311877B4C37F6C26ABACE01ADB973EF372FB51C8F1E5321A83717161AD7DEFFD46F5013900E68B6220F3B25E9302A4208A9C673D32749';
$json = '{"notificationId":"4bbba8fb-1d32-46b6-a513-a9ca2fed885c","eventType":"net.authorize.customer.subscription.created","eventDate":"2019-11-27T06:20:36.3621687Z","webhookId":"a2929d59-147e-4400-a2bb-b3bd25a0311d","payload":{"name":"Test subscription","amount":290.00,"status":"active","profile":{"customerProfileId":1921894828,"customerPaymentProfileId":1834842681,"customerShippingAddressId":1879009509},"entityName":"subscription","id":"6168233"}}';
$secret = 'F7B582AFFA9372866965456CFAC0D1B1219258F955FD5266D1A96BF9BE3C85F7D54C7CDFF9EF3EE7D3916EACB5EE920167F557BBB307288C17FBD169F0257AB4';
if (hash_equals(strtolower($signature), 'sha512=' . hash_hmac('sha512', $json, $secret))) {
echo 'valid';
}else{
echo 'invalid';
}
Demo
I think your error is you are encoding the JSON which is already JSON. So change this line:
$json = Json::encode($this->body);
new code:
if (isset($this->header['x-anet-signature'])) {
$json = $this->body;
if ($json) {
//To check the header and signature is true
if (hash_equals(strtolower($this->header['x-anet-signature']),
'sha512=' . hash_hmac('sha512',$json, $secret))
) {
}else{
yii::info($json,'webhookhNotifications');
throw new \yii\web\ServerErrorHttpException('Authentication failed in Webhook');
return false;
}
}
}

Slim v2 to Slim v3 Upgrade

I have been using Slim v2 for my APIs and am thinking about upgrading to v3.
Unfortunately I have limited experience and could use your help on a code example below.
This is the login code:
$app->post('/register', function() use ($app) {
// check for required params
verifyRequiredParams(array('name', 'email', 'password'));
$response = array();
// reading post params
$name = $app->request->post('name');
$email = $app->request->post('email');
$password = $app->request->post('password');
// validating email address
validateEmail($email);
$db = new DbHandler();
$res = $db->createUser($name, $email, $password);
if ($res == USER_CREATED_SUCCESSFULLY) {
$response["error"] = false;
$response["message"] = "You are successfully registered";
} else if ($res == USER_CREATE_FAILED) {
$response["error"] = true;
$response["message"] = "Oops! An error occurred while registereing";
} else if ($res == USER_ALREADY_EXISTED) {
$response["error"] = true;
$response["message"] = "Sorry, this email already existed";
}
// echo json response
echoRespnse(201, $response);
});
Here is the validateEmail function:
function validateEmail($email) {
$app = \Slim\Slim::getInstance();
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response["error"] = true;
$response["message"] = 'Email address is not valid';
echoRespnse(400, $response);
$app->stop();
}
}
How do I get an Instance of app in Slim v3 to actually stop the app when input criteria are not met?
I would appreciate it if you could give me an example with the help of my code.
Thanks for the help!
EDIT
The above issue was solved. Unfortunately, a new issue arose after checking my code.
I have a middle layer to authenticate the user:
function authenticate(\Slim\Route $route) {
// Getting request headers
$headers = apache_request_headers();
$response = array();
$app = \Slim\Slim::getInstance();
// Verifying Authorization Header
if (isset($headers['Authorization'])) {
//omitted code
} else {
// api key is missing in header
$response["error"] = true;
$response["message"] = "Api key is misssing";
echoRespnse(400, $response);
$app->stop();
}
In my main code i implement function authenticate as follows:
$app->get('/tasks', 'authenticate', function() {
global $user_id;
$response = array();
$db = new DbHandler();
//ommit some code
echoRespnse(200, $response);
});
Would you know how to do this in Slim v3?
I would really appreciate your help.
In Slim3, return $response (return Response object) is a better way to stop app.
So how is the below?
$app->post('/register', function($request, $response, $args) {
// omit some codes
if(!validateEmail($request->getParsedBodyParam('email'))){
return $response->withJson(['message' => 'Email address is not valid', 'error' => true], 400);
}
// omit some codes
}
validateEmail function is changed to like below.
function validateEmail($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return false
}
return true;
}
Hope it will help you.

sometimes php cURL can't connect to Node js server, returns http code 0

[Context]
This is Node js code from my local machine, works fine on live with changed host name. I use forever to execute it. Also php code which connects to node js server for http response. The above combinations works fine largely on production.
Problem: Once in 3-4 days, node js connectivity fails which results in down time for my application. It returns http code 0. Since I am using forever, it automatically connects back after 5-7 minutes but it is visibly painful during this interval. Specially on production. Can anybody suggest me potential area to debug or any working solution?
[Context]
var config = require('./config.js'),
http = require('http'),
redis = require('redis'),
redisClient = redis.createClient(config.redis.port,config.redis.host),
url = require('url'),
crypto = require('crypto');
var app = http.createServer(function (req, res) {
if(req.method == "OPTIONS"){
res.header('Access-Control-Allow-Origin', '*:*');
res.send(200);
} else {
var u = url.parse(req.url,true),
body = '';
req.on('data',function(chunk) {
body += chunk;
});
req.on('end',function() {
if(body) {
var data =JSON.parse(body);
if(data.__app_secret__ && data.__app_secret__ == '12345') {
switch(u.pathname) {
case '/generateusersecret' :
redisClient.get(req.headers.host + '_' + data.user_id,function(err,reply) {
if(reply) {
jsonResponse(res,{userSecret : reply});
} else {
genToken(req.headers.host + '_' + data.user_id,res);
}
});
break;
case '/getusersecret' :
redisClient.get(req.headers.host + '_' + data.user_id,function(err,reply) {
jsonResponse(res,{userSecret : reply});
});
break;
case '/publish':
redisClient.publish(data.channel,data.message);
jsonResponse(res,{});
break;
default :
jsonResponse(res,{error : "Unknown Command: " + u.pathname});
break
}
} else {
res.writeHead(403, {'Content-Type': 'text/plain'});
res.end('Not authorized');
}
}
});
}
});
//app.listen(config.port || 4000, "127.0.0.1");
app.listen(6006, 'myproductionurl.com');`enter code here`
console.log('Server running at http://myproductionurl.com:6006/');
var io = require('socket.io').listen(app,{
'origins' : "*:*"
}),
sockets = {};
/*
var io = require('socket.io').listen(6006);
var sockets = {};
*/
io.configure(function() {
// set authorization
io.set('authorization',function(handshakeData,callback) {
if(handshakeData.query.secret) {
// when the user's secret is in redis then we trust him as an authenticated user
if(redisClient.get(handshakeData.query.secret)) {
callback(null,true);
} else {
// unauthenticated user
callback(null,false);
}
} else {
// no secret were given
callback('Bad URL');
}
});
});
// #TODO: create separeta namespaces as: /notificaions, /chat etc...
io.sockets.on('connection',function(socket) {
var secret = socket.manager.handshaken[socket.id].query.secret,
_redisClient = redis.createClient(config.redis.port,config.redis.host);
// when the redis client gets a message from the subscribed channels, we are sending back to the user's browser via socket.io
_redisClient.on('message',function(channel,message) {
socket.emit('notification',JSON.parse(message));
});
// subscribe to the user's own channel
_redisClient.subscribe(secret);
// subscribe to the broadcast channel
_redisClient.subscribe('broadcast');
// TODO: subscribe to group channels (a.k.a rooms)
});
function jsonResponse(res,obj) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(obj));
}
function genToken(prefix,res) {
crypto.randomBytes(48,function(ex,buf) {
var token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
redisClient.get(token,function(err,reply) {
if(reply) {
genToken(prefix,res);
} else {
redisClient.set(prefix,token);
jsonResponse(res,{userSecret : token});
}
});
});
}
private function api($url,$data) {
$ch = curl_init();
$data['__app_secret__'] = $this->appSecret;
curl_setopt($ch,CURLOPT_URL, $this->apiUrl.$url);
curl_setopt($ch,CURLOPT_POSTFIELDS, CJSON::encode($data));
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$responseHttpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($responseHttpCode == 403) {
throw new CException('Your app secret is not valid');
} elseif($responseHttpCode == 200) {
// nop
} else {
throw new CException('Uknown Error: ' . $responseHttpCode );
}
//close connection
curl_close($ch);
return CJSON::decode($response);
}

Categories