protected override Yield Start(XDoc config, Result result)
        {
            yield return(Coroutine.Invoke(base.Start, config, new Result()));

            // loop over all resources
            Type   type     = GetType();
            string assembly = type.Assembly.FullName.Split(new char[] { ',' }, 2)[0];

            foreach (DekiExtLibraryFilesAttribute files in Attribute.GetCustomAttributes(type, typeof(DekiExtLibraryFilesAttribute)))
            {
                string prefix = files.Prefix ?? type.Namespace;
                foreach (string filename in files.Filenames)
                {
                    MimeType mime = MimeType.FromFileExtension(filename);
                    _files[filename] = Plug.New(string.Format("resource://{0}/{1}.{2}", assembly, prefix, filename)).With("dream.out.type", mime.FullType);
                }
            }

            // check if a public digital signature key was provided
            string dsaKey = config["deki-signature"].AsText ?? config["dekiwiki-signature"].AsText;

            if (dsaKey != null)
            {
                try {
                    DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
                    dsa.ImportCspBlob(Convert.FromBase64String(dsaKey));
                    _publicDigitalSignature = dsa;
                } catch {
                    throw new ArgumentException("invalid digital signature provided", "deki-signature");
                }
            }

            // loop over all instance methods
            foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
            {
                // check if it has the DekiExtFunction attriute
                DekiExtFunctionAttribute ext = (DekiExtFunctionAttribute)Attribute.GetCustomAttribute(method, typeof(DekiExtFunctionAttribute));
                if (ext != null)
                {
                    // check if function has an associated script
                    XDekiScript script = null;
                    DekiExtFunctionScriptAttribute scriptAttr = (DekiExtFunctionScriptAttribute)Attribute.GetCustomAttribute(method, typeof(DekiExtFunctionScriptAttribute));
                    if (scriptAttr != null)
                    {
                        DreamMessage scriptresource = Plug.New(string.Format("resource://{0}/{1}.{2}", assembly, scriptAttr.Prefix ?? type.Namespace, scriptAttr.Scriptname)).With("dream.out.type", MimeType.XML.FullType).GetAsync().Wait();
                        if (scriptresource.IsSuccessful)
                        {
                            script = new XDekiScript(scriptresource.ToDocument());
                        }
                        if (script == null)
                        {
                            throw new InvalidOperationException(string.Format("method '{0}' is declard as script, but script could not be loaded", method.Name));
                        }
                    }

                    // add function
                    Add(ext, method, script);
                }
            }

            // add configuration settings
            var context = DreamContext.Current;

            _scriptConfig = new DekiScriptMap();
            foreach (KeyValuePair <string, string> entry in Config.ToKeyValuePairs())
            {
                XUri local;
                if (XUri.TryParse(entry.Value, out local))
                {
                    local = context.AsPublicUri(local);
                    _scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString()));
                }
                else
                {
                    _scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value));
                }
            }
            result.Return();
        }
        private void LoadScript() {
            _manifestPath = null;
            _resourcesPath = null;
            _manifestUri = null;
            _resourcesUri = null;
            _manifest = null;

            // read manifest
            _manifestPath = Config["manifest"].AsText;
            if(string.IsNullOrEmpty(_manifestPath)) {
                throw new ArgumentNullException("manifest");
            }
            _manifestUri = XUri.TryParse(_manifestPath);
            if(_manifestUri != null) {
                _manifestPath = null;
                _manifest = Plug.New(_manifestUri).Get().ToDocument();
                _resourcesUri = Config["resources"].AsUri ?? _manifestUri.WithoutLastSegment();
            } else {
                _manifest = XDocFactory.LoadFrom(_manifestPath, MimeType.XML);
                _resourcesPath = Config["resources"].AsText ?? Path.GetDirectoryName(_manifestPath);
            }
            if(!_manifest.HasName("extension")) {
                throw new ArgumentException("invalid extension manifest");
            }

            // initilize runtime
            _runtime = new DekiScriptRuntime();

            // read manifest settings
            _title = _manifest["title"].AsText;
            _label = _manifest["label"].AsText;
            _copyright = _manifest["copyright"].AsText;
            _description = _manifest["description"].AsText;
            _help = _manifest["uri.help"].AsText;
            _logo = _manifest["uri.logo"].AsText;
            _namespace = _manifest["namespace"].AsText;

            // initialize evaluation environment
            _commonEnv = _runtime.CreateEnv();

            // read functions
            _functions = new Dictionary<XUri, DekiScriptInvocationTargetDescriptor>();
            foreach(var function in _manifest["function"]) {
                var descriptor = ConvertFunction(function);
                if(descriptor != null) {
                    var uri = Self.At(descriptor.SystemName);
                    DekiScriptInvocationTargetDescriptor old;
                    if(_functions.TryGetValue(uri, out old)) {
                        _log.WarnFormat("duplicate function name {0} in script {1}", descriptor.Name, _manifestUri);
                    }
                    _functions[uri] = descriptor;
                }
            }
            _runtime.RegisterExtensionFunctions(_functions);

            // add extension functions to env
            foreach(var function in _functions) {
                _commonEnv.Vars.AddNativeValueAt(function.Value.Name.ToLowerInvariant(), function.Key);
            }

            // add configuration settings
            DreamContext context = DreamContext.Current;
            DekiScriptMap scriptConfig = new DekiScriptMap();
            foreach(KeyValuePair<string, string> entry in Config.ToKeyValuePairs()) {
                XUri local;
                if(XUri.TryParse(entry.Value, out local)) {
                    local = context.AsPublicUri(local);
                    scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString()));
                } else {
                    scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value));
                }
            }
            _commonEnv.Vars.Add("config", scriptConfig);
        }
        public static DekiScriptMap GetImplicitEnvironment(DreamMessage message, DSACryptoServiceProvider publicDigitalSignature)
        {
            DekiScriptMap env = new DekiScriptMap();

            // retrieve implicit arguments
            string[] headers = message.Headers.GetValues(IMPLICIT_ENVIRONMENT_HEADER);
            if (!ArrayUtil.IsNullOrEmpty(headers))
            {
                env.AddAt("__implicit", new DekiScriptList(new ArrayList(headers)));
                foreach (string implicitArg in headers)
                {
                    foreach (KeyValuePair <string, string> arg in HttpUtil.ParseNameValuePairs(implicitArg))
                    {
                        env.AddNativeValueAt(arg.Key, arg.Value);
                    }
                }
            }
            if (publicDigitalSignature != null)
            {
                bool valid = false;
                try {
                    Dictionary <string, string> values = HttpUtil.ParseNameValuePairs(message.Headers[IMPLICIT_SIGNATURE_HEADER]);

                    // verify date
                    DateTime date  = DateTime.Parse(values["date"]).ToUniversalTime();
                    double   delta = DateTime.UtcNow.Subtract(date).TotalSeconds;
                    if ((delta < -60) || (delta > 60))
                    {
                        throw new DreamAbortException(DreamMessage.Forbidden("date in message signature is too far apart from server date"));
                    }

                    // verify message
                    MemoryStream data  = new MemoryStream();
                    byte[]       bytes = null;

                    // get message bytes
                    bytes = message.AsBytes();
                    data.Write(bytes, 0, bytes.Length);

                    // retrieve headers to verify
                    if (!ArrayUtil.IsNullOrEmpty(headers))
                    {
                        Array.Sort(headers, StringComparer.Ordinal);
                        bytes = Encoding.UTF8.GetBytes(string.Join(",", headers));
                        data.Write(bytes, 0, bytes.Length);
                    }

                    // add request date
                    bytes = Encoding.UTF8.GetBytes(values["date"]);
                    data.Write(bytes, 0, bytes.Length);

                    // verify signature
                    byte[] signature = Convert.FromBase64String(values["dsig"]);
                    valid = publicDigitalSignature.VerifyData(data.GetBuffer(), signature);
                } catch (Exception e) {
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                }
                if (!valid)
                {
                    throw new DreamAbortException(DreamMessage.Forbidden("invalid or missing digital signature"));
                }
            }
            return(env);
        }
Beispiel #4
0
        private void LoadScript()
        {
            _manifestPath  = null;
            _resourcesPath = null;
            _manifestUri   = null;
            _resourcesUri  = null;
            _manifest      = null;

            // read manifest
            _manifestPath = Config["manifest"].AsText;
            if (string.IsNullOrEmpty(_manifestPath))
            {
                throw new ArgumentNullException("manifest");
            }
            _manifestUri = XUri.TryParse(_manifestPath);
            if (_manifestUri != null)
            {
                _manifestPath = null;
                _manifest     = Plug.New(_manifestUri).Get().ToDocument();
                _resourcesUri = Config["resources"].AsUri ?? _manifestUri.WithoutLastSegment();
            }
            else
            {
                _manifest      = XDocFactory.LoadFrom(_manifestPath, MimeType.XML);
                _resourcesPath = Config["resources"].AsText ?? Path.GetDirectoryName(_manifestPath);
            }
            if (!_manifest.HasName("extension"))
            {
                throw new ArgumentException("invalid extension manifest");
            }

            // initilize runtime
            _runtime = new DekiScriptRuntime();

            // read manifest settings
            _title       = _manifest["title"].AsText;
            _label       = _manifest["label"].AsText;
            _copyright   = _manifest["copyright"].AsText;
            _description = _manifest["description"].AsText;
            _help        = _manifest["uri.help"].AsText;
            _logo        = _manifest["uri.logo"].AsText;
            _namespace   = _manifest["namespace"].AsText;

            // initialize evaluation environment
            _commonEnv = _runtime.CreateEnv();

            // read functions
            _functions = new Dictionary <XUri, DekiScriptInvocationTargetDescriptor>();
            foreach (var function in _manifest["function"])
            {
                var descriptor = ConvertFunction(function);
                if (descriptor != null)
                {
                    var uri = Self.At(descriptor.SystemName);
                    DekiScriptInvocationTargetDescriptor old;
                    if (_functions.TryGetValue(uri, out old))
                    {
                        _log.WarnFormat("duplicate function name {0} in script {1}", descriptor.Name, _manifestUri);
                    }
                    _functions[uri] = descriptor;
                }
            }
            _runtime.RegisterExtensionFunctions(_functions);

            // add extension functions to env
            foreach (var function in _functions)
            {
                _commonEnv.Vars.AddNativeValueAt(function.Value.Name.ToLowerInvariant(), function.Key);
            }

            // add configuration settings
            DreamContext  context      = DreamContext.Current;
            DekiScriptMap scriptConfig = new DekiScriptMap();

            foreach (KeyValuePair <string, string> entry in Config.ToKeyValuePairs())
            {
                XUri local;
                if (XUri.TryParse(entry.Value, out local))
                {
                    local = context.AsPublicUri(local);
                    scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString()));
                }
                else
                {
                    scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value));
                }
            }
            _commonEnv.Vars.Add("config", scriptConfig);
        }