JSON response string ends with "null" - php

In both Postman and jQuery, I'm getting responses in the form
{"key1": "value1", "key2": "value2"}null
That trailing null is messing with anything that tries to parse it client-side and I can't figure out where it's coming from. If I error_log the encoded JSON before echoing it, there's no trailing null, so I assume that it's a string terminator, but I didn't think that PHP used null-terminated strings. How do I get rid of these nulls?
The object being encoded and returned:
public function jsonSerialize()
{
return [
'internal_id' => $this->internal_id, //int
'friendly_name' => $this->friendly_name, //string
'external_id' => $this->external_id, //string
'picture' => $this->picture //string
];
}
The actual return statement is just echo(json_encode($retval));

Once a PHP file has executed, you have to exit manually or return instead of echoing, otherwise it'll return NULL implicitly and mess everything up. Lesson learned.

Not the most elegant probably... but this SAVED me:
function removeTrailingNulls(__str){
var sanitized = __str;
var lastCharIndex = sanitized.length - 1;
var lastChar = sanitized[lastCharIndex];
var lastCharCode = lastChar.charCodeAt(0);
var isWeirdNullSpace = lastCharCode === 0;
console.log('checking last char (' + lastChar + ') code: ' + lastCharCode + '...null space end?' + isWeirdNullSpace);
var loopCount = 0;
while(isWeirdNullSpace){
sanitized = sanitized.substring(0, sanitized.length-1);
lastChar = sanitized[sanitized.length-1];
lastCharCode = lastChar.charCodeAt(0);
isWeirdNullSpace = lastCharCode === 0;
loopCount++;
if(loopCount>100) break; // prevent infinite loops just in case.
}
return String(sanitized);
}

Related

Kotlin(Android) MD5 checking with PHP Signature

I been working on this for days.
Our backend have a signature checking which is done using PHP:
private $HMAC_ALGO = 'md5';
public function decodeAndValidateMessage($data,$signature,$secretkey) {
if (!is_string($data)) {
throw new InvalidRequestException($data);
}
$decodedData = base64_decode($data);
// if not json returned the throw exception...
$jsonDecoded = json_decode($decodedData,true);
if (!$jsonDecoded) {
throw new InvalidRequestException($decodedData);
}
// validate
$signatureRef = base64_encode(hash_hmac($this->HMAC_ALGO,$decodedData,$secretkey,true));
if ($signature === $signatureRef) {
return $jsonDecoded;
} else {
throw new InvalidSignatureException();
}
}
I made it work on iOS:
func hmac(_ algorithm: HMACAlgorithm, key: String) -> String {
let cKey = key.cString(using: String.Encoding.utf8)
let cData = self.cString(using: String.Encoding.utf8)
var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength()))
CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result)
let hmacData:Data = Data(bytes: UnsafePointer<UInt8>(result), count: (Int(algorithm.digestLength())))
let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(String(hmacBase64))
return String(hmacBase64)
}
Any idea/help on doing this on Kotlin/Android? I'm being stuck on InvalidSignatureException error.
fun generateSignature(data : HashMap<String, Any>) : String {
val hmac = Mac.getInstance("HmacMD5")
hmac.init(SecretKeySpec(Constant.PRIVATEKEY.toByteArray(Charsets.UTF_8), hmac.algorithm))
return Base64.encodeToString(data.toString().toByteArray(),Base64.URL_SAFE + Base64.NO_PADDING + Base64.NO_CLOSE + Base64.NO_WRAP)
}
Thanks :D I really appreciate for any help :D
Update:
Just to make my question simpler?
Is it possible to make translate the iOS line of code to Kotlin?
enum HMACAlgorithm {
case md5, sha1, sha224, sha256, sha384, sha512
func toCCHmacAlgorithm() -> CCHmacAlgorithm {
var result: Int = 0
switch self {
case .md5:
result = kCCHmacAlgMD5
case .sha1:
result = kCCHmacAlgSHA1
case .sha224:
result = kCCHmacAlgSHA224
case .sha256:
result = kCCHmacAlgSHA256
case .sha384:
result = kCCHmacAlgSHA384
case .sha512:
result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}
func digestLength() -> Int {
var result: CInt = 0
switch self {
case .md5:
result = CC_MD5_DIGEST_LENGTH
case .sha1:
result = CC_SHA1_DIGEST_LENGTH
case .sha224:
result = CC_SHA224_DIGEST_LENGTH
case .sha256:
result = CC_SHA256_DIGEST_LENGTH
case .sha384:
result = CC_SHA384_DIGEST_LENGTH
case .sha512:
result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
this is how I call the function
var params : Dictionary
params.generateSignature()
fun generateSignature(data : HashMap) : String {
val hmac = Mac.getInstance("HmacMD5")
hmac.init(SecretKeySpec(Constant.PRIVATEKEY.toByteArray(Charsets.UTF_8), hmac.algorithm))
return Base64.encodeToString(data.toString().toByteArray(),Base64.URL_SAFE + Base64.NO_PADDING + Base64.NO_CLOSE + Base64.NO_WRAP)
}
Someone finally found out the answer.
My mistake is hashmap should be run under JSONObject
var obj = JsonObject(data)
and use obj.toString() :D

convert doctrine resultset to json from findby query using zend json

I've seend much assistance for everything BUT transforming data when using the findBy query.
What I want is a json string of the resulset from this query ensuring that the objects are serialized so i can use this somewhere else:
$posts = $entityManager->getRepository(\Application\Entity\Post::class)
->findBy(['status'=>\Application\Entity\Post::STATUS_PUBLISHED],
['dateCreated'=>'DESC']);
Json::encode($posts,true) from Zend Framework Json but the data is not showing up when i do this.
The result will be a json encoded string with the entity objects that i can pass somewhere else
I will use for the decoding:
\Zend\Json\Decoder::decode($posts,\Zend\Json\Json::TYPE_OBJECT)
UNLESS I should be using \Zend\Json\Json::TYPE_ARRAY)
Here is the way I do it :
include : use Zend\Json\Json;
here is my example of function / action :
public function getListAction(){
$request = $this->getRequest();
if($request->isPost()){
// recuperer le produit choisi :
$element = $request->getPost("element");
$result = null;
$result = $this->getEntityManager()->getRepository('Application\Entity\Element')->findBy(array('etat' => 'valide' , 'pkElement' => $element));
$champs = array();
$i = 0;
foreach ($result as $value) {
$champs[$i] = array("id"=>$value->getPkElement() , "nom"=>$value->getNom());
$i++;
}
$data = array(
'result' => true,
'data' => $champs
);
return $this->getResponse()->setContent(Json::encode($data));
}
}
Then the call in the view.phtml :
$.post('/application/controller_name/getList', {element: $("select[name=element]").val()}, function(result) {
var options = $("select[name=element]");
var obj = JSON.parse(result);
var data = obj.data;
var selected = "";
options.empty();
for (var i = 0; i < data.length; i++) {
options.append($("<option />").val(data[i]['id']).text(data[i]['nom']));
}
});
Hope it helps.

JSON Parsing - How to get rid of leading tab character in front of data?

I am trying to remove a tab character from a json_encoded data from php? Every time I try to fetch data from the script as JSON enocded format I use the following code below to parse my data but can not get the jsonStr to be parsed.
The error I am getting is
Error: JSON.parse: unexpected character at line 1 column 1 of the JSON
data
Code
jsonStr = data.toString();
jsonStr = JSON.stringify(jsonStr.replace("\t",""));
totJSON = JSON.parse(jsonStr['totalActionItems']);
How do I resolve this error to parse a well formed json string correctly?
EDIT
Corrected Parsing Code (JS)
$.ajax({url: "/dashboard/chartdata.php?chart=buildup", success: function(data)
{
jsonStr = data.replace(/\t/g, "");
console.log(jsonStr);
json = JSON.parse(jsonStr);
totJSON = json['totalActionItems'];
PHP Code
function getData($field, $rows)
{
$minDate = $rows[0][$field];
$maxDate = $rows[count($rows)-1][$field];
$date = $minDate;
$findDate = $minDate;
$idx = 0;
$tot = 0;
$dates = array();
$numActionItems = array();
while ($date < $maxDate)
{
if ($rows[$idx][$field] == $date)
{
$tot += $rows[$idx]['numactionitems'];
$idx++;
}
$timestamp = strtotime($date);
$date = date('Y-m-d', strtotime($date . "+1 days"));
$numActionItems[] = array('x'=>$timestamp*1000, 'y'=>$tot);
}
return $numActionItems;
}
function getBuildUpData($field)
{
$manageCharts = new manageCharts();
$rows = $manageCharts->buildup($field);
$items = getData($field, $rows);
return $items;
}
if (isset($_GET['chart']) && $_GET['chart'] == 'buildup')
{
$json = json_encode(['totalActionItems' => getBuildUpData('assigneddate'),
'ecdItems' => getBuildUpData('ecd'),
'originalDueItems' => getbuildUpData('duedate'),
'closedItems' => getBuildUpData('closeddate')]);
echo $json;
}
The following code helped produce the correct json for processing.
jsonStr = data.replace(/\t/g, "");
//console.log(jsonStr);
json = JSON.parse(jsonStr);
totJSON = json['totalActionItems'];

Why php service do not get variables?

From UI I make call:
$http.post('services/loadCategory.php', {
'id' :'1',
'type' :'string'
}).then(function(response) {
debugger;
...
}, function(response) {
...
});
On PHP service I can't get variables from body POST request:
include ("bd.php");
header("Content-type: text/html; charset=windows-1251");
// ----- ----- ----- ----- -----
if (isset($_POST['type'])) {
$type = $_POST['type'];
}
if (isset($_POST['id'])) {
$id = $_POST['id'];
}
//
exit(json_encode(
array('type' => iconv('windows-1251', 'UTF-8', $_POST['type']),
'id' => iconv('windows-1251', 'UTF-8', $_POST['id'])
)));
Request from service: { id:'', type:'' } How fix that?
When posting JSON to PHP, the $_POST variable is empty. To get the raw JSON in your PHP, use the following:
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$data = json_decode(file_get_contents('php://input'), true);
}
You can then access the data with $data['id'] and $data['type']
Check the incoming $data with print_r($data);
After doing a quick search about this issue, it appears that PHP has a hard time deserializing the POST body sent by AngularJS. AngularJS sends all information JSON encoded (application/json) as compared to most other JavaScript variants which send the content as application/x-www-form-urlencoded.
To fix this, you should either set the content-type of your request to application/x-www-form-urlencoded or you can try one of the solutions below which came from a similar question.
Based on this question, it would seem that the following code (provided by Felipe Miosso) seems to solve the problem:
// Your app's root module...
angular.module('MyModule', [], function($httpProvider) {
// Use x-www-form-urlencoded Content-Type
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* #param {Object} obj
* #return {String}
*/
var param = function(obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for(name in obj) {
value = obj[name];
if(value instanceof Array) {
for(i=0; i<value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value instanceof Object) {
for(subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if(value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
// Override $http service's default transformRequest
$httpProvider.defaults.transformRequest = [function(data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
});
Alternatively, you might be able to fix this problem by adding the following line of code to your PHP:
$params = json_decode(file_get_contents('php://input'),true);

jQuery .load not getting filepath variable

So I have a custom Drupal module that outputs a formatted version of the song node's data based on a node id in the path (load/song/NID). This function works fine, and when I look at the url in my browser, I see that everything has loaded perfectly.
My module's code:
function load_song($nid){
$node = node_load($nid);
$songname = $node->title;
$albumid = $node->field_album['und'][0]['nid'];
$album = node_load($albumid);
$file = $album->field_cover['und'][0];
//Loads the album filepath from the file array returned above
$filepath = $file['uri'];
//The path returned is something like "public://file.jpg"
$filepath = str_replace("public://", "http://mysite.com/sites/default/files/styles/thumbnail/public/", $filepath);
//I then set a variable (imgurl) to the formatted filepath
$imgurl = $filepath;
$artistid = $album->field_artist['und'][0]['nid'];
$artist = node_load($artistid);
$artistname = $artist->title;
echo 'I output the variables + formatting here';
}
With the output, I then load it in my page.tpl.php file in Drupal using the jQuery .load function. My code:
function loadSongInfo(id) {
$("#current-song").html('Loading').load('http://mysite.com/load/song/' + id);
}
So with this input, what I get is the data from the url (which is perfectly formatted), and the other variables I load (artist name, song name, etc) working fine. However, where I have the filepath, all I get is an empty string.
This of course confuses the hell out of me, because it works fine in my browser, but when I call the function in jQuery, it loads all the other variables fine, except for the filepath.
I've tried (and got unsuccessful results):
Casting the variable $filepath to a string using three different methods
(I thought it might be something weird with the url) I replaced the filepath variable with just the static string of it ("http://mysite.com/sites/default/files/styles/thumbnail/public/file.jpg"), which returned the correct result, but still fails with the actual variable
var_dump
print_r
Does anyone have any idea why this isn't working?
Mymodule
function mymodule_menu(){
$items = array();
$items['js/song'] = array(
'page callback' => 'load_song',
'type' => MENU_CALLBACK,
'access arguments' => array('access content')
);
}
function load_song() {
$nid = $_POST['nid'];
$node = node_load($nid);
/*
* Check for node existing
* Return response.error if not loaded
*/
if(!$node->nid){
drupal_json(array('error' => t('Some text for error')));
die();
}
$songtitle = $node->title;
$albumid = $node->field_album['und'][0]['nid'];
$album = node_load($albumid);
$file = $album->field_cover['und'][0];
// Loads the album filepath from the file array returned above
$filepath = $file['uri'];
// The path returned is something like "public://file.jpg"
$filepath = str_replace("public://", "http://mysite.com/sites/default/files/styles/thumbnail/public/", $filepath);
// I then set a variable (imgurl) to the formatted filepath
$imagepath = $filepath;
$artistid = $album->field_artist['und'][0]['nid'];
$artist = node_load($artistid);
$artistname = $artist->title;
$object = array(
'song_title' => l($songtitle, 'node/'. $node->nid),
'image_path' => $imagepath,
'artist_name' => l($artistname, $artist->nid)
);
drupal_json(array('data' => $object));
die();
}
Javascript:
Drupal.behaviors.SongInit = function(context){
$("#current-song").html('Loading...').load("/load/song", {
nid : id
}, function(response, status, xhr) {
if (status == 'error') {
var msg = Drupal.t("Sorry but there was an error: ");
$("#current-song").html(msg + xhr.status + " " + xhr.statusText);
}
if (response.error) {
var msg = Drupal.t("Sorry but there was an error: ");
$("#current-song").html(msg);
}
else {
var msg = response.data.song_title + '<br />';
var msg = '<img src=/"' + response.data.image_path + ' /><br />';
var msg = response.data.artist_name + '<br />';
$("#current-song").html(msg);
Drupal.attachBehaviors(context);
}
});
}

Categories