Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Parsing expressions defined by end users
Message
De
29/04/2016 08:22:41
 
 
À
28/04/2016 05:43:24
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Versions des environnements
Visual FoxPro:
VFP 9 SP2
Divers
Thread ID:
01635536
Message ID:
01635641
Vues:
62
>In an application I'm working with, users can insert an expression to be used as a formula to evaluate parameter values. I'm relying on VFP's own parser to do this, but there are many issues involved, including stability and security issues.
>
>I'll need to strip down the parsing to only accept a much more confined set of functions, and to prevent access to variables and run-time objects (starting with _VFP and the likes). I know that this can be done and how to do it, but wonder if anybody has done this previously or know of anything that has been already developed and it is available. For instance, if you authorize your users to edit reports, how do you secure the expressions they insert as field values?

An update, with token typification
N: number
C: character
D: date
T: datetime
L: logical
U: NULL
O: operator
F: function / array
V: variable / work area
M: method / array
P: property / field
LOCAL loTokenizer AS Tokenizer
LOCAL lcToken AS String
LOCAL lcTest AS String

m.loTokenizer = CREATEOBJECT("Tokenizer")
m.loTokenizer.AddTokenPattern("(\+|-)?(\.\d+|\d+(\.\d+)?)((e|E)(\+|-)?\d+)*", "N")
m.loTokenizer.AddTokenPattern('("[^"]*"|' + "'[^']*'|\[[^\[]*\])", "C")
m.loTokenizer.AddTokenPattern("{\^\d{1,4}-\d{1,2}-\d{1,2}}", "D")
m.loTokenizer.AddTokenPattern("{\^\d{1,4}-\d{1,2}-\d{1,2}\s+\d{1,2}:\d{1,2}(:\d{1,2})?(\s+?([aA]|[pP])[mM]?)?}", "T")
m.loTokenizer.AddTokenPattern("\.([tT]|[fF])\.", "L")
m.loTokenizer.AddTokenPattern("\.[nN][uU][lL]{2}\.", "U")
m.loTokenizer.AddTokenPattern("(==|!=|<=|>=|<>|!|=|>|<|\+|-|\*|\/|%|,|\)|\(|\$|[aA][nN][dD]|[oO][rR]|[nN][oO][tT])", "O")
m.loTokenizer.AddTokenPattern("[a-zA-Z][a-zA-Z0-9_]*\s*(\(|\[)", "F")
m.loTokenizer.AddTokenPattern("([mM]\.)?[a-zA-Z_][a-zA-Z0-9_]*", "V")
m.loTokenizer.AddTokenPattern("\.\s*[a-zA-Z_][a-zA-Z0-9_]*\s*(\(|\[)", "M")
m.loTokenizer.AddTokenPattern("\.\s*[a-zA-Z_][a-zA-Z0-9_]*", "P")

CLEAR
ACCEPT "Test Expression: " TO m.loTest

IF !m.loTokenizer.GetTokens(m.loTest)

	? "Error @" + m.loTokenizer.ErrorPointer

ELSE

	? "Tokens found:"
	FOR EACH m.loToken IN m.loTokenizer.Tokens
		? m.loToken.Type,m.loToken.Value
	ENDFOR

ENDIF

DEFINE CLASS Tokenizer AS Custom

	RegExpr = .NULL.
	TokenPatterns = .NULL.
	Tokens = .NULL.
	ErrorPointer = ""
	
	FUNCTION Init

		IF !"\_REGEXP.VCX" $ SET("Classlib")
			SET CLASSLIB TO (ADDBS(HOME(1)) + "ffc\_regexp.vcx") ADDITIVE
		ENDIF

		This.RegExpr = CREATEOBJECT("_regexp")
		
		This.TokenPatterns = CREATEOBJECT("collection")
		This.Tokens = CREATEOBJECT("collection")

	ENDFUNC

	FUNCTION AddTokenPattern (tcPattern AS String, tcType AS String)
	
		LOCAL loTokenType AS TokenType
		
		m.loTokenType = CREATEOBJECT("TokenType", IIF(LEFT(m.tcPattern,1) != "^", "^", "") + m.tcPattern, m.tcType)

		This.TokenPatterns.Add(m.loTokenType)

	ENDFUNC

	FUNCTION GetTokens (tcExpression AS String)

		LOCAL lcExpression AS String
		LOCAL loTokenType AS TokenType
		LOCAL lnTokenPattern AS Integer
		LOCAL lcToken AS String
		LOCAL loToken AS Token

		m.lcExpression = ALLTRIM(m.tcExpression,0," ",CHR(13),CHR(10),CHR(9))
		This.Tokens.Remove(-1)
		This.ErrorPointer = ""

		DO WHILE !EMPTY(m.lcExpression)

			m.lcToken = .NULL.

			FOR m.lnTokenPattern = 1 TO This.TokenPatterns.Count
			
				m.loTokenType = This.TokenPatterns.Item(m.lnTokenPattern)
					
				This.RegExpr.Clear()
				This.RegExpr.Pattern = m.loTokenType.Pattern

				IF This.RegExpr.Execute(m.lcExpression,.F.) = 1

					m.lcToken = This.RegExpr.Matches[1,2]
					m.lcExpression = LTRIM(SUBSTR(m.lcExpression,LEN(m.lcToken) + 1),0," ",CHR(13),CHR(10),CHR(9))

					m.loToken = CREATEOBJECT("Token", m.lcToken, m.loTokenType.Type)

					This.Tokens.Add(m.loToken)
					EXIT

				ENDIF
			ENDFOR

			IF ISNULL(m.lcToken)
				This.ErrorPointer = m.lcExpression
				RETURN .F.
			ENDIF
		ENDDO

		RETURN .T.
	ENDFUNC

ENDDEFINE

DEFINE CLASS TokenType AS Custom

	Pattern = ""
	Type = ""

	FUNCTION Init (tcPattern AS String, tcType AS String)
	
		This.Pattern = m.tcPattern
		This.Type = m.tcType
	
	ENDFUNC

ENDDEFINE

DEFINE CLASS Token AS Custom

	Value = ""
	Type = ""

	FUNCTION Init (tcValue AS String, tcType AS String)
	
		This.Value = m.tcValue
		This.Type = m.tcType

	ENDFUNC

ENDDEFINE
----------------------------------
António Tavares Lopes
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform