func replace_Regexp(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { regexp := args[0].(*rubex.Regexp) scope.Value = regexp.GsubFunc(scope.Value.(string), func(match string, captures map[string]string) string { usesGlobal := (ctx.GetEnv("use_global_replace_vars") == "true") for name, capture := range captures { if usesGlobal { //println("setting $", name, "to", capture) ctx.SetEnv(name, capture) } ctx.SetVar(name, capture) } replacementScope := &Scope{Value: match} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(replacementScope, child) } //println(ins.String()) //println("Replacement:", replacementScope.Value.(string)) return ctx.GetInnerReplacer().GsubFunc(replacementScope.Value.(string), func(_ string, numeric_captures map[string]string) string { capture := numeric_captures["1"] var val string if usesGlobal { val = ctx.GetEnv(capture) } else { val = ctx.GetVar(capture).(string) } return val }) }) returnValue = scope.Value return }
// Buggy, look at inject_at_v2 for fixed version. // kept for backwards compatibility. func inject_at_Position_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) position := args[0].(Position) input := args[1].(string) nodes, err := node.Coerce(input) if err == nil { for _, n := range nodes { MoveFunc(n, node, position) } } if len(nodes) > 0 { first := nodes[0] if first.NodeType() == xml.XML_ELEMENT_NODE { // successfully ran scope returnValue = "true" ns := &Scope{Value: first} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } } } else { returnValue = "false" } return }
func xml_Text_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { input := scope.Value.(string) doc, err := xml.Parse([]byte(input), nil, nil, xml.DefaultParseOption, nil) if err != nil { LogEngineError(ctx, "xml err: "+err.Error()) returnValue = "false" return } if doc == nil { LogEngineError(ctx, "xml err: nil doc") returnValue = "false" return } ctx.AddMemoryObject(doc) ctx.CurrentDoc = doc ns := &Scope{Value: doc} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } scope.Value = doc.String() ctx.CurrentDoc = nil returnValue = scope.Value //doc.Free() return }
func html_doc_Text_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { ctx.HtmlParsed = true inputEncoding := args[0].(string) inputEncodingBytes := []byte(inputEncoding) outputEncoding := args[1].(string) outputEncodingBytes := []byte(outputEncoding) input := scope.Value.(string) doc, err := html.Parse([]byte(input), inputEncodingBytes, nil, html.DefaultParseOption, outputEncodingBytes) if err != nil { LogEngineError(ctx, "html_doc err: "+err.Error()) returnValue = "false" return } if doc == nil { LogEngineError(ctx, "html_doc err: nil doc") returnValue = "false" return } ctx.AddMemoryObject(doc) ctx.CurrentDoc = doc ns := &Scope{Value: doc} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } if err := doc.SetMetaEncoding(outputEncoding); err != nil { //ctx.Log.Warn("executing html:" + err.Error()) } scope.Value = doc.String() ctx.CurrentDoc = nil returnValue = scope.Value //doc.Free() return }
func html_fragment_doc_Text_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { ctx.HtmlParsed = true inputEncoding := args[0].(string) inputEncodingBytes := []byte(inputEncoding) outputEncoding := args[1].(string) outputEncodingBytes := []byte(outputEncoding) input := scope.Value.(string) fragment, err := html.ParseFragment([]byte(input), inputEncodingBytes, nil, html.DefaultParseOption, outputEncodingBytes) if err != nil { LogEngineError(ctx, "html_fragment err: "+err.Error()) returnValue = "false" return } if fragment == nil { LogEngineError(ctx, "html_fragment err: nil fragment") returnValue = "false" return } ctx.AddMemoryObject(fragment.Node.MyDocument()) ctx.CurrentDoc = fragment ns := &Scope{Value: fragment} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } //output is always utf-8 because the content is internal to Doc. scope.Value = ns.Value.(*xml.DocumentFragment).String() //TODO(NOJ): Why are we setting currentdoc to nil instead of what it used to be? ctx.CurrentDoc = nil returnValue = scope.Value //fragment.Node.MyDocument().Free() return }
func header_comp_v1_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { header := scope.Value.(string) attr := args[0].(string) headersRegex := regexp.MustCompile(`(?m)^(\S+?):\s+(.+?)$`) headerParsed := headersRegex.FindStringSubmatch(header) replaceMe := "" if len(headerParsed) != 3 { return "" } ns := &Scope{} switch attr { case "name": replaceMe = headerParsed[1] case "value": replaceMe = headerParsed[2] if strings.HasSuffix(replaceMe, "\r") { replaceMe = replaceMe[:len(replaceMe)-1] } case "this": replaceMe = header } ns.Value = replaceMe if ns.Value != "" { for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } } // set the value of the container scope to the header replaced with the new ns.Value scope.Value = strings.Replace(header, replaceMe, ns.Value.(string), -1) // return the resultant ns.Value returnValue = ns.Value return }
func parse_headers_v1(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { httpStr := scope.Value.(string) // remove \r (will add them back later) httpStr = strings.Replace(httpStr, "\r", "", -1) headersRegex := regexp.MustCompile(`(?m)^\S+?:\s?[^\n]+`) // replace headers with result of eval'd instructions newHttpStr := headersRegex.ReplaceAllStringFunc(httpStr, func(header string) string { ns := &Scope{Value: header} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } return ns.Value.(string) }) // remove empty lines (in the case that a header is blanked) replaceEmptyLinesRegex := regexp.MustCompile(`\n+`) newHttpStr = replaceEmptyLinesRegex.ReplaceAllString(newHttpStr, "\n") // trim leading/trailing spaces (e.g. if last header is removed) newHttpStr = strings.TrimRight(newHttpStr, "\r\n") // replace all \n with \r\n scope.Value = strings.Replace(newHttpStr, "\n", "\r\n", -1) // return the entire http returnValue = scope.Value return }
func replace_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { ts := &Scope{Value: ""} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } scope.Value = strings.Replace(scope.Value.(string), args[0].(string), ts.Value.(string), -1) return }
func comp_v1_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { component := args[0].(string) u := scope.Value.(*url.URL) ns := &Scope{} switch component { case "scheme": ns.Value = u.Scheme case "host": ns.Value = u.Host case "path": ns.Value = u.Path case "fragment": ns.Value = u.Fragment case "userinfo": if u.User != nil { ns.Value = u.User.String() } else { ns.Value = "" } } if ns.Value != nil { for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } // write value back to URL (as long as it's a string) if newVal, ok := ns.Value.(string); ok { switch component { case "scheme": u.Scheme = newVal case "host": u.Host = newVal case "path": u.Path = newVal case "fragment": u.Fragment = newVal case "userinfo": if newVal == "" { // remove the userinfo u.User = nil } else { info := strings.Split(newVal, ":") newUserinfo := url.User(info[0]) if len(info) == 2 { newUserinfo = url.UserPassword(info[0], info[1]) } u.User = newUserinfo } } returnValue = newVal } } return }
func time_(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { start := time.Now() for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(scope, child) } duration := time.Since(start) // I only seem to get 6 significant digits, so output in microseconds returnValue = strconv.FormatInt(duration.Nanoseconds()/1000, 10) + "µs" return }
func name(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) ts := &Scope{Value: node.Name()} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } node.SetName(ts.Value.(string)) returnValue = ts.Value.(string) return }
func export_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { val := make([]string, 2) val[0] = args[0].(string) ts := &Scope{Value: ""} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } val[1] = ts.Value.(string) ctx.AddExport(val) return }
func else_(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { returnValue = "false" if ctx.ShouldContinue() { ctx.SetShouldContinue(false) for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(scope, child) } returnValue = "true" } return }
func inner_text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) ts := &Scope{Value: node.Content()} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } val := ts.Value.(string) node.SetInnerHtml(val) returnValue = val return }
func warn_v1_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { var msg string if loc := ctx.Env[isUserCalledEnvKey]; loc != "" { msg = fmt.Sprintf("%s: %s", loc, args[0].(string)) } else { msg = fmt.Sprintf("%s:%d: %s", ctx.Filename, ins.IGetLineNumber(), args[0].(string)) } LogEngineError(ctx, msg) ctx.Debugger.SendWarning(msg) ctx.Warnings++ returnValue = fmt.Sprintf("%d", ctx.Warnings) return }
func dup(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) newNode := node.Duplicate(1) if newNode.NodeType() == xml.XML_ELEMENT_NODE { MoveFunc(newNode, node, AFTER) } ns := &Scope{Value: newNode} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } return }
func insert_at_Position_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) position := args[0].(Position) tagName := args[1].(string) element := node.MyDocument().CreateElementNode(tagName) MoveFunc(element, node, position) ns := &Scope{Value: element} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } returnValue = "true" return }
func with_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { returnValue = "false" if ctx.ShouldContinue() { if args[0].(string) == ctx.MatchTarget() { for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(scope, child) } ctx.SetShouldContinue(false) returnValue = "true" } } return }
func not_Regexp(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { returnValue = "false" if ctx.ShouldContinue() { //println(matcher.MatchAgainst, matchWith) if !(args[0].(*rubex.Regexp)).Match([]uint8(ctx.MatchTarget())) { ctx.SetShouldContinue(false) for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(scope, child) } returnValue = "true" } } return }
func value(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) ts := &Scope{Value: node.Content()} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } val := ts.Value.(string) if attr, ok := node.(*xml.AttributeNode); ok { attr.SetValue(val) } returnValue = val return }
func attribute_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) name := args[0].(string) attr := node.Attribute(name) if attr == nil { node.SetAttr(name, "") attr = node.Attribute(name) } if attr != nil { as := &Scope{Value: attr} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(as, child) } if attr.Value() == "" { attr.Remove() } returnValue = "true" } return }
func param_v1_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { parameter := args[0].(string) u := scope.Value.(*url.URL) params := u.Query() ns := &Scope{Value: params.Get(parameter)} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } // if child instructions result in a string: if newVal, ok := ns.Value.(string); ok { // write the ns.Value back to params params.Set(parameter, newVal) // write params back to u.RawQuery u.RawQuery = params.Encode() returnValue = newVal } return }
func wrap_text_children_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { returnValue = "false" node := scope.Value.(xml.Node) if textNodes, err := node.SearchByDeadline("./text()", &ctx.Deadline); err == nil { tagName := args[0].(string) tag := fmt.Sprintf("<%s />", tagName) for index, textNode := range textNodes { textNode.Wrap(tag) parent := textNode.Parent() if parent == nil { continue } ns := &Scope{parent, index} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } } } return }
func fetch_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { node := scope.Value.(xml.Node) xpathStr := args[0].(string) expr := ctx.GetXpathExpr(xpathStr) if expr == nil { returnValue = "false" return } nodes, err := node.SearchByDeadline(expr, &ctx.Deadline) if err == nil && len(nodes) > 0 { node := nodes[0] returnValue = node.String() } if returnValue == nil { returnValue = "" } if ins.INumChildren() > 0 { ts := &Scope{Value: returnValue} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } returnValue = ts.Value } return }
func json_to_xml_v1(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { // unmarshal the json jsonSrc := scope.Value.(string) var jsonVal interface{} err := json.Unmarshal([]byte(jsonSrc), &jsonVal) if err != nil { // invalid JSON -- log an error message and keep going LogEngineError(ctx, "json_decoding err: "+err.Error()) returnValue = "null" return } // convert to an xml doc and run the supplied block on it newDoc := xml.CreateEmptyDocument(nil, nil) ctx.AddMemoryObject(newDoc) jsonNodes := json_to_node(jsonVal, newDoc) // put the jsonNodes under a new root node to get the xpath searches to be correctly scoped jsonRoot := newDoc.CreateElementNode("json") jsonRoot.AddChild(jsonNodes) newScope := &Scope{Value: jsonRoot} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(newScope, child) } // convert back to native Go data structures and re-marshal jsonVal = node_to_json(jsonRoot.FirstChild()) jsonOut, err := json.MarshalIndent(jsonVal, "", " ") if err != nil { // invalid JSON -- log an error message and keep going LogEngineError(ctx, "json_encoding err: "+err.Error()) returnValue = "null" return } scope.Value = string(jsonOut) returnValue = string(jsonOut) return }
func url_v1_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { urlStr := args[0].(string) urlParsed, err := url.Parse(urlStr) if err != nil { LogEngineError(ctx, "url parse err: "+err.Error()) returnValue = "false" return } ns := &Scope{Value: urlParsed} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } // return the modified URL string (allow strings as well?) if urlVal, isURL := ns.Value.(*url.URL); isURL { returnValue = urlVal.String() } else if urlStr, isStr := ns.Value.(string); isStr { returnValue = urlStr } return }
func match_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { // Setup stacks against := args[0].(string) ctx.PushMatchStack(against) ctx.PushShouldContinueStack(true) // Run children for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(scope, child) } if ctx.ShouldContinue() { returnValue = "false" } else { returnValue = "true" } // Clear ctx.PopShouldContinueStack() ctx.PopMatchStack() return }
func capture_Regexp(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { regexp := args[0].(*rubex.Regexp) scope.Value = regexp.GsubFunc(scope.Value.(string), func(match string, captures map[string]string) string { usesGlobal := (ctx.GetEnv("use_global_replace_vars") == "true") for name, capture := range captures { if usesGlobal { ctx.SetEnv(name, capture) } ctx.SetVar(name, capture) } replacementScope := &Scope{Value: match} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(replacementScope, child) } return replacementScope.Value.(string) }) returnValue = scope.Value return }
func base64_v1_Text_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { method := args[0].(string) str := args[1].(string) ns := &Scope{Value: str} switch method { case "decode": data, err := base64.StdEncoding.DecodeString(str) if err != nil { LogEngineError(ctx, "String decode error: "+err.Error()) ns.Value = "" } else { ns.Value = string(data) } case "encode": data := []byte(str) ns.Value = base64.StdEncoding.EncodeToString(data) } for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ns, child) } returnValue = ns.Value return }
func var_Text_Text(ctx *EngineContext, scope *Scope, ins protoface.Instruction, args []interface{}) (returnValue interface{}) { ctx.SetEnv(args[0].(string), args[1].(string)) returnValue = args[1].(string) if ins.INumChildren() > 0 { ts := &Scope{Value: returnValue} for i := 0; i < ins.INumChildren(); i++ { child := ins.IGetNthChild(i) ctx.RunInstruction(ts, child) } returnValue = ts.Value ctx.SetEnv(args[0].(string), returnValue.(string)) } return }