Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for xpointer root and id search #49

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions lib/xmldsig/reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module Xmldsig
class Reference
attr_accessor :reference, :errors, :id_attr

XPOINTER_ROOT = '#xpointer(/)'
XPOINTER_REG_ID = /#xpointer\(id\('(.*)'\)\)/

class ReferencedNodeNotFound < Exception;
end

Expand Down Expand Up @@ -32,18 +35,21 @@ def referenced_node
"Could not find referenced document with ContentId #{content_id}"
)
end
else
id = reference_uri[1..-1]
referenced_node_xpath = @id_attr ? "//*[@#{@id_attr}=$uri]" : "//*[@ID=$uri or @wsu:Id=$uri]"
variable_bindings = { 'uri' => id }
if ref = document.dup.at_xpath(referenced_node_xpath, NAMESPACES, variable_bindings)
ref
elsif reference_uri.start_with?("#xpointer")
return document.dup.root if reference_uri == XPOINTER_ROOT

matched = reference_uri.match(XPOINTER_REG_ID)
if !matched.nil?
get_node_by_id!(@id_attr, matched[1])
else
raise(
ReferencedNodeNotFound,
"Could not find the referenced node #{id}'"
ReferencedNodeNotFound,
"Could not find referenced document with referenceUri #{reference_uri}"
)
end
else
id = reference_uri[1..-1]
get_node_by_id!(@id_attr, id)
end
else
document.dup.root
Expand Down Expand Up @@ -96,5 +102,20 @@ def validate_digest_value
@errors << :digest_value
end
end

private

def get_node_by_id!(id_attr, id)
referenced_node_xpath = id_attr ? "//*[@#{id_attr}=$uri]" : "//*[@ID=$uri or @wsu:Id=$uri]"
variable_bindings = { 'uri' => id }
if ref = document.dup.at_xpath(referenced_node_xpath, NAMESPACES, variable_bindings)
ref
else
raise(
ReferencedNodeNotFound,
"Could not find the referenced node #{id}'"
)
end
end
end
end
14 changes: 14 additions & 0 deletions spec/lib/xmldsig/reference_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@
)
end

it "returns the referenced node by xpointer root" do
allow(reference).to receive(:reference_uri).and_return("#xpointer(/)")
expect(reference.referenced_node.to_s).to eq(
document.root.to_s
)
end

it "returns the referenced node by xpointer id" do
allow(reference).to receive(:reference_uri).and_return("#xpointer(id('foo'))")
expect(reference.referenced_node.to_s).to eq(
document.at_xpath("//*[@ID='foo']").to_s
)
end

it "returns the referenced node by parent" do
allow(reference).to receive(:reference_uri).and_return("")
expect(reference.referenced_node.to_s).to eq(
Expand Down