WSO2 SP Siddhi xml parsing from wso2event - wso2

I have input stream as wso2event on wso2 SP, and it contain timestamp and payload. Payload is in xml format. How can I parse this payload to variables? I see this doc https://wso2-extensions.github.io/siddhi-map-xml/api/4.0.11/ but i don't know, how get incoming wso2event to sourcemapper and then pars it to variables?

siddhi-map-* extensions are used to map input/output event attributes at the source/sink level.
Since this xml payload is an attribute of another stream, you can use siddhi-execution-map extension to create a map from that xml.
Then you can handle the xml payload as a hashmap within the siddhi app.
Please refer to the documentation[1] for more details on this.
[1] https://wso2-extensions.github.io/siddhi-execution-map/

Ok, I realized, that there is bug in https://wso2-extensions.github.io/siddhi-execution-map/api/latest/ createFromXML function. This function correctly parse xml file over each element, but there is badly defined HashMap, because function is called recursively and every cycle is created new map and override data in old map. So at the end, there is map with only one key.
private Object getMapFromXML(OMElement parentElement) throws XMLStreamException {
Map<Object, Object> topLevelMap = new HashMap<Object, Object>();
Iterator iterator = parentElement.getChildElements();
while (iterator.hasNext()) {
OMElement streamAttributeElement = (OMElement) iterator.next();
String key = streamAttributeElement.getQName().toString();
Object value;
if (streamAttributeElement.getFirstElement() != null) {
value = getMapFromXML(streamAttributeElement);
} else {
logger.info("getFirstElement is null now, iam in else - " + key);
String elementText = streamAttributeElement.getText();
if (elementText.equals("true") || elementText.equals("false")) {
value = Boolean.parseBoolean(elementText);
} else {
if (NumberUtils.isNumber(elementText)) {
try {
value = numberFormat.parse(elementText);
} catch (ParseException e) {
value = elementText;
}
} else {
value = elementText;
}
}
}
topLevelMap.put(key, value);
}
return topLevelMap;
}
topLevelMap should be declared as private global variable. Could someone make ticket on wso2 github to resolve this bug please?

Related

Getting Subject Alternate Names with Pkcs10CertificationRequest

I'm currently able to decode a CSR's values except for Requested Extensions, specifically X509v3 Subject Alternative Name. Here's the relevant part of
my `DecodeCSR(string csr):
public void DecodeCsr(string csrStr){
//getting just csr
var csrChars = Regex.Replace(csrStr, #"-----[^-]+-----", "").Trim().Replace(" ", "").Replace(Environment.NewLine, "").ToCharArray();
//converting that string into a byte array
byte[] csrEncode = Convert.FromBase64CharArray(csrChars, 0, csrChars.Length);
//giving decodeCsr the byte array
Pkcs10CertificationRequest decodeCsr = new Pkcs10CertificationRequest(csrEncode);
//getting a string of subject information
string subject = decodeCsr.GetCertificationRequestInfo().Subject.ToString();
//here's how I'm getting a DerSet of attribute
DerSet atts = (DerSet)decodeCsr.GetCertificationRequestInfo().Attributes;
}
Here's a test csr with SANs:
string csr = "-----BEGIN CERTIFICATE REQUEST-----MIIC1DCCAbwCAQAwXjELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0dlb3JnaWExEDAOBgNVBAcMB0F0bGFudGExDTALBgNVBAoMBFRlc3QxHDAaBgNVBAMME3d3dy50aGlzaXNhdGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFU4pXLB3d8csjvRIkIdZfUF2m9sijtk1bqYohqVwYr3+OyDRkfRuTCni8RJS9VOcl6n5aUiK27P4s5j9LqqfL0vS8B949P/ewb2ip2BGB1sEmxKcsEoZYNNEhMm9p7yNTAEqJ/WN0N1CpKBFV1J/w6xiQy5tUyUe7C9c8DX6K1uhEDF9pfeTaCNxYBShm0JFuAIqn6Z+RzbC7tdwc0KgN/bhx3bEvg8b0p/hgxd2veuUmB/fcIPsFawkGFPcQzLpSbc1Vb+zru40HAbRflyQckA3ZgRsa1OHsdiOyb8vpV7dUm4VHOm38bw2wVImRMfRtNZXrL/WiWcGadtFV8nxXAgMBAAGgMTAvBgkqhkiG9w0BCQ4xIjAgMB4GA1UdEQQXMBWCCHRlc3QuY29tggl0ZXN0Mi5jb20wDQYJKoZIhvcNAQELBQADggEBAKXxHlruiqtTwB1Ov17K+mz03EidfecdW+9u8gcLdOOLKn5kCg6RuC0mCjGHvFGjE6ljFc5cyUFbfdqzd8QXh1f3AgxveR+oq1wExJNr0Yl6kjVEdtndvHhSzUmZZ02EcPbIq/eY5KSTdKidjvIJMwTUtIyUQ71y/vSVn0YavvXYo/re57kC7chW/Ns/hZmHrZ6GvMWE9ea3P3jOKPyXCULJlbQCjXc6CQJAkBlcKpvnW6kU2PjreDWzRMhzqZzUqhc6RsGzz84/xwBsrYXfTj91FQd9+w15CYzBEJOv/Iz3CfVGb4s1+yUPVxgei2ezTjfQVcQgq4CusRnDU5/7lmE=-----END CERTIFICATE REQUEST-----";
The information I can get from decodeCsr.GetCertificationRequestInfo().Attributes is an Org.BouncyCastle.Asn1.DerSet that looks like this:
DerSet atts = (DerSet)decodeCsr.GetCertificationRequestInfo().Attributes;
This is what it looks like in debug mode(a picture of the overal object is below):
atts {[[1.2.840.113549.1.9.14, [[[2.5.29.17, #3026820a61757374696e2e636f6d820b61757374696e322e636f6d820b61757374696e342e636f6d]]]]]} Org.BouncyCastle.Asn1.DerSet
I can see the DerOctetString in debug mode, however I have no idea how to get to it. I believe if i can get that far Hugo's answer may be applicable, there is a DerOctetStringParser but at the moment I have nothing to give it.
I've tried to treat atts as a string removed the OIDs get the value exactly like the DerOctetString in debug mode and cast it as a DerOctetString that didn't work, and I don't believe that answer scales well.
I made it work with the following code :
public static void DecodeCsr(string csr)
{
csr = Regex.Replace(csr, #"-----[^-]+-----", String.Empty).Trim().Replace(" ", "").Replace(Environment.NewLine, "");
PemObject pem = new PemObject("CSR", Convert.FromBase64String(csr));
Pkcs10CertificationRequest request = new Pkcs10CertificationRequest(pem.Content);
CertificationRequestInfo requestInfo = request.GetCertificationRequestInfo();
// an Attribute is a collection of Sequence which contains a collection of Asn1Object
// let's find the sequence that contains a DerObjectIdentifier with Id of "1.2.840.113549.1.9.14"
DerSequence extensionSequence = requestInfo.Attributes.OfType<DerSequence>()
.First(o => o.OfType<DerObjectIdentifier>()
.Any(oo => oo.Id == "1.2.840.113549.1.9.14"));
// let's get the set of value for this sequence
DerSet extensionSet = extensionSequence.OfType<DerSet>().First();
// estensionSet = [[2.5.29.17, #30158208746573742e636f6d820974657374322e636f6d]]]
// extensionSet contains nested sequence ... let's use a recursive method
DerOctetString str = GetAsn1ObjectRecursive<DerOctetString>(extensionSet.OfType<DerSequence>().First(), "2.5.29.17");
GeneralNames names = GeneralNames.GetInstance(Asn1Object.FromByteArray(str.GetOctets()));
Console.WriteLine(names.ToString());
}
static T GetAsn1ObjectRecursive<T>(DerSequence sequence, String id) where T : Asn1Object
{
if (sequence.OfType<DerObjectIdentifier>().Any(o => o.Id == id))
{
return sequence.OfType<T>().First();
}
foreach (DerSequence subSequence in sequence.OfType<DerSequence>())
{
T value = GetAsn1ObjectRecursive<T>(subSequence, id);
if (value != default(T))
{
return value;
}
}
return default(T);
}
The tricky part is that BouncyCastle works with collection everywhere and the requested value is inside a nested nested collection. I use a recursive function because I'm not sure if your CSR will always have this value as nested.
As requested in the comments, here's a Java version (with Bouncy Castle 1.57).
One detail is that I had to format your CSR to make it work (I couldn't read it when it's all in one line):
-----BEGIN CERTIFICATE REQUEST-----
MIIC1DCCAbwCAQAwXjELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB0dlb3JnaWExEDAO
BgNVBAcMB0F0bGFudGExDTALBgNVBAoMBFRlc3QxHDAaBgNVBAMME3d3dy50aGlz
aXNhdGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFU4pX
LB3d8csjvRIkIdZfUF2m9sijtk1bqYohqVwYr3+OyDRkfRuTCni8RJS9VOcl6n5a
UiK27P4s5j9LqqfL0vS8B949P/ewb2ip2BGB1sEmxKcsEoZYNNEhMm9p7yNTAEqJ
/WN0N1CpKBFV1J/w6xiQy5tUyUe7C9c8DX6K1uhEDF9pfeTaCNxYBShm0JFuAIqn
6Z+RzbC7tdwc0KgN/bhx3bEvg8b0p/hgxd2veuUmB/fcIPsFawkGFPcQzLpSbc1V
b+zru40HAbRflyQckA3ZgRsa1OHsdiOyb8vpV7dUm4VHOm38bw2wVImRMfRtNZXr
L/WiWcGadtFV8nxXAgMBAAGgMTAvBgkqhkiG9w0BCQ4xIjAgMB4GA1UdEQQXMBWC
CHRlc3QuY29tggl0ZXN0Mi5jb20wDQYJKoZIhvcNAQELBQADggEBAKXxHlruiqtT
wB1Ov17K+mz03EidfecdW+9u8gcLdOOLKn5kCg6RuC0mCjGHvFGjE6ljFc5cyUFb
fdqzd8QXh1f3AgxveR+oq1wExJNr0Yl6kjVEdtndvHhSzUmZZ02EcPbIq/eY5KST
dKidjvIJMwTUtIyUQ71y/vSVn0YavvXYo/re57kC7chW/Ns/hZmHrZ6GvMWE9ea3
P3jOKPyXCULJlbQCjXc6CQJAkBlcKpvnW6kU2PjreDWzRMhzqZzUqhc6RsGzz84/
xwBsrYXfTj91FQd9+w15CYzBEJOv/Iz3CfVGb4s1+yUPVxgei2ezTjfQVcQgq4Cu
sRnDU5/7lmE=
-----END CERTIFICATE REQUEST-----
That's how I could read the attributes from the CSR:
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
String csr = // Base 64 CSR
PemReader reader = new PemReader(new StringReader(csr));
PemObject object = reader.readPemObject();
reader.close();
PKCS10CertificationRequest req = new PKCS10CertificationRequest(object.getContent());
Attribute[] attributes = req.getAttributes();
for (Attribute at : attributes) {
if ("1.2.840.113549.1.9.14".equals(at.getAttrType().getId())) { // extension request
// there's a sequence inside another sequence
DERSequence seq = (DERSequence) at.getAttrValues().getObjectAt(0);
seq = (DERSequence) seq.getObjectAt(0);
ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) seq.getObjectAt(0);
if ("2.5.29.17".equals(oid.getId())) { // 2.5.29.17 = subject alternative name
DEROctetString str = (DEROctetString) seq.getObjectAt(1);
GeneralNames names = GeneralNames.getInstance(str.getOctets());
System.out.println(names.toString());
}
}
}
The output is:
GeneralNames:
2: test.com
2: test2.com
The tag 2 is the dnsName (as stated by the RFC 5280).
PS: this code is a simple version that assumes there's only one attribute value (when I call at.getAttrValues().getObjectAt(0)). If there are more attributes, probably the getAttrValues() will have more elements and a loop will be better instead of just getting the first element.

Why is my class object empty after running JsonConvert.DeserializeObject<class>(string)?

I am trying to deserialize a JSON string into a large object; I'm using Angular to send my data to a controller. Data is present and correct when it arrives in the controller, but after deserialization, it's null. I've looked at some questions already, like this one here:
Deserialization of JSON.Net returns 'null'
Based on the answer to the question above, and the comment from the user who wrote the question, my code should work, but it doesn't.
Here's my code:
[HttpPost]
public OnlineOrderValidation Post(HttpRequestMessage request)
{
Task<string> result = request.Content.ReadAsStringAsync();
var json = result.Result;
OnlineOrder order = new OnlineOrder();
order = JsonConvert.DeserializeObject<OnlineOrder>(json);
// Save first
_orderFacade.UpdateCurrentOrder(CacheStore, order);
var validation = _orderFacade.ValidateOrder(order);
return validation;
}
The OnlineOrder class should accept all of the data from JsonConvert.DeserializeObject(json), but the values are either 0, null, or false.
I've tried DeserializeAnonymousType(string json, T anonObject) and JavasScriptSerializer.Deserialize(string data) as well, and they both yield an empty OnlineOrder object with null values.
I've also tried passing the object to the controller like this:
public OnlineOrderValidation Post([FromBody]string ooJson)
{
var order = JsonConvert.DeserializeObject<OnlineOrder>(ooJson);
//work with order object...
}
and like this
public OnlineOrderValidation Post([FromUri]string ooJson)
{
var order = JsonConvert.DeserializeObject<OnlineOrder>(ooJson);
//work with order object...
}
I wonder if the problem lies with 'ReadAsStringAsync()'. I noticed that it spits out each property on OnlineOrder out of order. The async part of this method must add each field/value pair as it finishes parsing the string, and since the first field in result doesn't match the first field on the OnlineOrder object, maybe JsonConvert.DeserializeObject() just stops execution.
Do I need to make a wrapper class for OnlineOrder and deserialize to that? Do I need to reorder the fields in my 'result' object before deserializing? Is there something else I'm doing wrong? Thanks all!
EDIT: Here is my JSON, as requested. The actual object is much larger than this, but you get the idea. The JSON string has valid data, but is either nulled or zeroed out after deserialization.
{"isTMIOfferEligible":false,
"tmiOfferCode":null,
"tmiUpgradeOfferCode":null,
"id":"a34mdxdivt0svmu1okucidbi",
"accountNumber":"111111111",
"transferAccountNumber":"222222222",
"serviceAddress":
{"address":"3922 N STREET AVE",
"addressLine":"3901 N STREET AVE",
"suite":"SYNCRD",
"city":"SOOFOO",
"state":"SD",
"zip":"57000",
"franchise":"111",
"market":"1 "},
"transferAddress":
{"disconnectDate":null,
"transferFromAddress":
{"address":"1234 SOME PLACE",
"addressLine":"1234 SOME PLACE",
"suite":"SYNCRD",
"city":"SOOFOO",
"state":"SD",
"zip":"57000",
"franchise":"123",
"market":"Z "
}
}
}
EDIT 2
I've updated my code to deserialize the JSON string from a custom, async method, and instantiate OnlineOrder when it's assigned:
try
{
var orderTask = ReadStringAsynchronously(request);
OnlineOrder order = orderTask.Result;
//work with order object
}
catch (Exception ex) { //...}
private async Task<OnlineOrder> ReadStringAsynchronously(HttpRequestMessage request)
{
try
{
var json = await request.Content.ReadAsStringAsync();
OnlineOrder orderAsync = JsonConvert.DeserializeObject<OnlineOrder>(json);
return orderAsync;
}
catch (Exception)
{
throw new Exception("Error occurred while reading string asynchronously.");
}
}
The order object on the task is still null.
The issue, in this case, was in the JSON string itself. There was HTML nestled within the JSON string that was not being encoded. Before posting to the server, I used encodeURIComponent(value) in a custom method:
function encodeOrderHtml(order) {
debugger;
var o = order;
//scrub HTML from product options
if (o && o.serviceDiscount) {
var sd = o.serviceDiscount;
if (sd.description !== "" && sd.description !== null) {
sd.description = encodeURIComponent(sd.description);
}
if (sd.descriptionNew !== "" && sd.descriptionNew !== null) {
sd.descriptionNew = encodeURIComponent(sd.descriptionNew);
}
if (sd.displayNameNew !== "" && sd.displayNameNew !== null) {
sd.displayNameNew = encodeURIComponent(sd.displayNameNew);
}
if (sd.name !== "" && sd.name !== null) {
sd.name = encodeURIComponent(sd.name);
}
}
return o;
}
I was able to get valid data to the server by posting the object in the body of the request.

Get inline object key and value

I am new in c# and stucked with geting object key and value in loop, i can't even create proper working loop that goes through object records.
Main function that define object
void Auth()
{
var data = new {
username = Username.text,
password = Password.text
};
networkManager.SendData("LOGIN", data);
}
after that data object going through multiple functions and finally comes to this function.
public string format(object nObject)
{
foreach (var row in nObject) {
Debug.Log(row.Key);
}
}
is there any way to create simple object and loop through it outside main function and retrive Key (username, password) and Value (Username.text, Password.text) both as strings also want notice that object not always will contain same data, basically i want simply manipulate with data inside object.
Or maybe there is some other better/correct way to do this ?
Please advise.
If I understand you correctly, you want to enumerate via all pair field and it value.
Because you passing anonymous type I see two options: via reflection and via object deserialization via JSON.
First approach:
public void format(object nObject)
{
foreach (var row in nObject.GetType().GetProperties())
{
Debug.Log($"Key{row.Name}={row.GetValue(nObject)}");
}
}
The second approach is good if you are planing to use complex value types:
public void format(object nObject)
{
var obj = JObject.FromObject(nObject);
foreach (var row in obj)
{
var key = row.Key;
string value;
switch (row.Value.Type)
{
case JTokenType.Array:
value = ((JArray) row.Value).Count.ToString();
break;
case JTokenType.Boolean:
value = ((Boolean)row.Value)? "Да" : "Нет";
break;
default:
value = row.Value.ToString();
break;
}
Debug.Log($"Key{key}={value}");
}
}
Here I use Json.NET
You should use a dictionary, and loop it with a foreach
foreach(KeyValuePair<string, string> entry in myDic)
{
// do something with entry.Value or entry.Key
}
You should look at the MS documentation here

Microsoft graph SingleValueLegacyExtendedProperty request returns empty GUID

I made a request to get a specific single value property from all events in a calendar with the Graph-SDK. To achieve this i used a filter according to the Graph APIs documentation (https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/singlevaluelegacyextendedproperty_get). The filter i used was " id eq 'Boolean {00062002-0000-0000-C000-000000000046} Id 0x8223' ". Below is the code i used for this request.
public static async Task<Tuple<List<Event>, List<ICalendarEventsCollectionRequest>>> GetEventsSingleValuePropertyAsync(GraphServiceClient graphClient, String userId, String calendarId, String filterQuery, int top, String select)
{
List<ICalendarEventsCollectionRequest> requestList = new List<ICalendarEventsCollectionRequest>();
// filterQuery = "id eq 'Boolean {00062002-0000-0000-C000-000000000046} Id 0x8223'"
String filterSingleVP = "singleValueExtendedProperties($filter=" + filterQuery + ")";
List<Event> eventList = new List<Event>();
ICalendarEventsCollectionPage result = null;
ICalendarEventsCollectionRequest request = null;
if (calendarId == "")
request = graphClient.Users[userId].Calendar.Events.Request().Expand(filterSingleVP).Top(top).Select(select);
else
request = graphClient.Users[userId].Calendars[calendarId].Events.Request().Expand(filterSingleVP).Top(top).Select(select);
try
{
if (request != null)
{
result = await request.GetAsync();
requestList.Add(request);
eventList.AddRange(result);
}
if (result != null)
{
var nextPage = result;
while (nextPage.NextPageRequest != null)
{
var nextPageRequest = nextPage.NextPageRequest;
nextPage = await nextPageRequest.GetAsync();
if (nextPage != null)
{
requestList.Add(nextPageRequest);
eventList.AddRange(nextPage);
}
}
}
}
catch
{
throw;
}
return new Tuple<List<Event>, List<ICalendarEventsCollectionRequest>>(eventList, requestList);
}
I get all events and every event that matched the query gets expanded with the SingleValueLegacyExtendedProperty. The only thing that bothers me is that it looks like this:
"singleValueExtendedProperties":
[
{
"value":"true",
"id":"Boolean {00000000-0000-0000-0000-000000000000} Id 0x8223"
}
],
As you can see the value is present but the id now has an empty GUID.
I tested some other properties but i always had the same result.
I thought my filter compares the given "filterQuery" with the "id" in the answer.
Did i misunderstand something or is my request implementation just wrong?
That just looks like a bug on our side. Seems like the Guid prop might not be getting set or serialized correctly. I will bring it up to the team - thanks for the report.
-edit-
Yep, in fact we already have a fix for this that should be checked in in a few days.
-edit, edit-
Just for education's sake, the reason that it behaves this way is that the GUID that you are using is one of the "well known guids". In that case, our code is setting the well-known GUID field internally instead of the normal propertySetId guid field and REST always uses the propertySetId when rendering responses. The fix of course on our side is to use the well known guid field if the propertySetId is Guid.Empty.
-edit,edit,edit-
A fix was checked in for this and will begin normal rollout. It should reach WW saturation in a few weeks.

Invalidate JSON object for keys without quotes in c#

In javascript this question JSON.parse(json) will validate to fail
Is there any alternative in c# when quotes are not provided for names in json object. (names indicate keys in keyvalue pairs)
{
name: "s"
}
should fail validation where as
{
"name": "s"
}
should pass validation
Tried with Newtonsoft.Json's JObject.Parse(body); but it automatically adds quotes and passes validation.
I'm trying to validate according to JSON Standard RFC 4627 in c#. Wondering if there a facility to fail validation in case of not providing quotes for keys in c#
Finally figured out the solution on my own.
public bool ValidateMissingDoubleQuotes(string json)
{
using (var reader = new JsonTextReader(new StringReader(json)))
{
while (reader.Read())
{
return !(reader.TokenType == JsonToken.PropertyName && reader.QuoteChar != '\"');
}
}
return true;
}

Resources