public static string RelativeLink(MethodInfo method, params object[] args) { APIEndpoint endpoint = find(method); var path = endpoint.GetFormattablePath(); return(string.Format(path, args)); }
static void buildEndpoints() { Endpoints = new Dictionary <string, List <APIEndpoint> >(); var q = from t in Assembly.GetExecutingAssembly().GetTypes() where t.IsClass && t.IsSubclassOf(typeof(APIBase)) select t; foreach (var module in q) { var mod = new APIModule(); mod.Name = module.GetCustomAttribute <NameAttribute>()?.Text ?? module.Name; mod.Summary = module.GetCustomAttribute <SummaryAttribute>()?.Text ?? null; mod.Type = module; foreach (var prec in module.GetCustomAttributes <APIPrecondition>()) { mod.Preconditions.Add(prec); } var methods = module.GetMethods(BindingFlags.Public | BindingFlags.Instance); foreach (var func in methods) { var method = func.GetCustomAttribute <MethodAttribute>(); var path = func.GetCustomAttribute <PathAttribute>(); if (method == null || path == null) { continue; } var name = func.GetCustomAttribute <NameAttribute>(); var api = new APIEndpoint(method.Method.Method, path); var regexs = func.GetCustomAttributes <RegexAttribute>(); foreach (var keypair in regexs) { api.Regexs[keypair.Name] = keypair.Regex; } api.Name = name?.Text ?? func.Name; api.Summary = func.GetCustomAttribute <SummaryAttribute>()?.Text ?? null; api.Function = func; api.Module = mod; mod.Endpoints.Add(api); var prec = api.Function.GetCustomAttributes <APIPrecondition>().ToList(); api.Preconditions = prec.ToArray(); if (Endpoints.ContainsKey(api.Method)) { Endpoints[api.Method].Add(api); } else { Endpoints.Add(api.Method, new List <APIEndpoint>() { api }); } } Modules.Add(mod); } foreach (var keypair in Endpoints) { Program.LogMsg($"Loaded {keypair.Value.Count} {keypair.Key} endpoints", source: "API", sev: LogSeverity.Debug); } }
public static T Get <T>(APIEndpoint command) where T : APIPrecondition { foreach (var p in command.Preconditions) { if (p is T) { return(p as T); } } return(null); }
public ErrorItem(APIEndpoint e, string r) { endpoint = e; reason = r; }
ParseResult kowalski_analysis(APIEndpoint cmd, Match rgxMatch) { context.Endpoint = cmd; // temporary for PathRegex int weight = 0; var cnt = System.Activator.CreateInstance(cmd.Module.Type, context); var commandBase = (APIBase)cnt; var preconditions = new List <APIPrecondition>(); var final = new ParseResult(cmd); final.CommandBase = commandBase; var ORS = new Dictionary <string, List <PreconditionResult> >(); var ANDS = new Dictionary <string, List <PreconditionResult> >(); var building = new List <APIPrecondition>(); building.AddRange(cmd.Preconditions); Type parent = commandBase.GetType(); do { var attrs = parent.GetCustomAttributes <APIPrecondition>(); building.AddRange(attrs); parent = parent.BaseType; } while (parent != null); building.Reverse(); foreach (var nextThing in building) { var previousThing = preconditions.FirstOrDefault(x => x.TypeId == nextThing.TypeId); if (previousThing != null) { if (!previousThing.CanChildOverride(nextThing)) { continue; } preconditions.Remove(previousThing); } preconditions.Add(nextThing); } foreach (var pred in preconditions) { if (string.IsNullOrWhiteSpace(pred.OR)) { ANDS.TryAdd(pred.AND, new List <PreconditionResult>()); } else { ORS.TryAdd(pred.OR, new List <PreconditionResult>()); if (!string.IsNullOrWhiteSpace(pred.AND)) { ANDS.TryAdd(pred.AND, new List <PreconditionResult>()); } } } bool requireExcessQueryMatch = true; foreach (var pred in preconditions) { if (pred is RequireNoExcessQuery rqp) { requireExcessQueryMatch = rqp.Required; } PreconditionResult result = null; try { result = pred.Check(context); } catch (HaltExecutionException e) { final.WithException(e); result = PreconditionResult.FromError(e.ToString()); } if (ORS.TryGetValue(pred.OR, out var orls)) { orls.Add(result); } if ((string.IsNullOrWhiteSpace(pred.AND) && string.IsNullOrWhiteSpace(pred.OR)) || !string.IsNullOrWhiteSpace(pred.AND)) { if (ANDS.TryGetValue(pred.AND, out var andls)) { andls.Add(result); } } } foreach (var or in ORS.Keys) { var ls = ORS[or]; var anySuccess = ls.FirstOrDefault(x => x.IsSuccess); if (anySuccess == null) { return(final.WithError($"{string.Join(",", ls.Where(x => !x.IsSuccess).Select(x => x.ErrorReason))}")); } } weight += 5; foreach (var and in ANDS.Keys) { var ls = ANDS[and]; var anyFailure = ls.FirstOrDefault(x => x.IsSuccess == false); if (anyFailure != null) { return(final.WithError($"{string.Join(",", ls.Where(x => !x.IsSuccess).Select(x => x.ErrorReason))}")); } } weight += 5; var serverName = (RequireServerName)preconditions.Last(x => x is RequireServerName); if (serverName.Domain == context.Host) { weight += 5; } var args = new List <object>(); var paramaters = cmd.Function.GetParameters(); foreach (var param in paramaters) { string value = null; if (cmd.Regexs.TryGetValue(param.Name, out var pattern)) { var match = rgxMatch.Groups[param.Name]; value = match.Value; } else { value = context.GetQuery(param.Name); } if (value == null && param.IsOptional == false) { return(final.WithError($"No argument specified for required item {param.Name}")); } if (value == null) { args.Add(param.DefaultValue); continue; } if (param.ParameterType == typeof(string)) { args.Add(Uri.UnescapeDataString(value)); } else { var typeResult = Program.AttemptParseInput(value, param.ParameterType); if (typeResult.IsSuccess) { args.Add(typeResult.BestMatch); } else { return(final.WithError($"Could not parse value for {param.Name} as {param.ParameterType.Name}: {typeResult.ErrorReason}")); } } } weight += args.Count; foreach (var key in context.GetAllKeys()) { var para = paramaters.FirstOrDefault(x => x.Name == key); if (para == null && requireExcessQueryMatch) { return(final.WithError($"Unknown argument specified: {key}")); } } weight += 50; final.Arguments = args; return(final); }
public ParseResult(APIEndpoint cmd) { Exceptions = new List <HaltExecutionException>(); Command = cmd; }