public SecurityExpressionVisitor(QbservableServiceOptions serviceOptions) { this.options = serviceOptions.ExpressionOptions; this.context = serviceOptions.EvaluationContext; if (options.HasFlag(ExpressionOptions.AllowTypeTests) && options.HasFlag(ExpressionOptions.AllowExplicitConversions)) { context.EnsureHasKnownOperator("Cast"); context.EnsureHasKnownOperator("OfType"); } if (options.HasFlag(ExpressionOptions.AllowCatchBlocks)) { context.EnsureHasKnownOperator("Catch"); context.EnsureHasKnownOperator("OnErrorResumeNext"); context.EnsureHasKnownOperator("Retry"); } }
public static ExpressionNode Parse(string buffer, int startOffset, int endOffset, ExpressionOptions options, int baseOffset) { List <ExpressionNode> splitList = null; var nodes = new List <ExpressionNode> (); int lastNodeEnd = startOffset; for (int offset = startOffset; offset <= endOffset; offset++) { char c = buffer [offset]; //consume entities simply so the semicolon doesn't mess with list parsing //we don't need the value and the base XML editor will handle errors if (c == '&') { offset++; //FIXME: use proper entity name logic. this will do for now. var name = ReadName(buffer, ref offset, endOffset); if (offset > endOffset) { break; } if (buffer[offset] == ';') { continue; } c = buffer [offset]; } if ((options.HasFlag(ExpressionOptions.Lists) && c == ';') || (c == ',' && options.HasFlag(ExpressionOptions.CommaLists))) { CaptureLiteral(offset, nodes.Count == 0); if (splitList == null) { splitList = new List <ExpressionNode> (); } FlushNodesToSplitList(offset); lastNodeEnd = offset + 1; continue; } int possibleLiteralEndOffset = offset; ExpressionNode node; switch (c) { case '@': if (!TryConsumeParen()) { continue; } if (options.HasFlag(ExpressionOptions.Items)) { node = ParseItem(buffer, ref offset, endOffset, baseOffset); } else { node = new ExpressionError(baseOffset + offset, ExpressionErrorKind.ItemsDisallowed); } break; case '$': if (!TryConsumeParen()) { continue; } node = ParseProperty(buffer, ref offset, endOffset, baseOffset); break; case '%': if (!TryConsumeParen()) { continue; } if (options.HasFlag(ExpressionOptions.Metadata)) { node = ParseMetadata(buffer, ref offset, endOffset, baseOffset); } else { node = new ExpressionError(baseOffset + offset, ExpressionErrorKind.MetadataDisallowed); } break; default: continue; } CaptureLiteral(possibleLiteralEndOffset, false); lastNodeEnd = offset + 1; nodes.Add(node); if (node is ExpressionError) { //short circuit out without capturing the rest as text, since it's not useful return(CreateResult(offset)); } bool TryConsumeParen() { if (offset < endOffset && buffer[offset + 1] == '(') { offset++; offset++; return(true); } return(false); } } CaptureLiteral(endOffset + 1, nodes.Count == 0); return(CreateResult(endOffset)); void CaptureLiteral(int toOffset, bool isPure) { if (toOffset > lastNodeEnd) { string s = buffer.Substring(lastNodeEnd, toOffset - lastNodeEnd); nodes.Add(new ExpressionText(baseOffset + lastNodeEnd, s, isPure)); } } void FlushNodesToSplitList(int offset) { if (nodes.Count == 0) { splitList.Add(new ExpressionError(baseOffset + offset, ExpressionErrorKind.EmptyListEntry)); } else if (nodes.Count == 1) { splitList.Add(nodes [0]); nodes.Clear(); } else { var start = nodes [0].Offset; var l = nodes [nodes.Count - 1].End - start; splitList.Add(new Expression(start, l, nodes.ToArray())); nodes.Clear(); } } ExpressionNode CreateResult(int offset) { if (splitList != null) { FlushNodesToSplitList(offset); } if (splitList != null) { return(new ExpressionList(baseOffset + startOffset, endOffset - startOffset + 1, splitList.ToArray())); } if (nodes.Count == 0) { return(new ExpressionText(baseOffset + startOffset, "", true)); } if (nodes.Count == 1) { return(nodes [0]); } return(new Expression(baseOffset + startOffset, endOffset - startOffset + 1, nodes.ToArray())); } }
protected override Expression VisitBinary(BinaryExpression node) { if (!options.HasFlag(ExpressionOptions.AllowAssignments)) { switch (node.NodeType) { case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: case ExpressionType.AndAssign: case ExpressionType.Assign: case ExpressionType.DivideAssign: case ExpressionType.ExclusiveOrAssign: case ExpressionType.LeftShiftAssign: case ExpressionType.ModuloAssign: case ExpressionType.MultiplyAssign: case ExpressionType.MultiplyAssignChecked: case ExpressionType.OrAssign: case ExpressionType.PostDecrementAssign: case ExpressionType.PostIncrementAssign: case ExpressionType.PowerAssign: case ExpressionType.PreDecrementAssign: case ExpressionType.PreIncrementAssign: case ExpressionType.RightShiftAssign: case ExpressionType.SubtractAssign: case ExpressionType.SubtractAssignChecked: throw new ExpressionSecurityException("Assignments are not permitted."); } } return(base.VisitBinary(node)); }