Xades4j - RuntimeException : "Could not resolve the node to a handle." with custom SignatureAppendingStrategy - xades4j

I am trying to sign a UBL document and I want to append the signature generated by xades4j within Extensions element tree like this :
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionURI>urn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>
<ext:ExtensionContent>
<sig:UBLDocumentSignatures xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2" xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2" xmlns:sbc="urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2">
<sac:SignatureInformation>
<cbc:ID>urn:oasis:names:specification:ubl:signature:1</cbc:ID>
<sbc:ReferencedSignatureID>
urn:oasis:names:specification:ubl:signature:Invoice
</sbc:ReferencedSignatureID>
*ds:Signature element goes here...*
</sac:SignatureInformation>
</sig:UBLDocumentSignatures>
</sig:UBLDocumentSignatures>
</ext:ExtensionContent>
</ext:UBLExtension>
</ext:UBLExtensions>
rest of Invoice children ...
</Invoice>
Code to generate signature :
org.w3c.dom.Document w3cDoc = ...;
KeyingDataProvider keyingDataProvider = new AppxKeyDataProvider();
SignatureAlgorithms signatureAlgorithms = new
SignatureAlgorithms().withSignatureAlgorithm("ECDSA", XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256);
XadesSigningProfile profile = new XadesBesSigningProfile(keyingDataProvider).withSignatureAlgorithms(signatureAlgorithms);
XadesSigner signer = profile.newSigner();
DataObjectDesc desc = new DataObjectReference("")
.withTransform(new XPathTransform("not(//ancestor-or-self::ext:UBLExtensions)"))
.withTransform(new XPathTransform("not(//ancestor-or-self::cac:Signature)"))
.withTransform(new XPathTransform("not(//ancestor-or-self::cac:AdditionalDocumentReference[cbc:ID='QR'])"))
.withTransform(new xades4j.algorithms.CanonicalXMLWithoutComments());
XadesSignatureResult result = signer.sign(new SignedDataObjects(desc), w3cDoc.getDocumentElement(),signatureAppendingStrategy);
Custom SignatureAppendingStrategy.append() method implementation
#Override
public void append(Element signatureElement, Node referenceNode) {
Element ublExtensions = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2","UBLExtensions");
ublExtensions.setPrefix("ext");
Element ublExtension = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2","UBLExtension");
ublExtension.setPrefix("ext");
ublExtensions.appendChild(ublExtension);
Element extensionURL = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2","ExtensionURI");
extensionURL.setPrefix("ext");
Node urlValue = w3cDoc.createTextNode("urn:oasis:names:specification:ubl:dsig:enveloped:xades");
extensionURL.appendChild(urlValue);
ublExtension.appendChild(extensionURL);
Element extensionContent = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2","ExtensionContent");
extensionContent.setPrefix("ext");
ublExtension.appendChild(extensionContent);
Element ublDocumentSignatures = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2","sig:UBLDocumentSignatures");
ublDocumentSignatures.setAttribute("xmlns:sac", "urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2");
ublDocumentSignatures.setAttribute("xmlns:sbc", "urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2");
extensionContent.appendChild(ublDocumentSignatures);
Element signatureInformation = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2","SignatureInformation");
signatureInformation.setPrefix("sac");
ublDocumentSignatures.appendChild(signatureInformation);
Element cbcId = w3cDoc.createElementNS("urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2","ID");
cbcId.setPrefix("cbc");
Node idValue = w3cDoc.createTextNode("urn:oasis:names:specification:ubl:signature:1");
cbcId.appendChild(idValue);
signatureInformation.appendChild(cbcId);
signatureInformation.appendChild(signatureElement);
referenceNode.insertBefore(ublExtensions, referenceNode.getFirstChild());
}
Exception :
Exception in thread "main" java.lang.RuntimeException: Could not resolve the node to a handle
at org.apache.xml.dtm.ref.DTMManagerDefault.getDTMHandleFromNode(DTMManagerDefault.java:576)
at org.apache.xpath.XPathContext.getDTMHandleFromNode(XPathContext.java:184)
at org.apache.xpath.XPath.execute(XPath.java:303)
at org.apache.xpath.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:121)
at org.apache.xpath.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:91)
at org.apache.xpath.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:176)
at org.apache.xml.security.utils.JDKXPathAPI.evaluate(JDKXPathAPI.java:112)
at org.apache.xml.security.transforms.implementations.TransformXPath$XPathNodeFilter.isNodeInclude(TransformXPath.java:138)
at org.apache.xml.security.c14n.implementations.CanonicalizerBase.isVisible(CanonicalizerBase.java:489)
at org.apache.xml.security.c14n.implementations.CanonicalizerBase.canonicalizeXPathNodeSet(CanonicalizerBase.java:366)
at org.apache.xml.security.c14n.implementations.CanonicalizerBase.engineCanonicalizeXPathNodeSetInternal(CanonicalizerBase.java:302)
at org.apache.xml.security.c14n.implementations.CanonicalizerBase.engineCanonicalize(CanonicalizerBase.java:147)
at org.apache.xml.security.transforms.implementations.TransformC14N.enginePerformTransform(TransformC14N.java:70)
at org.apache.xml.security.transforms.Transform.performTransform(Transform.java:326)
at org.apache.xml.security.transforms.Transforms.performTransforms(Transforms.java:267)
at org.apache.xml.security.signature.Reference.getContentsAfterTransformation(Reference.java:450)
at org.apache.xml.security.signature.Reference.calculateDigest(Reference.java:708)
at org.apache.xml.security.signature.Reference.generateDigestValue(Reference.java:417)
at org.apache.xml.security.signature.Manifest.generateDigestValues(Manifest.java:209)
at org.apache.xml.security.signature.XMLSignature.sign(XMLSignature.java:782)
at xades4j.production.SignerBES.sign(SignerBES.java:270)
at testx.TestXades.main(TestXades.java:276)
Actually the exception occurs while I apply the XPath transform "not(//ancestor-or-self::ext:UBLExtensions)".

Related

Getting PidLidEndRecurrenceDate value using Ews

What is the correct way of getting PidLidEndRecurrenceDate values using Ews. below code does not give proper result. property details that i am looking is https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxprops/816378cf-07ef-4926-b7d2-53475792403d
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials("X#X.com", "XXX");
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ItemView view = new ItemView(10);
Guid MyPropertySetId = new Guid("{6ED8DA90-450B-101B-98DA-00AA003F1305}");
int intValue = Convert.ToInt32("0x0000000F", 16);
ExtendedPropertyDefinition extendedPropertyDefinition =
new ExtendedPropertyDefinition(MyPropertySetId, intValue, MapiPropertyType.Integer);
view.PropertySet =
new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, extendedPropertyDefinition);
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Calendar, view);
foreach (Item item in findResults.Items)
{
Console.WriteLine(item.Subject);
if (item.ExtendedProperties.Count > 0)
{
// Display the extended name and value of the extended property.
foreach (ExtendedProperty extendedProperty in item.ExtendedProperties)
{
Console.WriteLine(" Extended Property Name: " + extendedProperty.PropertyDefinition.Name);
Console.WriteLine(" Extended Property Value: " + extendedProperty.Value);
}
}
}
That property is set on the Meeting invite messages only not on the Master instance of the Calendar Appointments which is what you seem to be looking at. For the Master instances you should just be able to use the strongly typed property https://learn.microsoft.com/en-us/dotnet/api/microsoft.exchange.webservices.data.recurrence.enddate?redirectedfrom=MSDN&view=exchange-ews-api#Microsoft_Exchange_WebServices_Data_Recurrence_EndDate
It you wanted to view the property you have above search the SentItems Folder for invites with recurrences (with Enddates) and that's where you will see it. Or probably easier just look at the messages with a Mapi editor like OutlookSpy or MFCMAPI and you will see the properties available.

How can I "pass" a persistent label in a custom transition animation in iOS8?

I have a custom transition animation between view controllers, and I want a UILabel to be (or appear) the same on both the fromViewController and the toViewController.
I tried the following:
toViewController.nameLabel = fromViewController.nameLabel;
In the context of the code below but got the following error :
[UINavigationController nameLabel]: unrecognized selector sent to
instance
What am I doing wrong?
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
// Grab the from and to view controllers from the context
HC_ExercisePageVC *fromViewController = (HC_ExercisePageVC *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
HC_TimerVC *toViewController = (HC_TimerVC *)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting) {
fromViewController.view.userInteractionEnabled = NO;
[transitionContext.containerView addSubview:toViewController.view];
CGRect startFrame = endFrame;
startFrame.origin.y += 75;
toViewController.movingViews.frame = startFrame;
toViewController.nameLabel = fromViewController.nameLabel;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.movingViews.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
Update: Following the suggestion by #Gavin, I replaced the code with:
// Grab the from and to view controllers from the context
HC_ExercisePageVC *fromViewController = (HC_ExercisePageVC *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UINavigationController *toViewControllerNavigation = (id)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
HC_TimerVC * toViewController = (HC_TimerVC *)toViewControllerNavigation.viewControllers.firstObject;
But when I do that I get error:
-[HC_TimerVC viewControllers]: unrecognized selector sent to instance
I always get hung up on how to handle navcontrollers...
Looks like your toViewController is contained within a UINavigationController, thus it is returning that as the destination.
So you'll need to grab the HC_TimerVC from the navigation controller:
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
// Grab the from and to view controllers from the context
HC_ExercisePageVC *fromViewController = (HC_ExercisePageVC *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UINavigationController *toViewControllerNavigation = (id)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
HC_TimerVC * toViewController = toViewControllerNavigation.viewControllers.firstObject;
....

F#: DataContractJsonSerializer.WriteObject method

I am new to programming and F# is my first language.
Here are the relevant parts of my code:
let internal saveJsonToFile<'t> (someObject:'t) (filePath: string) =
use fileStream = new FileStream(filePath, FileMode.OpenOrCreate)
(new DataContractJsonSerializer(typeof<'t>)).WriteObject(fileStream, someObject)
let dummyFighter1 = { id = 1; name = "Dummy1"; location = "Here"; nationality = "Somalia"; heightInMeters = 2.0; weightInKgs = 220.0; weightClass = "Too fat"}
let dummyFighter2 = { id = 2; name = "Dummy2"; location = "There"; nationality = "Afghanistan"; heightInMeters = 1.8; weightInKgs = 80.0; weightClass = "Just Nice"}
let filePath = #"G:\User\Fighters.json"
saveJsonToFile dummyFighter1 filePath
saveJsonToFile dummyFighter2 filePath
When I run "saveJsonToFile dummyFighter1 filePath", the information is successfully saved. My problem is this: Once I run "saveJsonToFile dummyFighter2 filePath", it immediately replaces all the contents that are already in the file, i.e., all the information about dummyFighter1.
What changes should I make so that information about dummyFighter2 is appended to the file, instead of replacing information about dummyFighter1?
Change the way you open a file setting FileMode.OpenOrCreate to FileMode.Append. Append means "create or append" :
use fileStream = new FileStream(filePath, FileMode.Append)
From MSDN (https://msdn.microsoft.com/fr-fr/library/system.io.filemode%28v=vs.110%29.aspx) :
FileMode.Append opens the file if it exists and seeks to the end of the file, or
creates a new file. This requires FileIOPermissionAccess.Append
permission. FileMode.Append can be used only in conjunction with
FileAccess.Write. Trying to seek to a position before the end of the
file throws an IOException exception, and any attempt to read fails
and throws a NotSupportedException exception.

Loop Through HTML Elements and Nodes

I'm working on an HTML page highlighter project but ran into problems when a search term is a name of an HTML tag metadata or a class/ID name; eg if search terms are "media OR class OR content" then my find and replace would do this:
<link href="/css/DocHighlighter.css" <span style='background-color:yellow;font-weight:bold;'>media</span>="all" rel="stylesheet" type="text/css">
<div <span style='background-color:yellow;font-weight:bold;'>class</span>="container">
I'm using Lucene for highlighting and my current code (sort of):
InputStreamReader xmlReader = new INputStreamReader(xmlConn.getInputStream(), "UTF-8");
if (searchTerms!=null && searchTerms!="") {
QueryScorer qryScore = new QueryScorer(qp.parse(searchTerms));
Highlighter hl = new Highlighter(new SimpleHTMLFormatter(hlStart, hlEnd), qryScore);
}
if (xmlReader!=null) {
BufferedReader br = new BufferedReader(xmlReader);
String inputLine;
while((inputLine = br.readLine())!=null) {
String tmp = inputLine.trim();
StringReader strReader = new stringReader(tmp);
HTMLStripCharFilter htm = HTMLStripCharFilter(strReader.markSupported() ? strReader : new BufferedReader(strReader));
String tHL = hl.getBestFragment(analyzer, "", htm);
tmp = (tHL==null ? tmp : tHL);
}
xmlDoc+=tmp;
}
bufferedReader.close()
As you can see (if you understand Lucene highlighting) this does an indiscriminate find/replace. Since my document will be HTML and the search terms are dictated by users there is no way for me to parse on certain elements or tags. Also, since the find/replace basically loops and appends the HTML to a string (the return type of the method) I have to keep all HTML tags and values in place and order. I've tried using Jsoup to loop through the page but handles the HTML tag as one big result. I also tried tag soup to remove the broken HTML caused by the problem but it doesn't work correctly. Does anyone know how to basically loop though the elements and node (data value) of html?
I've been having the most luck with this
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" enconding=\"UTF-8\"?><!DOCTYPE html>");
Document doc = Jsoup.parse(txt.getResult());
Element elements = doc.getAllElements();
for (Element e : elements) {
if (!(e.tagName().equalsIgnoreCase("#root"))) {
sb.append("<" + e.tagName() + e.attributes() + ">" + e.ownText() + "\n");
}// end if
}// end for
return sb;
The one snag I still get is the nesting isn't always "repaired" properly but still semi close. I'm working more on this.

Adding attribute to checkbox list at runtime

So I have some code that dynamically creates an ASP.NET form based on an XML input file. I'm trying to add attributes to the controls at run time and I'm having some weird issues with list items.
My Server Side Code looks something like this:
Me.radioButtonList = New RadioButtonList()
Me.dropDownList = New DropDownList()
Me.listControl = Nothing
If controlType = "dropdown" Then
Me.listControl = Me.dropDownList
Else
Me.listControl = Me.radioButtonList
End If
For Each ansElement As Answer In strAnswers
Dim newListItem = New ListItem(ansElement.AnswerText, ansElement.AnswerText)
If ansElement.ActionID IsNot Nothing AndAlso ansElement.ActionID <> "" Then
newListItem.Attributes.Add("actionID", ansElement.ActionID)
End If
Me.listControl.Items.Add(newListItem)
Next
Me.listControl.ID = controlID
Me.Controls.Add(Me.listControl)
The problem is when I run the code and the page is render the attributes are being added to the proceeding span tag of the control not the input item itself. So the rendered HTML ends up looking like this.
<span actionID="1">
<input id="lst_dynamic_MedIllnesses_0" name="ctl00$MainContentPlaceHolder$FormGenerator1$lst_dynamic_MedIllnesses$lst_dynamic_MedIllnesses_0" value="None" type="checkbox">
<label for="lst_dynamic_MedIllnesses_0">None</label>
</span>
What do I have to do to get the actionID attribute to be added to the actual input control and not the span tag?
Thanks!
I suppose you are talking about RadioButtonList. The problem with it is that it uses RadioButton control, and it has 3 attributes properties - Attributes, InputAttributes and LabelAttributes. Each of them is used for specific html element.
The problem with RadioButtonList, is that it uses just Attributes property, and doesn't use InputAttributes. Here is code of RadioButtonList.RenderItem method:
protected virtual void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
{
if (repeatIndex == 0)
{
this._cachedIsEnabled = this.IsEnabled;
this._cachedRegisterEnabled = this.Page != null && !this.SaveSelectedIndicesViewState;
}
RadioButton controlToRepeat = this.ControlToRepeat;
int index1 = repeatIndex + this._offset;
ListItem listItem = this.Items[index1];
controlToRepeat.Attributes.Clear();
if (listItem.HasAttributes)
{
foreach (string index2 in (IEnumerable) listItem.Attributes.Keys)
controlToRepeat.Attributes[index2] = listItem.Attributes[index2];
}
if (!string.IsNullOrEmpty(controlToRepeat.CssClass))
controlToRepeat.CssClass = "";
ListControl.SetControlToRepeatID((Control) this, (Control) controlToRepeat, index1);
controlToRepeat.Text = listItem.Text;
controlToRepeat.Attributes["value"] = listItem.Value;
controlToRepeat.Checked = listItem.Selected;
controlToRepeat.Enabled = this._cachedIsEnabled && listItem.Enabled;
controlToRepeat.TextAlign = this.TextAlign;
controlToRepeat.RenderControl(writer);
if (!controlToRepeat.Enabled || !this._cachedRegisterEnabled || this.Page == null)
return;
this.Page.RegisterEnabledControl((Control) controlToRepeat);
}
controlToRepeat is that RadioButton, and it specifies only Attributes property and ignores InputAttributes.
I can suggest way to fix it - you can create new class that inherits RadioButtonList, and use it instead of default. Here is code of that class:
public class MyRadioButtonList : RadioButtonList
{
private bool isFirstItem = true;
protected override void RenderItem(ListItemType itemType, int repeatIndex, RepeatInfo repeatInfo, HtmlTextWriter writer)
{
if (isFirstItem)
{
// this.ControlToRepeat will be created during this first call, and then it will be placed into Controls[0], so we can get it from here and update for each item.
var writerStub = new HtmlTextWriter(new StringWriter());
base.RenderItem(itemType, repeatIndex, repeatInfo, writerStub);
isFirstItem = false;
}
var radioButton = this.Controls[0] as RadioButton;
radioButton.InputAttributes.Clear();
var item = Items[repeatIndex];
foreach (string attribute in item.Attributes.Keys)
{
radioButton.InputAttributes.Add(attribute, item.Attributes[attribute]);
}
// if you want to clear attributes for top element, in that case it's a span, then you need to call
item.Attributes.Clear();
base.RenderItem(itemType, repeatIndex, repeatInfo, writer);
}
}
A bit of description - it has isFirstItem property, as RadioButton control that used by it is created in runtime in the first access, so we need to call RenderItem before we can update InputAttrubutes property. So we call it once and send some stub HtmlTextWriter, so it won't be displayed twice. And then after that we just get this control as Controls[0], and for each ListItem we update InputAttributes values.
PS. Sorry, I didn't use VB.Net so control is written in C#