public static CompilerError ValidateView(ref string expression, KEntity kentity) { var pageClassResult = Helper.Constants.ViewClassRegularExpression.Matches(expression); if (pageClassResult != null && pageClassResult.Count > 0) { foreach (var page in pageClassResult.ToList()) { var groupparam = page.Groups[2].Value?.Trim('(', ')'); if (!string.IsNullOrEmpty(groupparam)) { var partialViewParams = groupparam.Split(','); var viewName = partialViewParams[0]?.Trim('\''); if (kentity.Classes.Any(x => x.ClassType == KClassType.BaseClass && x.Description != null && x.Description.ToLower() == viewName.ToLower() && x.Name != null)) { expression = expression.Replace(page.Groups[1].Value, kentity.Classes.First(x => x.ClassType == KClassType.BaseClass && x.Description != null && x.Description.ToLower() == viewName.ToLower() && x.Name != null).Name); } else { return(CompileResultHelper.GetCompileError(string.Format(ErrorCodeConstants.UnrecognizedView, viewName))); } } } } return(null); }
public static CompilerError ValidatePartialView(ref string expression, List <ResourceItemMeta> resources) { var pageClassResult = Helper.Constants.PartialPageRegularExpression.Matches(expression); if (pageClassResult != null && pageClassResult.Count > 0) { foreach (var page in pageClassResult.ToList()) { var groupparam = page.Groups[1].Value?.Trim('(', ')'); if (!string.IsNullOrEmpty(groupparam)) { var partialViewParams = groupparam.Split(','); var viewName = partialViewParams[0]?.Trim('\''); if (!resources.Any(x => x.PageType == Models.Project.KitsunePageType.PARTIAL && x.SourcePath.ToLower() == viewName.ToLower())) { return(CompileResultHelper.GetCompileError(string.Format(ErrorCodeConstants.UnrecognizedView, viewName))); } } } } return(null); }
/// <summary> /// Validate k-tags and expressions in the document. /// </summary> /// <param name="document">Incoming document</param> /// <param name="request">Incoming request</param> /// <param name="compileErrors">list of errors during compile</param> /// <param name="kentity">project language</param> /// <param name="customVariables">custom variables found during compilation</param> /// <param name="rootUrl">root url</param> /// <param name="filePath">file path</param> public void ValidateDocument(HtmlDocument document, CompileResourceRequest request, List <CompilerError> compileErrors, KEntity kentity, Dictionary <string, int> customVariables, string rootUrl, string filePath, GetProjectDetailsResponseModel projectDetails, List <KEntity> componentsEntity = null) { Dictionary <string, bool> objectNamesValidated = new Dictionary <string, bool>(); Dictionary <string, string> classNameAlias = new Dictionary <string, string>(); Dictionary <int, string> classNameAliasLevel = new Dictionary <int, string>(); List <MatchNode> objectNamesToValidate = new List <MatchNode>(); entities.Add(kentity.EntityName, kentity); defaultEntity = kentity.EntityName; if (componentsEntity != null && componentsEntity.Any()) { foreach (var comEntity in componentsEntity) { if (!entities.Keys.Contains(comEntity.EntityName)) { entities.Add(comEntity.EntityName, comEntity); } } } var baseClassList = entities.SelectMany(x => x.Value?.Classes?.Where(y => y.ClassType == KClassType.BaseClass)?.ToList()); HtmlNode node = document.DocumentNode; List <string> dynamicTagDescriptors = GetDynamicTagDescriptors(typeof(LanguageAttributes)); int level = 0; while (node != null) { if (node.NodeType == HtmlNodeType.Element) { var dynamicAttributes = node.Attributes.Where(x => dynamicTagDescriptors.Contains(x.Name.ToLower())); for (int i = 0; i < dynamicAttributes.Count(); i++) { if (!string.IsNullOrEmpty(dynamicAttributes.ElementAt(i).Value)) { Processor processor = ProcessorFactory.GetProcessor(dynamicAttributes.ElementAt(i).Name); processor.ProcessNode(request, compileErrors, customVariables, rootUrl, filePath, classNameAlias, classNameAliasLevel, level, node, dynamicAttributes.ElementAt(i), objectNamesToValidate, this); } //k-partial k-norepeat attribute can be empty else if (dynamicAttributes.ElementAt(i).Name?.ToLower() != LanguageAttributes.KPartial.GetDescription()?.ToLower() && dynamicAttributes.ElementAt(i).Name?.ToLower() != LanguageAttributes.KNoRepeat.GetDescription()?.ToLower()) { compileErrors.Add(CompileResultHelper.GetCompileError(string.Format(ErrorCodeConstants.InvalidKitsuneTagValue, dynamicAttributes.ElementAt(i).Name, dynamicAttributes.ElementAt(i).Line, dynamicAttributes.ElementAt(i).LinePosition))); } } if (node.Name.Equals(LanguageAttributes.KScript.GetDescription(), StringComparison.InvariantCultureIgnoreCase)) { Processor processor = ProcessorFactory.GetProcessor(node.Name.ToLower()); processor.ProcessNode(request, compileErrors, customVariables, rootUrl, filePath, classNameAlias, classNameAliasLevel, level, node, null, objectNamesToValidate, this); } } if (node.HasChildNodes) { node = node.FirstChild; level++; } else { ValidateExpressions(compileErrors, entities, objectNamesValidated, classNameAlias, baseClassList, node, objectNamesToValidate, customVariables, projectDetails); if (node.NextSibling != null) { node = node.NextSibling; ClearNameAliases(classNameAlias, classNameAliasLevel, level); } else { while (node.ParentNode != null && node.ParentNode.NextSibling == null) { node = node.ParentNode; ValidateExpressions(compileErrors, entities, objectNamesValidated, classNameAlias, baseClassList, node, objectNamesToValidate, customVariables, projectDetails); level--; ClearNameAliases(classNameAlias, classNameAliasLevel, level); } node = node?.ParentNode; if (node != null) { ValidateExpressions(compileErrors, entities, objectNamesValidated, classNameAlias, baseClassList, node, objectNamesToValidate, customVariables, projectDetails); } node = node?.NextSibling; level--; ClearNameAliases(classNameAlias, classNameAliasLevel, level); } } } }
/// <summary> /// Validate objects used in expressions are valid. /// </summary> /// <param name="compileErrors"></param> /// <param name="kentity"></param> /// <param name="objectNamesValidated"></param> /// <param name="classNameAlias"></param> /// <param name="baseClassList"></param> /// <param name="node"></param> private void ValidateExpressions(List <CompilerError> compileErrors, Dictionary <string, KEntity> entities, Dictionary <string, bool> objectNamesValidated, Dictionary <string, string> classNameAlias, IEnumerable <KClass> baseClassList, HtmlNode node, List <MatchNode> objectNamesToValidate, Dictionary <string, int> customVariables, GetProjectDetailsResponseModel projectDetails) { if (node.NodeType != HtmlNodeType.Element) { return; } int lineNo = 0; CompilerError viewExist = null; CompilerError partialViewExist = null; string viewExpression = string.Empty; foreach (string line in node.OuterHtml.Split("\n")) { List <MatchNode> expressionNodes = HtmlHelper.GetExpressionFromElement(line, node.Line + lineNo); foreach (var expression in expressionNodes) { try { viewExpression = expression.Value; //View() function validation viewExist = KitsuneCompiler.ValidateView(ref viewExpression, entities.First().Value); if (viewExist != null) { viewExist.LineNumber = expression.Line; viewExist.LinePosition = expression.Column; compileErrors.Add(viewExist); } //Partial() view function validation partialViewExist = KitsuneCompiler.ValidatePartialView(ref viewExpression, projectDetails.Resources); if (partialViewExist != null) { partialViewExist.LineNumber = expression.Line; partialViewExist.LinePosition = expression.Column; compileErrors.Add(partialViewExist); } foreach (string raw_obj in Parser.GetObjects(viewExpression)) { string obj = raw_obj.Replace("[[", "").Replace("]]", "").ToLower(); if (customVariables.ContainsKey(obj)) { continue; } else { objectNamesToValidate.Add(new MatchNode { Value = obj, Line = node.Line + lineNo, Column = line.IndexOf(obj) }); } } } catch (Exception ex) { compileErrors.Add(CompileResultHelper.GetCompileError(ex.Message, node.Line, node.LinePosition)); continue; } } lineNo++; } foreach (MatchNode obj in objectNamesToValidate) { Boolean isAlias = false; string objectName = obj.Value.ToLower(); if ((classNameAlias.ContainsKey(objectName) && classNameAlias[objectName] == "") || customVariables.ContainsKey(objectName)) { continue; } string baseClassName = objectName.Split('.')[0]; while (baseClassName != "kresult" && baseClassName != "search" && classNameAlias.ContainsKey(baseClassName)) { int index = objectName.IndexOf('.'); objectName = classNameAlias[baseClassName] + (index >= 0 ? objectName.Substring(index) : ""); isAlias = true; baseClassName = objectName.Split('.')[0]; } if (objectNamesValidated.ContainsKey(objectName)) { if (!objectNamesValidated[objectName] && !isAlias) { compileErrors.Add(CompileResultHelper.GetCompileError(String.Format(ErrorCodeConstants.UnrecognizedType, objectName), obj.Line, obj.Column)); } } else { string[] objectPathArray = objectName.ToLower().Split('.'); string basePropertyName = objectPathArray[0]; var baseClass = baseClassList.FirstOrDefault(x => x.Name?.ToLower() == basePropertyName); if (baseClass != null) { var baseEntity = entities.Keys.Contains(basePropertyName) ? entities[basePropertyName] : null; if (baseEntity == null) { baseEntity = entities.First().Value; } IEnumerable <CompilerError> errorList = ValidateExpression(objectPathArray, 1, basePropertyName, PropertyType.obj, obj.Line, obj.Column, baseEntity); if (errorList.Count() > 0) { compileErrors.AddRange(errorList); objectNamesValidated.Add(objectName, false); } else { objectNamesValidated.Add(objectName, true); } } else if (!ValidObjects.Contains(basePropertyName.Trim('[').Trim(']')) && ((basePropertyName.StartsWith("kresult") && !classNameAlias.ContainsKey("kresult")) || !basePropertyName.StartsWith("kresult"))) { compileErrors.Add(CompileResultHelper.GetCompileError(String.Format(ErrorCodeConstants.UnrecognizedClass, basePropertyName), obj.Line, obj.Column)); //objectNamesValidated.Add(objectName, false); } } } //InnerText returns text from inner html tags, need to clear so we don't run parser again. DOM is unaffected by this. node.InnerHtml = ""; objectNamesToValidate.Clear(); }
public static CompileResult CompileHTML(CompileResourceRequest req, out HtmlDocument documentRef, GetProjectDetailsResponseModel projectDetails, KEntity kentity, GetPartialPagesDetailsResponseModel partialPages = null, bool subsequentCompilation = false, List <KLanguageModel> componentEntities = null) // partialPage is required only for the publish/preview { ///TODO : Handle the kitsune-settings.xml saperatly documentRef = GetDocumentObject(); var filePath = req.SourcePath.Trim('/'); if (!string.IsNullOrEmpty(req.FileContent)) { HtmlDocument document; List <CompilerError> nfUXErrors = new List <CompilerError>(); Dictionary <string, int> customVariables = new Dictionary <string, int>(); string rootUrl; DocumentPreprocessor.PreprocessDocument(req, kentity, filePath, out document, nfUXErrors, out rootUrl); documentRef = document; /* * if (document.ParseErrors.Count() > 0) * { * return CompileResultHelper.GetCompileResult(nfUXErrors, req.SourcePath, false); * } */ req.UrlPattern = req.SourcePath; //assigning default urlpattern if (!req.IsStatic) { if (kentity == null) { return(CompileResultHelper.GetErrorCompileResult("Schema not found for this project.", req.SourcePath)); } else if (kentity.EntityName == null) { kentity.EntityName = Constants.KPayDefaultSchema; } HtmlDocument documentClone = GetDocumentObject(); documentClone.LoadHtml(document.DocumentNode.OuterHtml); DocumentValidator validator = new DocumentValidator(); validator.ValidateDocument(documentClone, req, nfUXErrors, kentity, customVariables, rootUrl, filePath, projectDetails, componentEntities?.Select(x => x.Entity)?.ToList()); if (nfUXErrors.Count == 0) { if (req.IsPublish) { var csrfPresent = Constants.CSRFRegularExpression.IsMatch(document.DocumentNode.OuterHtml); UpdateForPublish(ref document, req, kentity, nfUXErrors, customVariables, projectDetails, partialPages, componentEntities, csrfPresent); if (req.PageType != Models.Project.KitsunePageType.PARTIAL) { HandleScriptInjection(document, req, kentity, rootUrl, projectDetails, csrfPresent); } } } /* * KitsunePage myPage = (new NewRootNodeProcessor()).Process(document.DocumentNode.OuterHtml); * var jsonSerializeSettings = new JsonSerializerSettings(); * jsonSerializeSettings.TypeNameHandling = TypeNameHandling.Objects; * string output = JsonConvert.SerializeObject(myPage, Formatting.None, jsonSerializeSettings); * //KitsunePage myNewPage = JsonConvert.DeserializeObject<KitsunePage>(output, jsonSerializeSettings); */ } UpdatePathsForPreview(req, document); if (nfUXErrors.Count > 0) { return new CompileResult { Success = false, ErrorMessages = nfUXErrors, PageName = req.SourcePath } } ; else { return new CompileResult { Success = true, CompiledString = document.DocumentNode.OuterHtml.ToString(), ErrorMessages = nfUXErrors, PageName = req.SourcePath, CustomVariables = customVariables } }; } return(new CompileResult { Success = false, ErrorMessages = new List <CompilerError> { new CompilerError { Message = "Input should not be empty" } }, PageName = req.SourcePath, }); }