예제 #1
0
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
}
예제 #2
0
// 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
}
예제 #3
0
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
}
예제 #4
0
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
}
예제 #5
0
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
}
예제 #6
0
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
}
예제 #7
0
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
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
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
}
예제 #11
0
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
}
예제 #12
0
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
}
예제 #13
0
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
}
예제 #14
0
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
}
예제 #15
0
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
}
예제 #16
0
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
}
예제 #17
0
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
}
예제 #18
0
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
}
예제 #19
0
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
}
예제 #20
0
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
}
예제 #21
0
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
}
예제 #22
0
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
}
예제 #23
0
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
}
예제 #24
0
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
}
예제 #25
0
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
}
예제 #26
0
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
}
예제 #27
0
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
}
예제 #28
0
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
}
예제 #29
0
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
}
예제 #30
0
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
}