private void Add(DekiExtFunctionAttribute ext, MethodInfo method, XDoc script) { // convert DekiExtParamAttribute into DekiScriptNativeInvocationTarget.Parameter var parameters = from param in method.GetParameters() let attr = (DekiExtParamAttribute[])param.GetCustomAttributes(typeof(DekiExtParamAttribute), false) select((attr != null) && (attr.Length > 0)) ? new DekiScriptNativeInvocationTarget.Parameter(attr[0].Hint, attr[0].Optional) : null; // create native target invocation var target = new DekiScriptNativeInvocationTarget(this, method, parameters.ToArray()); DekiScriptInvocationTargetDescriptor function; // check if implementation is provided by a script instead if (script != null) { var scriptTarget = new DekiScriptExpressionInvocationTarget(target.Access, target.Parameters, DekiScriptParser.Parse(script)); function = new DekiScriptInvocationTargetDescriptor(target.Access, ext.IsProperty, false, ext.Name ?? method.Name, target.Parameters, target.ReturnType, ext.Description, ext.Transform, scriptTarget); } else { function = new DekiScriptInvocationTargetDescriptor(target.Access, ext.IsProperty, false, ext.Name ?? method.Name, target.Parameters, target.ReturnType, ext.Description, ext.Transform, target); } _functions[Self.At(function.SystemName)] = function; }
public Yield PostExtensionFunction(DreamContext context, DreamMessage request, Result <DreamMessage> response) { var name = context.GetParam("function"); XUri uri = Self.At(name); // check if deki server is permitted to invoke this function if (this is IDreamServiceLicense) { string deki; if (context.ServiceLicense.TryGetValue("deki", out deki) && !deki.EqualsInvariant(request.Headers[DEKI_HEADER] ?? string.Empty)) { throw new DreamAbortException(DreamMessage.Forbidden("deki server is not licensed for this service")); } } // check if any functions were found DekiScriptInvocationTargetDescriptor descriptor; if (!_functions.TryGetValue(uri, out descriptor)) { response.Return(DreamMessage.NotFound(string.Format("function {0} not found", context.GetParam("function")))); yield break; } // check if invoker has access to function if ((descriptor.Access != DreamAccess.Public) && (descriptor.Access > DetermineAccess(context, request))) { response.Return(DreamMessage.Forbidden("insufficient access privileges")); yield break; } // check if request has a requested culture context.Culture = HttpUtil.GetCultureInfoFromHeader(request.Headers.AcceptLanguage, context.Culture); // check for implicit arguments context.SetState(GetImplicitEnvironment(request, _publicDigitalSignature)); // create custom environment DekiScriptEnv env = CreateEnvironment(); // create custom target for custom environment var target = descriptor.Target as DekiScriptExpressionInvocationTarget; if (target != null) { // TODO (steveb): re-initializing the invocation target works for the first call, but not if the function calls another function in the same extension! target = new DekiScriptExpressionInvocationTarget(target.Access, target.Parameters, target.Expression, env); } // invoke target DekiScriptLiteral eval; if (target != null) { eval = target.Invoke(ScriptRuntime, DekiScriptLiteral.FromXml(request.ToDocument())); } else { eval = descriptor.Target.Invoke(ScriptRuntime, DekiScriptLiteral.FromXml(request.ToDocument())); } // invoke function response.Return(DreamMessage.Ok(new DekiScriptList().Add(eval).ToXml())); yield break; }