I am trying to compute an HMAC signature in Google Apps Script, but the documentation isn't 100% clear on how I need to pass in the parameters, and I have been unable to get the expected output.
To determine if I am getting correct output, I am comparing the result against known-good PHP code. That code is:
$key = "a2V5"; # this is "key" base64-encoded
$value = "test";
$result = base64_encode(hash_hmac('sha512', $value, base64_decode($key), true));
My code in Google Apps Script is:
key = "a2V5"; // this is "key" base64-encoded
value = "test";
result = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, value, Utilities.base64Decode(key)));
The output I expected to receive was:
KHoPuJp/vfpbVThjaRjlN6W4MGXk/zMSaLeqoRXd4EepsPT7W4KGCPwLYyfxAFX3Y3sFjp4Nu55piQGj5t1GHA==
But what I got instead was:
mGXJ3X/nH5ZIFUAPtf1PsViY50pD3cfU7J8w2KAIEAqrAgZ3dpKcuy5V1yvH4/C5n1C9rFFsKc2JKHTwUqPscQ==
What did I screw up here?
I reviewed your code and there is one thing which caught my eye:
Utilities.base64Decode(key) method returns Byte[]
Utilities.computeHmacSignature(macAlgorithm, value, key) accepts 3 parameters. value and key are of type string.
Maybe this is the issue. Why don't you try something like the following and check results then:
key = "a2V5"; // this is "key" base64-encoded
clearKey = "key";
value = "test";
result = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, value, clearKey));
I check Google Apps Script here.
Related
Using Powershell, I get a json snippet returned into my First variable (this always works fine);
# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'
Then I call the convert function into a temp variable like this;
$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;
which puts the Json into a nice little data structure like this;
message_id
----------
9093813071099257562
From which I can select the value I want by calling this;
$nMessage_id = $ResponseBody.message_id;
Usually, this works fine and I get the value into my second variable;
$nMessage_id = 9093813071099257562
The problem is: Sometimes I get nothing in $nMessage_id, even though $whatStatusJsonContent is definitely logged as having the Json returned correctly from the function.
My question is: Do I have to ConvertFrom-Json, or can I read it raw from the First variable..?
COMBINED SOLUTION: Thanks to #mklement() and #Bernard-Moeskops
# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'
$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;
if($ResponseBody.message_id){
# ConvertFrom-Json got the value!
$nMessage_id = $ResponseBody.message_id
}else{
# ConvertFrom-Json didn't work!
$nMessage_id = = ($whatStatusJsonContent -split '[:}]')[1]
}
There's nothing overtly wrong with your code.
ConvertFrom-Json should work as expected and return a [pscustomobject] instance with a .message_id property.
In your example, the message_id JSON property value is a number that is an integer, for which ConvertTo-Json automatically chooses a suitable integer data type as follows: the smallest signed type >= [int] (System.Int32)[1] that can accommodate the value ([int] -> [long] (System.Int64) -> [decimal] (System.Decimal)); the caveat is that if the value can't even fit into a [decimal], an - inexact - [double] is used.[2]
With the sample JSON in your question, [long] is chosen.
In a follow-up comment you state:
The routine makes over 1000 calls/hour and for most of them the Json comes back and the $nMessage_id is yielded perfectly. Then, suddenly, the $nMessage_id is empty, even though the Json is logged as coming back fine. So, somewhere in the ConvertFrom-Json or $ResponseBody.message_id the value is going missing...
I have no explanation, but if - for whatever reason - ConvertFrom-Json is the culprit, you can try string manipulation as a workaround to extract the message ID and see if that helps:
$whatStatusJsonContent = '{"message_id":9093813071099257562}'
# Extract the message_id property value as a *string*
# (which you can cast to a numeric type if/as needed).
$message_id = ($whatStatusJsonContent -split '[:}]')[1]
The above stores a string with content 9093813071099257562 in $message_id; note that, as written, the input string must have the exact format as above with respect to whitespace; while it is possible to make the text parsing more robust, not having to worry about format variations is one good reason to use a dedicated parser such as ConvertFrom-Json.
Another option is to try a different JSON parser to see if that helps.
Json.NET is the preeminent JSON parser in the .NET world (which now underlies the JSON cmdlets in PowerShell Core):
$whatStatusJsonContent = '{"message_id":9093813071099257562}'
$message_id = [NewtonSoft.Json.Linq.JObject]::Parse($whatStatusJsonContent).message_id.Value
Note: Json.NET - like ConvetFrom-Json in PowerShell _Core - commendably uses the arbitrary large [bigint] type as well once a number is too large to fit into a [long].
Use of the Json.NET assembly has the added advantage of better performance than the ConvertFrom-Json cmdlet.
In PowerShell Core, you can run the above code as-is (the assembly is preloaded); in Windows PowerShell you'll have to download the package via the link above and add the assembly (NewtonSoft.Json.dll) to your session with Add-Type -LiteralPath.
[1] Curiously, in PowerShell Core, as of (at least) v6.2.0, the smallest type chosen is [long] (System.Int64).
[2] More helpfully, PowerShell Core, as of (at least) v6.2.0, creates an arbitrarily large [bigint] (System.Numerics.BigInteger) instance once a value doesn't fit into a [long] anymore; that is, the [decimal] type is skipped altogether.
You are going to have to convert it, so that PowerShell can understand it. It will convert from a string to a PSCustomObject. Just check by asking the type of the variable before and after.
$ResponseBody.message_id.GetType()
If sometimes the output is nothing, you could do something like:
if($ResponseBody.message_id){
$nMessage_id = $ResponseBody.message_id
}else{
throw "No message id found"
}
Hope this helps.
Using the example from the Spring docs, I'm trying to return a value from a mySQL function. I keep getting the error Can't set IN parameter for return value of stored function call;.
I created a mySQL function that works fine (ran in MySQL Workbench). I've written a SimpleJdbcCall statement, set up the parameters as per Spring docs example but consistently get this error. If I turn the function into a procedure, the code works, I just have to retrieve the return value from the result set.
I used https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch13s05.html, section 13.5.8 as reference.
CREATE FUNCTION `ScenarioRegistration`(
environment VARCHAR(45),
username VARCHAR(15),
scenario_name VARCHAR(45)) RETURNS int(11)
A couple of SELECT statements followed by an INSERT then
RETURN scenario_id; // The inserted id
Java code:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess();
simpleJdbcCall.addDeclaredParameter(new SqlParameter("environment"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("username"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("scenario_name"
,Types.VARCHAR));
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
simpleJdbcCall.setReturnValueRequired(true);
Integer scenario_id = simpleJdbcCall.executeFunction(
Integer.class, parameters);
All I want the routine to do is give me back the id of the newly inserted scenario.
What I get is:
SQL [{? = call scenarioregistration(?, ?)}]; Can't set IN parameter for return value of stored function call.
I find it interesting that it's taken my THREE input values and changed them to an output and TWO input values.
Anyone enlighten me as to the problem and how to fix it?
Thanks,
Steven.
I would refer to the latest docs here for your answer. It appears Spring is trying to infer the output because you didn't explicity specify one.
Per the docs above there are two valid approaches on calling the desired function with the SimpleJdbcCall:
Inferred Parameters
Because you've specified withoutProcedureColumnMetaDataAccess, Spring isn't going to look and see what the ins/outs are to your function. If you want it easy, just don't specify that and you should be able to do:
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.executeFunction(Integer.class, parameters);
Explicit Parameters
If you want to keep withoutProcedureColumnMetaDataAccess turned off for whatever reason, you can do:
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate)
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("environment", "username", "scenario_name")
.declareParameters(
new SqlOutParameter("scenario_id", Types.NUMERIC),
new SqlParameter("environment", Types.VARCHAR),
new SqlParameter("username", Types.VARCHAR),
new SqlParameter("scenario_name", Types.VARCHAR)
).executeFunction(Integer.class, parameters);
Note: It appears that order is critical in this example. The output parameter should be declared first, and the subsequent named IN parameters come last. That is, the order of the parameters ? are ordinal in [{? = call scenarioregistration(?, ?, ?)}])
Alternative NamedParameterJdbcTemplate Solution
Another way to invoke your function is via an actual JDBC call. This could hypothetically save you the grief of using the fine tuning of the SimpleJdbcCall.
Integer scenarioId = namedParameterJdbcTemplate.queryForObject(
"SELECT ScenarioRegistration(:environment, :username, :scenario_name)",
parameters,
Integer.class);
Hello I'm attempting delete a certain index in my array while using Angular2 and Typescript. I would like to retrieve the index from the value.
My array is declared normally...
RightList = [
'Fourth property',
'Fifth property',
'Sixth property',
]
I start out with a basic premise to set up my remove function.
removeSel(llist: ListComponent, rlist:ListComponent){
this.selectedllist = llist;
console.log(JSON.stringify(this.selectedllist)); // what is to be searched turned into a string so that it may actually be used
My console.log of my JSON.Stringify tells me that the value that I will attempt to remove is "Sixth property". However when I attempt to look for this value in my array using the following code. It returns -1 which means my value is not found in the array.
var rightDel = this.RightList.indexOf((JSON.stringify(this.selectedllist))); // -1 is not found 1 = found
console.log(rightDel);
On my output to the console it does return the item that is to be searched for but does not find the item in the array
CONSOLE OUTPUT:
"Sixth property" // Item to be searched for
-1 // not found
Is there something wrong in my implementation of my function that searches the array?
Of course indexOf will not find you item in array because
JSON.stringify(this.selectedllist) !== this.selectedllist
This is because JSON stringified string encodes quotes around literal, that original string doesn't have. It is easy to test:
var a = 'test';
console.log( JSON.stringify(a), a, JSON.stringify(a) === a )
Remove JSON.stringify and it should work. In general, to cast something to String type you should use its .toString() method, or simply wrap this something into String(something).
in a Windows 10 UWP I try use WebAuthenticationCoreManager.RequestTokenAsync to get the result from a login with a Microsoft account.
I get a WebTokenRequestResult with Success. ResponseData[0] contains a WebAccount with an ID - but the UserName is empty.
The scope of the call is wl.basic - so I should get a lot of information...
I'm not sure how to retrieve extra information - and for the current test the Username would be OK.
I checked out the universal samples - and there I found a snippet which tries to do what I'm trying - an output of webTokenRequestResult.ResponseData[0].WebAccount.UserName.
By the way - the example output is also empty.
Is this a bug - or what do I (and the MS in the samples) have to do to get the users profile data (or at least the Username)?
According to the documentation (https://learn.microsoft.com/en-us/windows/uwp/security/web-account-manager), you have to make a specific REST API call to retrieve it:
var restApi = new Uri(#"https://apis.live.net/v5.0/me?access_token=" + result.ResponseData[0].Token);
using (var client = new HttpClient())
{
var infoResult = await client.GetAsync(restApi);
string content = await infoResult.Content.ReadAsStringAsync();
var jsonObject = JsonObject.Parse(content);
string id = jsonObject["id"].GetString();
string name = jsonObject["name"].GetString();
}
As to why the WebAccount property doesn't get set... shrugs
And FYI, the "id" returned here is entirely different from the WebAccount.Id property returned with the authentication request.
The current code takes form input and does THIS to it:
$apikey = 'myapikey';
$q = urlencode($bookSearchTerm);
$endpoint = 'https://www.googleapis.com/books/v1/volumes?q=' . $q . '&key=' . $apikey;
$session = curl_init($endpoint);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($session);
curl_close($session);
$search_results = json_decode($data);
if ($search_results === NULL) die('Error parsing json');
Just for kicks, I also did
echo $endpoint;
which shows
https://www.googleapis.com/books/v1/volumes?q=lord+of+the+rings&key=myapikey
When I enter that URL into a browser, I get a screen full o' data, telling me that, among other things, there are 814 items.
Yet when I run the code on a page, I get
Error parsing json
Can someone show me where I'm going wrong?
Thanks in advance.
By the response to the comment, it could be set, maybe not. It may also be the case that what is returned isn't parse-able by the parser because it isn't in the right data format. Check what $data gives back as a result. If it's correct then by the json_decode doc on the PHP site it may be that it's simply too big for the parser to parse (reaches recursion limit) though I doubt that.
It it is possible that the what is return just overflows the PHP allocated memory limit. PHP parses JSON into associative or numbered arrays, which can get expensive. So if what you get back is just too big, it'll fail to finish parsing and just return null.