EME Key ID different in session request vs. message (ClearKey) - html

What is the relationship between the kid supplied to MediaKeySession.generateRequest() and the one provided via MediaKeyMessageEvent?
If they are supposed to be the same - why are they different in the code below? note, this won't run here due to security restrictions
navigator.requestMediaKeySystemAccess("org.w3.clearkey", [{
initDataTypes: ['webm'],
audioCapabilities: [{
contentType: 'audio/webm; codecs="opus"'
}],
videoCapabilities: [{
contentType: 'video/webm; codecs="vp8"'
},
{
contentType: 'video/webm; codecs="vp9"'
}
],
}]).then((keySystemAccess) => {
return keySystemAccess.createMediaKeys();
}).then((mediaKeys) => {
var session = mediaKeys.createSession("temporary");
var keyId = "VHM2iIMGiSg";
var initData = '{"kids":["' + keyId + '"]}';
console.log(keyId);
session.addEventListener('message', (evt) => {
var requestJson = new TextDecoder().decode(evt.message);
var request = JSON.parse(requestJson);
console.log(request.kids[0]);
});
this.session.generateRequest("webm", new TextEncoder().encode(initData));
});
output:
VHM2iIMGiSg
eyJraWRzIjpbIlZITTJpSU1HaVNnIl19
expected output is for second line to also be VHM2iIMGiSg

eyJraWRzIjpbIlZITTJpSU1HaVNnIl19 is the base64url encoded value of initData that was passed to generateRequest.
The reason that request.kids[0] is the full value of initData and not the value of keyId is because generateRequest was invoked with the initDataType parameter set to webm. Had the initDataType parameter been set to keyids then request.kids[0] would be the value of keyId.
When the initDataType parameter is set to webm the initData parameter is expected to be a single key ID of one or more bytes. Whereas when the initDataType parameter is set to keyids the initData parameter is expected to be a JSON object encoded as UTF-8, containing a single member kids which is an array of base64url encoded Key ID(s).

Related

U-SQL JsonTuple - How to access specific fields in JSON array

I'm extracting AVRO data which has a JSON field that I need to get values from. The JSON has an array, and I don't know what order the different elements of the array may appear in. How can I target specific node/values?
For example, Filters[0] could be Category one time, but could be AddressType another time.
I'm extracting AVRO data - i.e.
#rs =
EXTRACT date DateTime,
Body byte[]
FROM #input_file
USING new Microsoft.Analytics.Samples.Formats.ApacheAvro.AvroExtractor(#"
...
The Body is JSON that can look like this (but Category is not always Filter[0]. This is a small example; there are 7 different types of "Field"s):
{
""TimeStamp"": ""2019-02-19T15:00:29.1067771-05:00"",
""Filters"": [{
""Operator"": ""eq"",
""Field"": ""Category"",
""Value"": ""Sale""
}, {
""Operator"": ""eq"",
""Field"": ""AddressType"",
""Value"": ""Home""
}
]
}
My U-SQL looks like this, which of course does not always work.
#keyvalues =
SELECT JsonFunctions.JsonTuple(Encoding.UTF8.GetString(Body),
"TimeStamp",
"$.Filters[?(#.Field == 'Category')].Value",
"$.Filters[?(#.Field == 'AddressType')].Value"
) AS message
FROM #rs;
#results =
SELECT
message["TimeStamp"] AS TimeStamp,
message["Filters[0].Value"] AS Category,
message["Filters[1].Value"] AS AddressType
FROM #keyvalues;
Although this does not actually answer my question, as a workaround, I modified the Microsoft 'sample' JsonFunctions.JsonTuple method to be able to specify my own key name for extracted values:
/// Added - Prefix a path expression with a specified key. Use key~$e in the expression.
/// eg:
/// JsonTuple(json, "myId~id", "myName~name") -> field names MAP{ {myId, 1 }, {myName, Ed } }
The modified code:
private static IEnumerable<KeyValuePair<string, T>> ApplyPath<T>(JToken root, string path)
{
var keySeparatorPos = path.IndexOf("~");
string key = null;
var searchPath = path;
if (keySeparatorPos > 0) // =0?if just a leading "=", i.e. no key provided, then don't parse out a key.
{
key = path.Substring(0, keySeparatorPos).Trim();
searchPath = path.Substring(keySeparatorPos + 1);
}
// Children
var children = SelectChildren<T>(root, searchPath);
foreach (var token in children)
{
// Token => T
var value = (T)JsonFunctions.ConvertToken(token, typeof(T));
// Tuple(path, value)
yield return new KeyValuePair<string, T>(key ?? token.Path, value);
}
}
For example, I can access vales and name them
#keyvalues =
SELECT JsonFunctions.JsonTuple(Encoding.UTF8.GetString(Body),
"TimeStamp",
"EventName",
"Plan~ $.UrlParams.plan",
"Category~ $.Filters[?(#.Field == 'Category')].Value",
"AddressType~ $.Filters[?(#.Field == 'AddressType')].Value"
) AS message
FROM #rs;
#results =
SELECT
message["TimeStamp"] AS TimeStamp,
message["EventName"] AS EventName,
message["Plan"] AS Plan,
message["Category"] AS Category,
message["AddressType"] AS AddressType
FROM #keyvalues;
(I've not tested to see what would happen if the same Field appears multiple times in the array; That won't happen in my case)

How does Symbol.keyFor() work?

For the below code,
let obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
}
document.write(Symbol.keyFor(Symbol.for('my_key')) + '<br>'); // retrieves 'my_key'
document.write(Symbol.keyFor(Object.getOwnPropertySymbols(obj)[0])); // does not retrieve 'my_key'
below is the output:
my_key
undefined
Why Symbol.keyFor() does not retrieve token string in second case?
From MDN:
The Symbol.keyFor(sym) method retrieves a shared symbol key from the global symbol registry for the given symbol.
In your first case you are using global symbol but as object key using local symbol:
// local symbol
Symbol('my_key')
// global symbol
Symbol.for('my_key')
When you use global symbol in your object literal it will work as youw expect:
let obj = {
[Symbol.for('my_key')]: 1,
enum: 2,
nonEnum: 3
}
Global symbols are stored in global symbol registry. How do you store local symbols is up to you. Here is demonstrated the difference between the two:
Symbol('my_key') === Symbol('my_key') // false
Symbol.for('my_key') === Symbol.for('my_key') // true

How to extract "sunny" from below represented format?

var email = req.body.emailId;
connection.query('SELECT name FROM fun WHERE email = "' + email +'" ',function(err, result,fields) {
console.log(result);
});
The console displays "result" in the below format:
[{name:'sunny'}]
Can someone tell me how to display"sunny"?
Sunny should be accessible with the following code
alert(result[0].name); //sunny!
As you can see, the JS object displayed is an array with one element, which is an object with one key (name).
So you simply index the array to the first value result[0] and then fetch that element's name value result[0].name.

Querying JSON with JSONPath or SelectTokens? With JSON.NET in C#

I am trying to use the Newtonsoft.Json.Net in c#. The following is part of JSON file that I need to retrieve data out of:
{
"video":{
"local_recording_device":{
"codecs":null
},
"preferred_string":"___PREFERRED___",
"streams":{
"99176901":{
"id":"99176901",
"name":"PTZ Camera",
"site":"someone",
"email":"someone#awebsite.com",
"codec":"VP8 HD1 (720p)",
"local":true,
"screen":false,
"fit_to_window":true,
"stay_on_top":false,
"layout":0,
"native_width":1280,
"native_height":720,
"window_width":456,
"window_height":254,
"preferred":false,
"local_recording":false,
"device_id":"MJPEG Camera",
"normalized_device_id":"MJPEGCamera",
"shared_window_id":"MJPEG Camera",
"enable":true,
"big_location":"2",
"x":347,
"y":737,
"window_id":"197302",
"camera_id":null
},
"3091494011":{
"id":"3091494011",
"name":"Logitech Webcam C930e",
"site":"Joe Smith",
"email":"joe#awebsite.com",
"codec":"VP8 Medium (CIF)",
"local":false,
"screen":false,
"fit_to_window":true,
"stay_on_top":false,
"layout":0,
"native_width":352,
"native_height":288,
"window_width":864,
"window_height":702,
"preferred":true,
"local_recording":false,
"enable":true,
"big_location":"1",
"x":204,
"y":0,
"window_id":"197296",
"camera_id":null
},
"3798287599":{
"id":"3798287599",
"name":"Drive Camera",
"site":"ASiteName",
"email":"asitesame#awebsite.com",
"codec":"VP8 HD1 (720p)",
"local":true,
"screen":false,
"fit_to_window":true,
"stay_on_top":false,
"layout":0,
"native_width":1280,
"native_height":720,
"window_width":456,
"window_height":254,
"preferred":true,
"local_recording":false,
"device_id":"Logitech Webcam C930e",
"normalized_device_id":"LogitechWebcamC930e",
"shared_window_id":"Logitech Webcam C930e",
"enable":true,
"big_location":"3",
"x":814,
"y":737,
"window_id":"262822",
"camera_id":null
}
}
}
}
So, inside the JSON data is: "video", "streams" inside streams can be x amount of different streams (stream id's). The streams in "streams" (the long numbers) can change at anytime. In my example here there are three. I need to search through all streams in "streams" and see if any of them has a "email" that matches a particular email address. Each of the streams has a "email". If a email matches my supplied email address I need to check that streams "enable" to see if it's true or false.
Any help is appreciated in leading me in the right direction. I have not worked with a JSON data before.
You can use LINQ to JSON and SelectTokens to do the required query:
string json = GetJson();
var obj = JObject.Parse(json);
var testEmail = "someone#awebsite.com";
var streamQuery = obj.SelectTokens("video.streams.*").Where(s => (string)s["email"] == testEmail);
var firstEnabled = streamQuery.Select(s => (bool?)s["enable"]).FirstOrDefault();
The query returns a nullable bool that is true or false if the first stream for the desired email is enabled, or null if there is no stream for that email address.
Note that this returns the enabled state of the first stream matching the given email address. If you want to know if any are enabled, do:
var anyEnabled = streamQuery.Any(s => (bool)s["enable"]);

What is "compressed JSON"?

I see a lot of references to "compressed JSON" when it comes to different serialization formats. What exactly is it? Is it just gzipped JSON or something else?
Compressed JSON removes the key:value pair of json's encoding to store keys and values in seperate parallel arrays:
// uncompressed
JSON = {
data : [
{ field1 : 'data1', field2 : 'data2', field3 : 'data3' },
{ field1 : 'data4', field2 : 'data5', field3 : 'data6' },
.....
]
};
//compressed
JSON = {
data : [ 'data1','data2','data3','data4','data5','data6' ],
keys : [ 'field1', 'field2', 'field3' ]
};
This method of usage i found here
Content from link (http://www.nwhite.net/?p=242)
rarely find myself in a place where I am writing javascript applications that use AJAX in its pure form. I have long abandoned the ‘X’ and replaced it with ‘J’ (JSON). When working with Javascript, it just makes sense to return JSON. Smaller footprint, easier parsing and an easier structure are all advantages I have gained since using JSON.
In a recent project I found myself unhappy with the large size of my result sets. The data I was returning was tabular data, in the form of objects for each row. I was returning a result set of 50, with 19 fields each. What I realized is if I augment my result set I could get a form of compression.
// uncompressed
JSON = {
data : [
{ field1 : 'data1', field2 : 'data2', field3 : 'data3' },
{ field1 : 'data4', field2 : 'data5', field3 : 'data6' },
.....
]
};
//compressed
JSON = {
data : [ 'data1','data2','data3','data4','data5','data6' ],
keys : [ 'field1', 'field2', 'field3' ]
};
I merged all my values into a single array and store all my fields in a separate array. Returning a key value pair for each result cost me 8800 byte (8.6kb). Ripping the fields out and putting them in a separate array cost me 186 bytes. Total savings 8.4kb.
Now I have a much more compressed JSON file, but the structure is different and now harder to work with. So I implement a solution in Mootools to make the decompression transparent.
Request.JSON.extend({
options : {
inflate : []
}
});
Request.JSON.implement({
success : function(text){
this.response.json = JSON.decode(text, this.options.secure);
if(this.options.inflate.length){
this.options.inflate.each(function(rule){
var ret = ($defined(rule.store)) ? this.response.json[rule.store] : this.response.json[rule.data];
ret = this.expandData(this.response.json[rule.data], this.response.json[rule.keys]);
},this);
}
this.onSuccess(this.response.json, text);
},
expandData : function(data,keys){
var arr = [];
var len = data.length; var klen = keys.length;
var start = 0; var stop = klen;
while(stop < len){
arr.push( data.slice(start,stop).associate(keys) );
start = stop; stop += klen;
}
return arr;
}
});
Request.JSON now has an inflate option. You can inflate multiple segments of your JSON object if you so desire.
Usage:
new Request.JSON({
url : 'url',
inflate : [{ 'keys' : 'fields', 'data' : 'data' }]
onComplete : function(json){}
});
Pass as many inflate objects as you like to the option inflate array. It has an optional property called ’store’ If set the inflated data set will be stored in that key instead.
The ‘keys’ and ‘fields’ expect strings to match a location in the root of your JSON object.
Based in Paniyar's answer, we can convert a List of Objects in "compressed" Json format using C# like this:
var JsonString = serializer.Serialize(
new
{
cols = new[] { "field1", "field2", "field3"},
items = data.Select(x => new object[] {x.field1, x.field2, x.field3})
});
I used an array of object because the fields can be int, bool, string...
More Reduction:
If the field is repeated very often and it is a string type, you can get compressed a little be more if you add a distinct list of that field... for instance, a field name job position, city, etc are excellent candidate for this. You can add a distinct list of this items and in each item change the value for a reference number. That will make your Json more lite.
Compressed:
[["KeyA", "KeyB", "KeyC", "KeyD", "KeyE", "KeyF"],
["ValA1", "ValB1", "ValC1", "ValD1", "ValE1", "ValF1"],
["ValA2", "ValB2", "ValC2", "ValD2", "ValE2", "ValF2"],
["ValA3", "ValB3", "ValC3", "ValD3", "ValE3", "ValF3"],
["ValA4", "ValB4", "ValC4", "ValD4", "ValE4", "ValF4"]]
Uncompressed:
[{KeyA: "ValA1", KeyB: "ValB1", KeyC: "ValC1", KeyD: "ValD1", KeyE: "ValE1", KeyF: "ValF1"},
{KeyA: "ValA2", KeyB: "ValB2", KeyC: "ValC2", KeyD: "ValD2", KeyE: "ValE2", KeyF: "ValF2"},
{KeyA: "ValA3", KeyB: "ValB3", KeyC: "ValC3", KeyD: "ValD3", KeyE: "ValE3", KeyF: "ValF3"},
{KeyA: "ValA4", KeyB: "ValB4", KeyC: "ValC4", KeyD: "ValD4", KeyE: "ValE4", KeyF: "ValF4"}]
The most likely answer is that it really is just gzipped JSON. There is no other standard meaning to this phrase.
Re-organizing a homogenous array of JSON objects into a pair of arrays is a very useful technique to make the payload smaller and to speed up encoding and decoding, it is not commonly called "compressed JSON". I haven't run across it ever in open source or any open API, but we use this technique internally and call it "jsontable".