/usr/lib/ruby/vendor_ruby/diaspora_federation/discovery/xrd_document.rb is in ruby-diaspora-federation 0.1.4-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | module DiasporaFederation
module Discovery
# This class implements basic handling of XRD documents as far as it is
# necessary in the context of the protocols used with diaspora* federation.
#
# @note {http://tools.ietf.org/html/rfc6415 RFC 6415} recommends that servers
# should also offer the JRD format in addition to the XRD representation.
# Implementing +XrdDocument#to_json+ and +XrdDocument.json_data+ should
# be almost trivial due to the simplicity of the format and the way the data
# is stored internally already. See
# {http://tools.ietf.org/html/rfc6415#appendix-A RFC 6415, Appendix A}
# for a description of the JSON format.
#
# @example Creating a XrdDocument
# doc = XrdDocument.new
# doc.expires = DateTime.new(2020, 1, 15, 0, 0, 1)
# doc.subject = "http://example.tld/articles/11"
# doc.aliases << "http://example.tld/cool_article"
# doc.aliases << "http://example.tld/authors/2/articles/3"
# doc.properties["http://x.example.tld/ns/version"] = "1.3"
# doc.links << { rel: "author", type: "text/html", href: "http://example.tld/authors/2" }
# doc.links << { rel: "copyright", template: "http://example.tld/copyright?id={uri}" }
#
# doc.to_xml
#
# @example Parsing a XrdDocument
# data = XrdDocument.xml_data(xml_string)
#
# @see http://docs.oasis-open.org/xri/xrd/v1.0/xrd-1.0.html Extensible Resource Descriptor (XRD) Version 1.0
class XrdDocument
# xml namespace url
XMLNS = "http://docs.oasis-open.org/ns/xri/xrd-1.0".freeze
# +Link+ element attributes
LINK_ATTRS = %i(rel type href template).freeze
# format string for datetime (+Expires+ element)
DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ".freeze
# The <Expires> element contains a time value which specifies the instant at
# and after which the document has expired and SHOULD NOT be used.
# @param [DateTime] value
attr_writer :expires
# The <Subject> element contains a URI value which identifies the resource
# described by this XRD.
# @param [String] value
attr_writer :subject
# @return [Array<String>] list of alias URIs
attr_reader :aliases
# @return [Hash<String => mixed>] list of properties. Hash key represents the
# +type+ attribute, and the value is the element content
attr_reader :properties
# @return [Array<Hash<attr => val>>] list of +Link+ element hashes. Each
# hash contains the attributesa and their associated values for the +Link+
# element.
attr_reader :links
def initialize
@aliases = []
@links = []
@properties = {}
end
# Generates an XML document from the current instance and returns it as string
# @return [String] XML document
def to_xml
Nokogiri::XML::Builder.new(encoding: "UTF-8") {|xml|
xml.XRD("xmlns" => XMLNS) {
xml.Expires(@expires.strftime(DATETIME_FORMAT)) if @expires.instance_of?(DateTime)
xml.Subject(@subject) if !@subject.nil? && !@subject.empty?
add_aliases_to(xml)
add_properties_to(xml)
add_links_to(xml)
}
}.to_xml
end
# Parse the XRD document from the given string and create a hash containing
# the extracted data.
#
# Small bonus: the hash structure that comes out of this method is the same
# as the one used to produce a JRD (JSON Resource Descriptor) or parsing it.
#
# @param [String] xrd_doc XML string
# @return [Hash] extracted data
# @raise [InvalidDocument] if the XRD is malformed
def self.xml_data(xrd_doc)
doc = parse_xrd_document(xrd_doc)
{}.tap do |data|
exp_elem = doc.at_xpath("xrd:XRD/xrd:Expires", NS)
data[:expires] = DateTime.strptime(exp_elem.content, DATETIME_FORMAT) unless exp_elem.nil?
subj_elem = doc.at_xpath("xrd:XRD/xrd:Subject", NS)
data[:subject] = subj_elem.content unless subj_elem.nil?
parse_aliases_from_xml_doc(doc, data)
parse_properties_from_xml_doc(doc, data)
parse_links_from_xml_doc(doc, data)
end
end
private
NS = {xrd: XMLNS}.freeze
def add_aliases_to(xml)
@aliases.each do |a|
next if !a.instance_of?(String) || a.empty?
xml.Alias(a.to_s)
end
end
def add_properties_to(xml)
@properties.each do |type, val|
xml.Property(val.to_s, type: type)
end
end
def add_links_to(xml)
@links.each do |l|
attrs = {}
LINK_ATTRS.each do |attr|
attrs[attr.to_s] = l[attr] if l.key?(attr)
end
xml.Link(attrs)
end
end
private_class_method def self.parse_xrd_document(xrd_doc)
raise ArgumentError unless xrd_doc.instance_of?(String)
doc = Nokogiri::XML::Document.parse(xrd_doc)
raise InvalidDocument, "Not an XRD document" if !doc.root || doc.root.name != "XRD"
doc
end
private_class_method def self.parse_aliases_from_xml_doc(doc, data)
aliases = []
doc.xpath("xrd:XRD/xrd:Alias", NS).each do |node|
aliases << node.content
end
data[:aliases] = aliases unless aliases.empty?
end
private_class_method def self.parse_properties_from_xml_doc(doc, data)
properties = {}
doc.xpath("xrd:XRD/xrd:Property", NS).each do |node|
properties[node[:type]] = node.children.empty? ? nil : node.content
end
data[:properties] = properties unless properties.empty?
end
private_class_method def self.parse_links_from_xml_doc(doc, data)
links = []
doc.xpath("xrd:XRD/xrd:Link", NS).each do |node|
link = {}
LINK_ATTRS.each do |attr|
link[attr] = node[attr.to_s] if node.key?(attr.to_s)
end
links << link
end
data[:links] = links unless links.empty?
end
end
end
end
|