func (xmlNode *XmlNode) addChild(node Node) (err error) { nodeType := node.NodeType() if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE { err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD return } nodePtr := node.NodePtr() if xmlNode.NodePtr() == nodePtr { return } ret := xmlNode.isAccestor(nodePtr) if ret < 0 { return } else if ret == 0 { if !xmlNode.Document.RemoveUnlinkedNode(nodePtr) { C.xmlUnlinkNodeWithCheck((*C.xmlNode)(nodePtr)) } C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr)) } else if ret > 0 { node.Remove() } /* childPtr := C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr)) if nodeType == XML_TEXT_NODE && childPtr != (*C.xmlNode)(nodePtr) { //check the retured pointer //if it is not the text node just added, it means that the text node is freed because it has merged into other nodes //then we should invalid this node, because we do not want to have a dangling pointer node.Remove() } */ return }
// CreateElementNS Create an element with the given namespace func (xp *Xp) createElementNS(prefix, element string, context *C.xmlNode, before *C.xmlNode) (newcontext *C.xmlNode) { ns := C.xmlNewNs(nil, namespaces[prefix].ns_uri, namespaces[prefix].prefix) // candidate for cache ... if ns == nil { panic("ns is nil") } celement := unsafe.Pointer(C.CString(element)) newelement := C.xmlNewDocNode(xp.doc, ns, (*C.xmlChar)(celement), nil) C.free(celement) if before != nil { newcontext = C.xmlAddPrevSibling(before, newelement) } else { if context == nil { context = C.xmlDocGetRootElement(xp.doc) } newcontext = C.xmlAddChild(context, newelement) } return }
func (xmlNode *XmlNode) addChild(node Node) (err error) { nodeType := node.NodeType() if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE { err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD return } nodePtr := node.NodePtr() parentPtr := xmlNode.Ptr.parent if C.xmlNodePtrCheck(unsafe.Pointer(parentPtr)) == C.int(0) { return } isNodeAccestor := false for ; parentPtr != nil; parentPtr = parentPtr.parent { if C.xmlNodePtrCheck(unsafe.Pointer(parentPtr)) == C.int(0) { return } p := unsafe.Pointer(parentPtr) if p == nodePtr { isNodeAccestor = true } } if !isNodeAccestor { C.xmlUnlinkNode((*C.xmlNode)(nodePtr)) C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr)) } else { node.Remove() } /* childPtr := C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr)) if nodeType == XML_TEXT_NODE && childPtr != (*C.xmlNode)(nodePtr) { //check the retured pointer //if it is not the text node just added, it means that the text node is freed because it has merged into other nodes //then we should invalid this node, because we do not want to have a dangling pointer node.Remove() } */ return }
func (xmlNode *XmlNode) addChild(node Node) (err error) { nodeType := node.NodeType() if nodeType == XML_DOCUMENT_NODE || nodeType == XML_HTML_DOCUMENT_NODE { err = ERR_CANNOT_MAKE_DUCMENT_AS_CHILD return } nodePtr := node.NodePtr() if xmlNode.NodePtr() == nodePtr { return } ret := xmlNode.isAccestor(nodePtr) if ret < 0 { return } else if ret == 0 { if !xmlNode.Document.RemoveUnlinkedNode(nodePtr) { C.xmlUnlinkNodeWithCheck((*C.xmlNode)(nodePtr)) } C.xmlAddChild(xmlNode.Ptr, (*C.xmlNode)(nodePtr)) } else if ret > 0 { node.Remove() } return }
func (n *xmlNode) AddChild(child Node) { C.xmlAddChild(n.ptr, (*C.xmlNode)(child.pointer())) }
// xmlAddChild func (parent *Node) AddChild(cur *Node) *Node { return makeNode(C.xmlAddChild(parent.Ptr, cur.Ptr)) }
// NewResponse - create a new response using the supplied metadata and resp. authnrequest and response for filling out the fields // The response is primarily for the attributes, but other fields is eg. the AuthnContextClassRef is also drawn from it func NewResponse(params IdAndTiming, idpmd, spmd, authnrequest, sourceResponse *Xp) (response *Xp) { template := []byte(`<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="" Version="2.0" IssueInstant="" InResponseTo="" Destination="" > <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"></saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="" Version="2.0" IssueInstant="" > <saml:Issuer></saml:Issuer> <saml:Subject> <saml:NameID SPNameQualifier="" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" ></saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="" Recipient="" InResponseTo="" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="" NotOnOrAfter="" > <saml:AudienceRestriction> <saml:Audience></saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="" SessionNotOnOrAfter="" SessionIndex="" > <saml:AuthnContext> <saml:AuthnContextClassRef></saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"> </saml:AttributeStatement> </saml:Assertion> </samlp:Response>`) response = NewXp(template) issueInstant := params.Now.Format(xsDateTime) assertionIssueInstant := params.Now.Format(xsDateTime) assertionNotOnOrAfter := params.Now.Add(params.Slack).Format(xsDateTime) sessionNotOnOrAfter := params.Now.Add(params.Sessionduration).Format(xsDateTime) msgid := params.Id if msgid == "" { msgid = Id() } assertionID := params.Assertionid if assertionID == "" { assertionID = Id() } spEntityID := spmd.Query1(nil, `/md:EntityDescriptor/@entityID`) idpEntityID := idpmd.Query1(nil, `/md:EntityDescriptor/@entityID`) acs := authnrequest.Query1(nil, "@AssertionConsumerServiceURL") response.QueryDashP(nil, "./@ID", msgid, nil) response.QueryDashP(nil, "./@IssueInstant", issueInstant, nil) response.QueryDashP(nil, "./@InResponseTo", authnrequest.Query1(nil, "@ID"), nil) response.QueryDashP(nil, "./@Destination", acs, nil) response.QueryDashP(nil, "./saml:Issuer", idpEntityID, nil) assertion := response.Query(nil, "saml:Assertion")[0] response.QueryDashP(assertion, "@ID", assertionID, nil) response.QueryDashP(assertion, "@IssueInstant", assertionIssueInstant, nil) response.QueryDashP(assertion, "saml:Issuer", idpEntityID, nil) nameid := response.Query(assertion, "saml:Subject/saml:NameID")[0] response.QueryDashP(nameid, "@SPNameQualifier", spEntityID, nil) response.QueryDashP(nameid, "@Format", sourceResponse.Query1(nil, "//saml:NameID/@Format"), nil) response.QueryDashP(nameid, ".", sourceResponse.Query1(nil, "//saml:NameID"), nil) subjectconfirmationdata := response.Query(assertion, "saml:Subject/saml:SubjectConfirmation/saml:SubjectConfirmationData")[0] response.QueryDashP(subjectconfirmationdata, "@NotOnOrAfter", assertionNotOnOrAfter, nil) response.QueryDashP(subjectconfirmationdata, "@Recipient", acs, nil) response.QueryDashP(subjectconfirmationdata, "@InResponseTo", authnrequest.Query1(nil, "@ID"), nil) conditions := response.Query(assertion, "saml:Conditions")[0] response.QueryDashP(conditions, "@NotBefore", assertionIssueInstant, nil) response.QueryDashP(conditions, "@NotOnOrAfter", assertionNotOnOrAfter, nil) response.QueryDashP(conditions, "saml:AudienceRestriction/saml:Audience", spEntityID, nil) authstatement := response.Query(assertion, "saml:AuthnStatement")[0] response.QueryDashP(authstatement, "@AuthnInstant", assertionIssueInstant, nil) response.QueryDashP(authstatement, "@SessionNotOnOrAfter", sessionNotOnOrAfter, nil) response.QueryDashP(authstatement, "@SessionIndex", "missing", nil) response.QueryDashP(authstatement, "saml:AuthnContext/saml:AuthnContextClassRef", sourceResponse.Query1(nil, "//saml:AuthnContextClassRef"), nil) sourceResponse = NewXp([]byte(sourceResponse.Pp())) sourceAttributes := sourceResponse.Query(nil, `//saml:AttributeStatement/saml:Attribute`) destinationAttributes := response.Query(nil, `//saml:AttributeStatement`)[0] attrcache := map[string]*C.xmlNode{} for _, attr := range sourceAttributes { attrcache[attr.GetAttr("Name")] = attr attrcache[attr.GetAttr("FriendlyName")] = attr } //requestedAttributes := spmd.Query(nil, `./md:SPSSODescriptor/md:AttributeConsumingService[1]/md:RequestedAttribute[@isRequired=true()]`) requestedAttributes := spmd.Query(nil, `./md:SPSSODescriptor/md:AttributeConsumingService[1]/md:RequestedAttribute`) for _, requestedAttribute := range requestedAttributes { // for _, requestedAttribute := range sourceResponse.Query(nil, `//saml:Attribute`) { name := requestedAttribute.GetAttr("Name") friendlyname := requestedAttribute.GetAttr("FriendlyName") //nameFormat := requestedAttribute.GetAttr("NameFormat") //log.Println("requestedattribute:", name, nameFormat) // look for a requested attribute with the requested nameformat // TO-DO - xpath escape name and nameFormat // TO-Do - value filtering //attributes := sourceResponse.Query(sourceAttributes[0], `saml:Attribute[@Name="`+name+`" or @Name="`+friendlyname+`" or @FriendlyName="`+friendlyname+`"]`) //log.Println("src attrs", len(attributes), `saml:Attribute[@Name="`+name+`" or @Name="`+friendlyname+`" or @FriendlyName="`+friendlyname+`"]`) //attributes := sourceResponse.Query(sourceAttributes, `saml:Attribute[@Name="`+name+`"]`) attribute := attrcache[name] if attribute == nil { attribute = attrcache[friendlyname] if attribute == nil { continue } } // for _, attribute := range sourceAttributes { newAttribute := C.xmlAddChild(destinationAttributes, C.xmlDocCopyNode(attribute, response.doc, 2)) allowedValues := spmd.Query(requestedAttribute, `saml:AttributeValue`) allowedValuesMap := make(map[string]bool) for _, value := range allowedValues { allowedValuesMap[spmd.NodeGetContent(value)] = true } for _, valueNode := range sourceResponse.Query(attribute, `saml:AttributeValue`) { value := sourceResponse.NodeGetContent(valueNode) if len(allowedValues) == 0 || allowedValuesMap[value] { C.xmlAddChild(newAttribute, C.xmlDocCopyNode(valueNode, response.doc, 1)) } } // } } return }
func (destination *C.xmlNode) AddChild(source *C.xmlNode) (res *C.xmlNode) { res = C.xmlAddChild(destination, source) return }
// NewXpFromNode creates a new *Xp from a node (subtree) from another *Xp func NewXpFromNode(node *C.xmlNode) *Xp { xp := NewXp(nil) C.xmlAddChild((*C.xmlNode)(unsafe.Pointer(xp.doc)), C.xmlDocCopyNode(node, xp.doc, 1)) return xp }
func XmlAddChild(node unsafe.Pointer, child unsafe.Pointer) { C.xmlAddChild((*C.xmlNode)(node), (*C.xmlNode)(child)) }