예제 #1
0
        public static UrlRule CreateUrl(dynamic model, RequestFilteringSection section)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            string urlString = DynamicHelper.Value(model.url);

            if (string.IsNullOrEmpty(urlString))
            {
                throw new ApiArgumentException("url");
            }
            if (DynamicHelper.To <bool>(model.allow) == null)
            {
                throw new ApiArgumentException("allow");
            }
            bool allow = DynamicHelper.To <bool>(model.allow);

            return(new UrlRule()
            {
                Url = urlString,
                Allow = allow
            });
        }
예제 #2
0
        public object Patch(dynamic model)
        {
            if (!ScmHelper.IsInstalled())
            {
                return(NotFound());
            }

            if (model.status != null)
            {
                Status status = DynamicHelper.To <Status>(model.status);
                switch (status)
                {
                case Status.Started:
                    ScmHelper.Start();
                    break;

                case Status.Stopped:
                    ScmHelper.Stop();
                    break;

                default:
                    break;
                }
            }

            return(ScmHelper.ToJsonModel());
        }
        public static void Update(ApiKey key, dynamic model)
        {
            if (key == null)
            {
                throw new ArgumentNullException();
            }

            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            //
            // purpose
            string purpose = DynamicHelper.Value(model.purpose);

            if (purpose != null)
            {
                key.Purpose = purpose;
            }

            //
            // expires_on
            DateTime?expiresOn = DynamicHelper.To <DateTime>(model.expires_on);

            if (expiresOn != null)
            {
                key.ExpiresOn = expiresOn;
            }

            //
            // Set last modified
            key.LastModified = DateTime.Now;
        }
예제 #4
0
        public static HeaderLimit UpdateHeaderLimit(HeaderLimit headerLimit, dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (headerLimit == null)
            {
                throw new ApiArgumentException("headerLimit");
            }
            string header = DynamicHelper.Value(model.header);

            if (header == string.Empty)
            {
                throw new ApiArgumentException("header");
            }

            try {
                headerLimit.Header    = DynamicHelper.Value(model.header) ?? headerLimit.Header;
                headerLimit.SizeLimit = DynamicHelper.To(model.size_limit, 0, uint.MaxValue) ?? headerLimit.SizeLimit;
            }
            catch (FileLoadException e) {
                throw new LockedException(RequestFilteringGlobals.RequestFilteringSectionName, e);
            }

            return(headerLimit);
        }
        public async Task <object> Patch(string id, [FromBody] dynamic model)
        {
            // Cut off the notion of uuid from beginning of request
            string name = AppPoolId.CreateFromUuid(id).Name;

            // Set settings
            ApplicationPool appPool = AppPoolHelper.UpdateAppPool(name, model);

            if (appPool == null)
            {
                return(NotFound());
            }

            if (model.identity != null && !await IsAppPoolIdentityAllowed(appPool))
            {
                return(new ForbidResult());
            }

            // Start/Stop
            if (model.status != null)
            {
                Status status = DynamicHelper.To <Status>(model.status);
                try {
                    switch (status)
                    {
                    case Status.Stopped:
                        appPool.Stop();
                        break;

                    case Status.Started:
                        appPool.Start();
                        break;
                    }
                }
                catch (COMException e) {
                    // If pool is fresh and status is still unknown then COMException will be thrown when manipulating status
                    throw new ApiException("Error setting application pool status", e);
                }
            }

            // Update changes
            ManagementUnit.Current.Commit();

            // Refresh data
            appPool = ManagementUnit.ServerManager.ApplicationPools[appPool.Name];

            //
            // Create response
            dynamic pool = AppPoolHelper.ToJsonModel(appPool, Context.Request.GetFields());

            // The Id could change by changing apppool name
            if (pool.id != id)
            {
                return(LocationChanged(AppPoolHelper.GetLocation(pool.id), pool));
            }

            return(pool);
        }
        public static void UpdateModule(Module module, dynamic model, Site site)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (module == null)
            {
                throw new ArgumentNullException("module");
            }
            if (string.IsNullOrEmpty(module.Name))
            {
                throw new ApiArgumentException("module.Name");
            }

            string type         = DynamicHelper.Value(model.type) ?? string.Empty;
            string precondition = DynamicHelper.Value(model.precondition) ?? module.PreCondition;

            if (ModuleIsLocked(module) && site != null)
            {
                // Can't update the module if it is locked
                // Unless the scope is at server level
                throw new InvalidOperationException("Lock violation");
            }

            try {
                // Locked
                bool?locked = DynamicHelper.To <bool>(model.locked);
                if (locked != null)
                {
                    SetItemLocked(module, locked.Value);
                }

                // Precondition
                if (ConfigurationUtility.ShouldPersist(module.PreCondition, precondition))
                {
                    module.PreCondition = precondition;
                }

                // Type
                if (string.IsNullOrEmpty(module.Type) != string.IsNullOrEmpty(type))
                {
                    // If the module specified a type, we allow a type name change but not erasure
                    // If the module did not specify a type during creation we don't allow a change
                    throw new ApiArgumentException("type");
                }

                module.Type = type;
            }
            catch (FileLoadException e) {
                throw new LockedException(ModulesGlobals.ModulesSectionName, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }
        }
예제 #7
0
        public object Patch(string id, [FromBody] dynamic model)
        {
            // Set settings
            Site site = SiteHelper.UpdateSite(new SiteId(id).Id, model, _fileProvider);

            if (site == null)
            {
                return(NotFound());
            }

            // Start/Stop
            if (model.status != null)
            {
                Status status = DynamicHelper.To <Status>(model.status);
                try {
                    switch (status)
                    {
                    case Status.Stopped:
                        site.Stop();
                        break;

                    case Status.Started:
                        site.Start();
                        break;
                    }
                }
                catch (COMException e) {
                    // If site is fresh and status is still unknown then COMException will be thrown when manipulating status
                    throw new ApiException("Error setting site status", e);
                }
                catch (ServerManagerException e) {
                    throw new ApiException(e.Message, e);
                }
            }

            // Update changes
            ManagementUnit.Current.Commit();

            // Refresh data
            site = ManagementUnit.ServerManager.Sites[site.Name];

            //
            // Create response
            dynamic sModel = SiteHelper.ToJsonModel(site, Context.Request.GetFields());

            // The Id could change by changing the sites key
            if (sModel.id != id)
            {
                return(LocationChanged(SiteHelper.GetLocation(sModel.id), sModel));
            }

            return(sModel);
        }
        public static Rule SetRule(Rule rule, dynamic model, IPSecuritySection section)
        {
            if (rule == null)
            {
                throw new ArgumentNullException("rule");
            }

            string subnetMask = DynamicHelper.Value(model.subnet_mask);

            if (subnetMask != null)
            {
                try {
                    // Throw format exception of subnet mask is not in valid format
                    IPAddress.Parse(subnetMask);
                }
                catch (FormatException e) {
                    throw new ApiArgumentException("subnet_mask", e);
                }
            }

            string    inIp      = DynamicHelper.Value(model.ip_address);
            IPAddress ipAddress = null;

            if (inIp != null)
            {
                try {
                    ipAddress = IPAddress.Parse(inIp);
                }
                catch (FormatException e) {
                    throw new ApiArgumentException("ip_address", e);
                }

                if (ipAddress != rule.IpAddress && section.IpAddressFilters.Any(r => r.IpAddress.Equals(ipAddress)))
                {
                    throw new AlreadyExistsException("ip_address");
                }
            }

            try {
                rule.IpAddress  = ipAddress != null ? ipAddress : rule.IpAddress;
                rule.Allowed    = DynamicHelper.To <bool>(model.allowed) ?? rule.Allowed;
                rule.SubnetMask = subnetMask ?? rule.SubnetMask;
                rule.DomainName = DynamicHelper.Value(model.domain_name) ?? rule.DomainName;
            }
            catch (FileLoadException e) {
                throw new LockedException(IPRestrictionsGlobals.IPSecuritySectionName, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }

            return(rule);
        }
        private static ApiKey FromJson(dynamic key)
        {
            string   tokenHash = DynamicHelper.Value(key.token_hash) ?? DynamicHelper.Value(key.hash);
            string   tokenType = DynamicHelper.Value(key.token_type) ?? "SWT";
            DateTime createdOn = DynamicHelper.To <DateTime>(key.created_on) ?? DateTime.UtcNow;

            return(new ApiKey(tokenHash, tokenType)
            {
                Id = DynamicHelper.Value(key.id) ?? GenerateId(),
                Purpose = DynamicHelper.Value(key.purpose) ?? string.Empty,
                CreatedOn = createdOn,
                ExpiresOn = DynamicHelper.To <DateTime>(key.expires_on),
                LastModified = DynamicHelper.To <DateTime>(key.last_modified) ?? createdOn
            });
        }
        private static LoggingRolloverPeriod?PeriodFromRepresentation(dynamic period)
        {
            string p = DynamicHelper.Value(period);

            if (string.IsNullOrEmpty(p))
            {
                return(null);
            }

            if (p.Equals("max_size"))
            {
                return(LoggingRolloverPeriod.MaxSize);
            }

            return(DynamicHelper.To <LoggingRolloverPeriod>(period));
        }
        public static Extension UpdateExtension(Extension extension, dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (extension == null)
            {
                throw new ApiArgumentException("extension");
            }

            DynamicHelper.If((object)model.extension, ext => extension.FileExtension = ext.StartsWith(".") ? ext : "." + ext);
            extension.Allowed = DynamicHelper.To <bool>(model.allow) ?? extension.Allowed;

            return(extension);
        }
예제 #12
0
        internal IFileInfo UpdateDirectory(dynamic model, IFileInfo directory)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            DateTime?created      = DynamicHelper.To <DateTime>(model.created);
            DateTime?lastAccess   = DynamicHelper.To <DateTime>(model.last_access);
            DateTime?lastModified = DynamicHelper.To <DateTime>(model.last_modified);

            //
            // Change name
            if (model.name != null)
            {
                string name = DynamicHelper.Value(model.name).Trim();

                if (!PathUtil.IsValidFileName(name))
                {
                    throw new ApiArgumentException("name");
                }

                string newPath = Path.Combine(directory.Parent.Path, name);

                if (!newPath.Equals(directory.Path, StringComparison.OrdinalIgnoreCase))
                {
                    IFileInfo destination = _fileProvider.GetDirectory(newPath);

                    if (destination.Exists || _fileProvider.GetFile(newPath).Exists)
                    {
                        throw new AlreadyExistsException("name");
                    }

                    _fileProvider.Move(directory, destination);

                    //
                    // Refresh
                    directory = _fileProvider.GetDirectory(destination.Path);
                }
            }

            //
            // Set file times
            _fileProvider.SetFileTime(directory, lastAccess, lastModified, created);

            return(directory);
        }
예제 #13
0
        public IActionResult Post([FromBody] dynamic model)
        {
            if (_downloadService == null)
            {
                throw new NotFoundException(typeof(IDownloadService).GetTypeInfo().Assembly.FullName);
            }

            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (model.file == null)
            {
                throw new ApiArgumentException("file");
            }
            if (!(model.file is JObject))
            {
                throw new ApiArgumentException("file", ApiArgumentException.EXPECTED_OBJECT);
            }

            //
            // Check Id
            string fileUuid = DynamicHelper.Value(model.file.id);

            if (fileUuid == null)
            {
                throw new ApiArgumentException("file.id");
            }

            int?ttl = DynamicHelper.To <int>(model.ttl);

            FileId    fileId = FileId.FromUuid(fileUuid);
            IFileInfo file   = _fileService.GetFile(fileId.PhysicalPath);

            if (!file.Exists)
            {
                throw new NotFoundException(fileId.PhysicalPath);
            }

            var dl = _downloadService.Create(file.Path, ttl ?? DEFAULT_DOWNLOAD_TIMEOUT);

            // Inform client location points to downloadable attachment
            Context.Response.Headers.Add("Pragma", "attachment");

            return(Created(dl.Href, null));
        }
예제 #14
0
        internal string UpdateDirectory(dynamic model, string directoryPath)
        {
            DateTime?created      = null;
            DateTime?lastAccess   = null;
            DateTime?lastModified = null;

            var directory = _fileProvider.GetDirectory(directoryPath);

            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            created      = DynamicHelper.To <DateTime>(model.created);
            lastAccess   = DynamicHelper.To <DateTime>(model.last_access);
            lastModified = DynamicHelper.To <DateTime>(model.last_modified);

            if (model.name != null)
            {
                string name = DynamicHelper.Value(model.name);

                if (!PathUtil.IsValidFileName(name))
                {
                    throw new ApiArgumentException("name");
                }

                var newPath = Path.Combine(directory.Parent.Path, name);

                if (!newPath.Equals(directoryPath, StringComparison.OrdinalIgnoreCase))
                {
                    if (_fileProvider.FileExists(newPath) || _fileProvider.DirectoryExists(newPath))
                    {
                        throw new AlreadyExistsException("name");
                    }

                    _fileProvider.Move(directoryPath, newPath);

                    directoryPath = newPath;
                }
            }

            _fileProvider.SetFileTime(directoryPath, lastAccess, lastModified, created);

            return(directoryPath);
        }
        public static void Update(ConfigurationSection section, dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (section == null)
            {
                throw new ArgumentException("section");
            }

            OverrideMode?overrideMode = DynamicHelper.To <OverrideMode>(model.override_mode);

            if (overrideMode != null && overrideMode.Value != section.OverrideMode)
            {
                section.OverrideMode = overrideMode.Value;
            }
        }
        public static Rule CreateRule(dynamic model, AuthorizationSection section)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            RuleAccessType?accessType = DynamicHelper.To <RuleAccessType>(model.access_type);

            if (accessType == null)
            {
                throw new ApiArgumentException("access_type");
            }

            Rule rule = section.Rules.CreateElement();

            SetRule(rule, model);

            return(rule);
        }
        private static void SetMapping(dynamic model, Mapping mapping)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (mapping == null)
            {
                throw new ArgumentNullException("mapping");
            }

            mapping.Path                = DynamicHelper.Value(model.path) ?? mapping.Path;
            mapping.Verb                = DynamicHelper.Value(model.verbs) ?? mapping.Verb;
            mapping.Type                = DynamicHelper.Value(model.type) ?? mapping.Type;
            mapping.Modules             = DynamicHelper.Value(model.modules) ?? mapping.Modules;
            mapping.ScriptProcessor     = DynamicHelper.Value(model.script_processor) ?? mapping.ScriptProcessor;
            mapping.ResourceType        = DynamicHelper.To <ResourceType>(model.resource_type) ?? mapping.ResourceType;
            mapping.RequireAccess       = DynamicHelper.To <HandlerRequiredAccess>(model.require_access) ?? mapping.RequireAccess;
            mapping.AllowPathInfo       = DynamicHelper.To <bool>(model.allow_path_info) ?? mapping.AllowPathInfo;
            mapping.PreCondition        = DynamicHelper.Value(model.precondition) ?? mapping.PreCondition;
            mapping.ResponseBufferLimit = DynamicHelper.To(model.response_buffer_limit, 0, uint.MaxValue) ?? mapping.ResponseBufferLimit;
        }
        public static Extension CreateExtension(dynamic model, RequestFilteringSection section)
        {
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            string extension = DynamicHelper.Value(model.extension);

            if (string.IsNullOrEmpty(extension))
            {
                throw new ApiArgumentException("extension");
            }

            Extension ext = section.FileExtensions.CreateElement();

            ext.FileExtension = extension.StartsWith(".") ? extension : "." + extension;

            ext.Allowed = DynamicHelper.To <bool>(model.allow) ?? ext.Allowed;

            return(ext);
        }
        public static QueryStringRule CreateQueryString(dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            string queryString = DynamicHelper.Value(model.query_string);

            if (string.IsNullOrEmpty(queryString))
            {
                throw new ApiArgumentException("query_string");
            }

            QueryStringRule queryStringRule = new QueryStringRule();

            queryStringRule.QueryString = queryString;

            queryStringRule.Allow = DynamicHelper.To <bool>(model.allow) ?? default(bool);

            return(queryStringRule);
        }
        public static VerbElement UpdateVerb(VerbElement verb, dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }
            if (verb == null)
            {
                throw new ArgumentNullException("verb");
            }

            try {
                verb.Allowed = DynamicHelper.To <bool>(model.allowed) ?? verb.Allowed;
            }
            catch (FileLoadException e) {
                throw new LockedException(RequestFilteringGlobals.RequestFilteringSectionName, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }

            return(verb);
        }
예제 #21
0
        private static Site SetSite(Site site, dynamic model, IFileProvider fileProvider)
        {
            Debug.Assert(site != null);
            Debug.Assert((bool)(model != null));

            //
            // Name
            DynamicHelper.If((object)model.name, v => { site.Name = v; });

            //
            // Server Auto Start
            site.ServerAutoStart = DynamicHelper.To <bool>(model.server_auto_start) ?? site.ServerAutoStart;


            //
            // Physical Path
            string physicalPath = DynamicHelper.Value(model.physical_path);

            if (physicalPath != null)
            {
                physicalPath = physicalPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
                var expanded = System.Environment.ExpandEnvironmentVariables(physicalPath);

                if (!PathUtil.IsFullPath(expanded))
                {
                    throw new ApiArgumentException("physical_path");
                }
                if (!fileProvider.IsAccessAllowed(expanded, FileAccess.Read))
                {
                    throw new ForbiddenArgumentException("physical_path", physicalPath);
                }
                if (!Directory.Exists(expanded))
                {
                    throw new NotFoundException("physical_path");
                }

                var rootApp = site.Applications["/"];
                if (rootApp != null)
                {
                    var rootVDir = rootApp.VirtualDirectories["/"];

                    if (rootVDir != null)
                    {
                        rootVDir.PhysicalPath = physicalPath;
                    }
                }
            }

            //
            // Enabled Protocols
            string enabledProtocols = DynamicHelper.Value(model.enabled_protocols);

            if (enabledProtocols != null)
            {
                var rootApp = site.Applications["/"];

                if (rootApp != null)
                {
                    rootApp.EnabledProtocols = enabledProtocols;
                }
            }

            //
            // Limits
            if (model.limits != null)
            {
                dynamic limits = model.limits;

                site.Limits.MaxBandwidth   = DynamicHelper.To(limits.max_bandwidth, 0, uint.MaxValue) ?? site.Limits.MaxBandwidth;
                site.Limits.MaxConnections = DynamicHelper.To(limits.max_connections, 0, uint.MaxValue) ?? site.Limits.MaxConnections;

                if (site.Limits.Schema.HasAttribute(MaxUrlSegmentsAttribute))
                {
                    site.Limits.MaxUrlSegments = DynamicHelper.To(limits.max_url_segments, 0, 16383) ?? site.Limits.MaxUrlSegments;
                }

                long?connectionTimeout = DynamicHelper.To(limits.connection_timeout, 0, ushort.MaxValue);
                site.Limits.ConnectionTimeout = (connectionTimeout != null) ? TimeSpan.FromSeconds(connectionTimeout.Value) : site.Limits.ConnectionTimeout;
            }

            //
            // Bindings
            if (model.bindings != null)
            {
                IEnumerable <dynamic> bindings = (IEnumerable <dynamic>)model.bindings;

                // If the user passes an object for the bindings property rather than an array we will hit an exception when we try to access any property in
                // the foreach loop.
                // This means that the bindings collection won't be deleted, so the bindings are safe from harm.

                List <Binding> newBindings = new List <Binding>();

                // Iterate over the bindings to create a new binding list
                foreach (dynamic b in bindings)
                {
                    Binding binding = site.Bindings.CreateElement();
                    SetBinding(binding, b);

                    foreach (Binding addedBinding in newBindings)
                    {
                        if (addedBinding.Protocol.Equals(binding.Protocol, StringComparison.OrdinalIgnoreCase) &&
                            addedBinding.BindingInformation.Equals(binding.BindingInformation, StringComparison.OrdinalIgnoreCase))
                        {
                            throw new AlreadyExistsException("binding");
                        }
                    }

                    // Add to bindings list
                    newBindings.Add(binding);
                }

                // All bindings have been verified and added to the list
                // Clear the old list, and add the new
                site.Bindings.Clear();
                newBindings.ForEach(binding => site.Bindings.Add(binding));
            }

            //
            // App Pool
            if (model.application_pool != null)
            {
                // Extract the uuid from the application_pool object provided in model
                string appPoolUuid = DynamicHelper.Value(model.application_pool.id);

                // It is an error to provide an application pool object without specifying its id property
                if (appPoolUuid == null)
                {
                    throw new ApiArgumentException("application_pool.id");
                }

                // Create application pool id object from uuid provided, use this to obtain the application pool
                AppPoolId       appPoolId = AppPoolId.CreateFromUuid(appPoolUuid);
                ApplicationPool pool      = AppPoolHelper.GetAppPool(appPoolId.Name);

                Application rootApp = site.Applications["/"];

                if (rootApp == null)
                {
                    throw new ApiArgumentException("application_pool", "Root application does not exist.");
                }

                // REVIEW: Should we create the root application if it doesn't exist and they specify an application pool?
                // We decided not to do this for physical_path.
                // Application pool for a site is extracted from the site's root application
                rootApp.ApplicationPoolName = pool.Name;
            }

            return(site);
        }
예제 #22
0
        private static void AssignRuleFromModel(dynamic model, InboundRule rule, InboundRulesSection section, AllowedServerVariablesSection serverVariablesSection)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            //
            // Name, check for already existing name
            string name = DynamicHelper.Value(model.name);

            if (!string.IsNullOrEmpty(name))
            {
                if (!name.Equals(rule.Name, StringComparison.OrdinalIgnoreCase) &&
                    section.InboundRules.Any(r => r.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
                {
                    throw new AlreadyExistsException("name");
                }

                rule.Name = name;
            }

            DynamicHelper.If((object)model.pattern, v => rule.Match.Pattern = v);
            DynamicHelper.If <bool>((object)model.ignore_case, v => rule.Match.IgnoreCase   = v);
            DynamicHelper.If <bool>((object)model.negate, v => rule.Match.Negate            = v);
            DynamicHelper.If <bool>((object)model.stop_processing, v => rule.StopProcessing = v);
            DynamicHelper.If((object)model.pattern_syntax, v => rule.PatternSyntax          = PatternSyntaxHelper.FromJsonModel(v));

            //
            // Action
            dynamic action = model.action;

            if (action != null)
            {
                if (!(action is JObject))
                {
                    throw new ApiArgumentException("action", ApiArgumentException.EXPECTED_OBJECT);
                }

                DynamicHelper.If((object)action.type, v => rule.Action.Type = ActionTypeHelper.FromJsonModel(v));
                DynamicHelper.If((object)action.url, v => rule.Action.Url   = v);
                DynamicHelper.If <bool>((object)action.append_query_string, v => rule.Action.AppendQueryString = v);
                DynamicHelper.If <bool>((object)action.log_rewritten_url, v => rule.Action.LogRewrittenUrl     = v);
                DynamicHelper.If <long>((object)action.status_code, v => rule.Action.StatusCode        = v);
                DynamicHelper.If <long>((object)action.sub_status_code, v => rule.Action.SubStatusCode = v);
                DynamicHelper.If((object)action.description, v => rule.Action.StatusDescription        = v);
                DynamicHelper.If((object)action.reason, v => rule.Action.StatusReason = v);
                DynamicHelper.If <RedirectType>((object)action.redirect_type, v => rule.Action.RedirectType = v);
            }

            //
            // Server variables
            if (model.server_variables != null)
            {
                IEnumerable <dynamic> serverVariables = model.server_variables as IEnumerable <dynamic>;

                if (serverVariables == null)
                {
                    throw new ApiArgumentException("server_variables", ApiArgumentException.EXPECTED_ARRAY);
                }

                rule.ServerVariableAssignments.Clear();

                foreach (dynamic serverVariable in serverVariables)
                {
                    if (!(serverVariable is JObject))
                    {
                        throw new ApiArgumentException("server_variables.item");
                    }

                    string svName    = DynamicHelper.Value(serverVariable.name);
                    string svValue   = DynamicHelper.Value(serverVariable.value);
                    bool   svReplace = DynamicHelper.To <bool>(serverVariable.replace) ?? false;

                    if (string.IsNullOrEmpty(svName))
                    {
                        throw new ApiArgumentException("server_variables.item.name", "Required");
                    }

                    if (string.IsNullOrEmpty(svValue))
                    {
                        throw new ApiArgumentException("server_variables.item.value", "Required");
                    }

                    var svAssignment = rule.ServerVariableAssignments.CreateElement();
                    svAssignment.Name    = svName;
                    svAssignment.Value   = svValue;
                    svAssignment.Replace = svReplace;

                    AddAllowedServerVariable(serverVariablesSection, svAssignment.Name);

                    rule.ServerVariableAssignments.Add(svAssignment);
                }
            }

            DynamicHelper.If((object)model.condition_match_constraints, v => rule.Conditions.LogicalGrouping = LogicalGroupingHelper.FromJsonModel(v));
            DynamicHelper.If <bool>((object)model.track_all_captures, v => rule.Conditions.TrackAllCaptures  = v);

            //
            // Conditions
            if (model.conditions != null)
            {
                IEnumerable <dynamic> conditions = model.conditions as IEnumerable <dynamic>;

                if (conditions == null)
                {
                    throw new ApiArgumentException("conditions", ApiArgumentException.EXPECTED_ARRAY);
                }

                rule.Conditions.Clear();

                foreach (dynamic condition in conditions)
                {
                    if (!(condition is JObject))
                    {
                        throw new ApiArgumentException("conditions.item");
                    }

                    string input        = DynamicHelper.Value(condition.input);
                    string rawMatchType = DynamicHelper.Value(condition.match_type);

                    if (string.IsNullOrEmpty(input))
                    {
                        throw new ApiArgumentException("conditions.item.input", "Required");
                    }

                    if (string.IsNullOrEmpty(rawMatchType))
                    {
                        throw new ApiArgumentException("conditions.item.match_type", "Required");
                    }

                    MatchType matchType = MatchTypeHelper.FromJsonModel(rawMatchType);

                    var con = rule.Conditions.CreateElement();
                    con.Input      = input;
                    con.MatchType  = matchType;
                    con.Pattern    = DynamicHelper.Value(condition.pattern);
                    con.Negate     = DynamicHelper.To <bool>(condition.negate);
                    con.IgnoreCase = DynamicHelper.To <bool>(condition.ignore_case);

                    rule.Conditions.Add(con);
                }
            }

            if (rule.Schema.HasAttribute(InboundRule.ResponseCacheDirectiveAttribute))
            {
                DynamicHelper.If((object)model.response_cache_directive, v => rule.ResponseCacheDirective = ResponseCacheDirectiveHelper.FromJsonModel(v));
            }

            //
            // Check set to valid state
            if ((rule.Action.Type == ActionType.Redirect || rule.Action.Type == ActionType.Rewrite) && string.IsNullOrEmpty(rule.Action.Url))
            {
                throw new ApiArgumentException("action.url");
            }

            UpdatePriority(model, rule, section);
        }
        public static void UpdateQueryString(QueryStringRule queryString, dynamic model, Site site, string path, string configPath = null)
        {
            if (queryString == null)
            {
                throw new ArgumentNullException("queryString");
            }
            if (queryString.QueryString == null)
            {
                throw new ArgumentNullException("queryString.QueryString");
            }
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            bool?  allow           = DynamicHelper.To <bool>(model.allow);
            string queryStringName = DynamicHelper.Value(model.query_string);

            // Empty change set
            if (string.IsNullOrEmpty(queryStringName) && allow == null)
            {
                return;
            }

            var section = RequestFilteringHelper.GetRequestFilteringSection(site, path, configPath);

            try {
                // Remove the old query string

                if (queryString.Allow)
                {
                    // We have to retrieve the configuration element from the allow collection
                    var allowCollection = section.AlwaysAllowedQueryStrings;
                    var allowElement    = allowCollection.First(s => s.QueryString.Equals(queryString.QueryString));

                    // Remove the query string from the allow collection
                    allowCollection.Remove(allowElement);
                }
                else
                {
                    var denyCollection = section.DenyQueryStringSequences;
                    var denyElement    = denyCollection.First(s => s.Sequence.Equals(queryString.QueryString));

                    denyCollection.Remove(denyElement);
                }
            }
            catch (FileLoadException e) {
                throw new LockedException(section.SectionPath, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }


            // Update the query string to its new state
            queryString.Allow       = allow == null ? queryString.Allow : allow.Value;
            queryString.QueryString = string.IsNullOrEmpty(queryStringName) ? queryString.QueryString : queryStringName;


            try {
                // Add the updated query string back into its respective collection

                if (queryString.Allow)
                {
                    // Insert the query string into the allow collection
                    section.AlwaysAllowedQueryStrings.Add(queryString.QueryString);
                }
                else
                {
                    // Insert the query string into the deny collection
                    section.DenyQueryStringSequences.Add(queryString.QueryString);
                }
            }
            catch (FileLoadException e) {
                throw new LockedException(section.SectionPath, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }
        }
예제 #24
0
        private static Site SetSite(Site site, dynamic model)
        {
            Debug.Assert(site != null);
            Debug.Assert((bool)(model != null));

            DynamicHelper.If((object)model.name, v => { site.Name = v; });

            site.ServerAutoStart = DynamicHelper.To <bool>(model.server_auto_start) ?? site.ServerAutoStart;

            string physicalPath = DynamicHelper.Value(model.physical_path);

            if (physicalPath != null)
            {
                if (!Directory.Exists(System.Environment.ExpandEnvironmentVariables(physicalPath)))
                {
                    throw new ApiArgumentException("physical_path", "Directory does not exist.");
                }

                var rootApp = site.Applications["/"];
                if (rootApp == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root application does not exist.");
                }

                var rootVDir = rootApp.VirtualDirectories["/"];
                if (rootVDir == null)
                {
                    throw new ApiArgumentException("site/physical_path", "Root virtual directory does not exist.");
                }

                rootVDir.PhysicalPath = physicalPath.Replace('/', '\\');
            }

            string enabledProtocols = DynamicHelper.Value(model.enabled_protocols);

            if (enabledProtocols != null)
            {
                var rootApp = site.Applications["/"];

                if (rootApp != null)
                {
                    rootApp.EnabledProtocols = enabledProtocols;
                }
            }

            // Limits
            if (model.limits != null)
            {
                dynamic limits = model.limits;

                site.Limits.MaxBandwidth   = DynamicHelper.To(limits.max_bandwidth, 0, uint.MaxValue) ?? site.Limits.MaxBandwidth;
                site.Limits.MaxConnections = DynamicHelper.To(limits.max_connections, 0, uint.MaxValue) ?? site.Limits.MaxConnections;

                if (site.Limits.Schema.HasAttribute(MaxUrlSegmentsAttribute))
                {
                    site.Limits.MaxUrlSegments = DynamicHelper.To(limits.max_url_segments, 0, 16383) ?? site.Limits.MaxUrlSegments;
                }

                long?connectionTimeout = DynamicHelper.To(limits.connection_timeout, 0, ushort.MaxValue);
                site.Limits.ConnectionTimeout = (connectionTimeout != null) ? TimeSpan.FromSeconds(connectionTimeout.Value) : site.Limits.ConnectionTimeout;
            }

            // Bindings
            if (model.bindings != null)
            {
                IEnumerable <dynamic> bindings = (IEnumerable <dynamic>)model.bindings;

                // If the user passes an object for the bindings property rather than an array we will hit an exception when we try to access any property in
                // the foreach loop.
                // This means that the bindings collection won't be deleted, so the bindings are safe from harm.

                List <Binding> newBindings = new List <Binding>();

                // Iterate over the bindings to create a new binding list
                foreach (dynamic binding in bindings)
                {
                    // Extract data from binding
                    string ipAddress = DynamicHelper.Value(binding.ip_address);
                    long?  port      = DynamicHelper.To(binding.port, 1, 65535);
                    string hostname  = DynamicHelper.Value(binding.hostname) ?? "";

                    bool?  isHttps              = DynamicHelper.To <bool>(binding.is_https);
                    string certificateHash      = null;
                    string certificateStoreName = null;

                    byte[] hashBytes = null;

                    // Validate that data forms valid binding
                    if (ipAddress == null)
                    {
                        throw new ApiArgumentException("binding.ip_address");
                    }
                    else if (port == null)
                    {
                        throw new ApiArgumentException("binding.port");
                    }
                    else if (isHttps == null)
                    {
                        throw new ApiArgumentException("binding.is_https");
                    }

                    if (isHttps.Value)
                    {
                        if (binding.certificate == null || !(binding.certificate is JObject))
                        {
                            throw new ApiArgumentException("certificate");
                        }

                        dynamic certificate = binding.certificate;
                        string  uuid        = DynamicHelper.Value(certificate.id);

                        if (string.IsNullOrEmpty(uuid))
                        {
                            throw new ApiArgumentException("certificate.id");
                        }

                        CertificateId id = new CertificateId(uuid);
                        certificateHash      = id.Thumbprint;
                        certificateStoreName = Enum.GetName(typeof(StoreName), id.StoreName);

                        List <byte> bytes = new List <byte>();

                        // Decode the hex string of the certificate hash into bytes
                        for (int i = 0; i < id.Thumbprint.Length; i += 2)
                        {
                            bytes.Add(Convert.ToByte(id.Thumbprint.Substring(i, 2), 16));
                        }

                        hashBytes = bytes.ToArray();
                    }

                    // Create binding
                    Binding newBinding = site.Bindings.CreateElement();

                    // If format of the information is incorrect throws ArgumentException but does not populate ParamName
                    newBinding.BindingInformation = $"{ipAddress}:{port}:{hostname}";
                    newBinding.Protocol           = isHttps.Value ? "https" : "http";

                    // Attempting to get or set the certificate hash when the protocol is not https will raise an error -msdn
                    if (isHttps.Value)
                    {
                        // The specified certificate must be in the store with a private key or else there will be an exception when we commit
                        newBinding.CertificateHash      = hashBytes;
                        newBinding.CertificateStoreName = certificateStoreName;
                    }

                    // Add to bindings list
                    newBindings.Add(newBinding);
                }

                // All bindings have been verified and added to the list
                // Clear the old list, and add the new
                site.Bindings.Clear();
                newBindings.ForEach(binding => site.Bindings.Add(binding));
            }

            // Set the app pool
            if (model.application_pool != null)
            {
                // Extract the uuid from the application_pool object provided in model
                string appPoolUuid = DynamicHelper.Value(model.application_pool.id);

                // It is an error to provide an application pool object without specifying its id property
                if (appPoolUuid == null)
                {
                    throw new ApiArgumentException("application_pool.id");
                }

                // Create application pool id object from uuid provided, use this to obtain the application pool
                AppPools.AppPoolId appPoolId = AppPoolId.CreateFromUuid(appPoolUuid);
                ApplicationPool    pool      = AppPoolHelper.GetAppPool(appPoolId.Name);

                Application rootApp = site.Applications["/"];

                if (rootApp == null)
                {
                    throw new ApiArgumentException("application_pool", "Root application does not exist.");
                }

                // REVIEW: Should we create the root application if it doesn't exist and they specify an application pool?
                // We decided not to do this for physical_path.
                // Application pool for a site is extracted from the site's root application
                rootApp.ApplicationPoolName = pool.Name;
            }

            return(site);
        }
예제 #25
0
        private static void SetRule(Rule rule, dynamic model)
        {
            try {
                rule.Name            = DynamicHelper.Value(model.name) ?? rule.Name;
                rule.ScanUrl         = DynamicHelper.To <bool>(model.scan_url) ?? rule.ScanUrl;
                rule.ScanQueryString = DynamicHelper.To <bool>(model.scan_query_string) ?? rule.ScanQueryString;

                if (model.headers != null)
                {
                    IEnumerable <dynamic> headers = (IEnumerable <dynamic>)model.headers;

                    // Clear previous headers
                    rule.ScanHeaders.Clear();

                    // Iterate through all headers provided
                    foreach (dynamic header in headers)
                    {
                        // Extract the header string from the dynamic model
                        string value = DynamicHelper.Value(header);
                        if (!String.IsNullOrEmpty(value))
                        {
                            // Add the header to the rule
                            rule.ScanHeaders.Add(value);
                        }
                    }
                }

                if (model.file_extensions != null)
                {
                    IEnumerable <dynamic> appliesTo = (IEnumerable <dynamic>)model.file_extensions;

                    rule.AppliesTo.Clear();

                    foreach (dynamic fileExtension in appliesTo)
                    {
                        string value = DynamicHelper.Value(fileExtension);
                        if (!String.IsNullOrEmpty(value))
                        {
                            rule.AppliesTo.Add(value);
                        }
                    }
                }

                if (model.deny_strings != null)
                {
                    IEnumerable <dynamic> denyStrings = (IEnumerable <dynamic>)model.deny_strings;

                    rule.DenyStrings.Clear();

                    foreach (dynamic denyString in denyStrings)
                    {
                        string value = DynamicHelper.Value(denyString);
                        if (!String.IsNullOrEmpty(value))
                        {
                            rule.DenyStrings.Add(value);
                        }
                    }
                }
            }
            catch (FileLoadException e) {
                throw new LockedException(RequestFilteringGlobals.RequestFilteringSectionName, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }
        }
예제 #26
0
        public async Task <object> Post([FromBody] dynamic model)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            if (model.expires_on == null)
            {
                throw new ApiArgumentException("expires_on");
            }

            string   purpose   = DynamicHelper.Value(model.purpose) ?? string.Empty;
            DateTime?expiresOn = DynamicHelper.Value(model.expires_on) != String.Empty ? DynamicHelper.To <DateTime>(model.expires_on) : null;

            ApiToken token = _keyProvider.GenerateKey(purpose);

            token.Key.ExpiresOn = expiresOn;

            await _keyProvider.SaveKey(token.Key);

            //
            // Create response
            dynamic key = ApiKeyHelper.ToJsonModel(token);

            return(Created(ApiKeyHelper.GetLocation(key.id), key));
        }
예제 #27
0
        private static void SetBinding(Binding binding, dynamic obj)
        {
            string protocol           = DynamicHelper.Value(obj.protocol);
            string bindingInformation = DynamicHelper.Value(obj.binding_information);
            bool?  requireSni         = DynamicHelper.To <bool>(obj.require_sni);

            if (protocol == null)
            {
                throw new ApiArgumentException("binding.protocol");
            }

            binding.Protocol = protocol;

            bool isHttp = protocol.Equals("http") || protocol.Equals("https");

            if (isHttp)
            {
                //
                // HTTP Binding information provides port, ip address, and hostname
                UInt16    port;
                string    hostname;
                IPAddress ipAddress = null;

                if (bindingInformation == null)
                {
                    var ip = DynamicHelper.Value(obj.ip_address);
                    if (ip == "*")
                    {
                        ipAddress = IPAddress.Any;
                    }
                    else if (!IPAddress.TryParse(ip, out ipAddress))
                    {
                        throw new ApiArgumentException("binding.ip_address");
                    }

                    UInt16?p = (UInt16?)DynamicHelper.To(obj.port, 1, UInt16.MaxValue);
                    if (p == null)
                    {
                        throw new ApiArgumentException("binding.port");
                    }
                    port = p.Value;

                    hostname = DynamicHelper.Value(obj.hostname) ?? string.Empty;
                }
                else
                {
                    var parts = bindingInformation.Split(':');
                    if (parts.Length != 3)
                    {
                        throw new ApiArgumentException("binding.binding_information");
                    }

                    if (parts[0] == "*")
                    {
                        ipAddress = IPAddress.Any;
                    }
                    else if (!IPAddress.TryParse(parts[0], out ipAddress))
                    {
                        throw new ApiArgumentException("binding.binding_information");
                    }

                    if (!UInt16.TryParse(parts[1], out port))
                    {
                        throw new ApiArgumentException("binding.binding_information");
                    }

                    hostname = parts[2];
                }

                binding.Protocol = protocol;

                // HTTPS
                if (protocol.Equals("https"))
                {
                    if (string.IsNullOrEmpty(hostname) && requireSni.HasValue && requireSni.Value)
                    {
                        throw new ApiArgumentException("binding.require_sni");
                    }

                    if (obj.certificate == null || !(obj.certificate is JObject))
                    {
                        throw new ApiArgumentException("certificate");
                    }

                    dynamic certificate = obj.certificate;
                    string  uuid        = DynamicHelper.Value(certificate.id);

                    if (string.IsNullOrEmpty(uuid))
                    {
                        throw new ApiArgumentException("certificate.id");
                    }

                    CertificateId id    = new CertificateId(uuid);
                    List <byte>   bytes = new List <byte>();

                    // Decode the hex string of the certificate hash into bytes
                    for (int i = 0; i < id.Thumbprint.Length; i += 2)
                    {
                        bytes.Add(Convert.ToByte(id.Thumbprint.Substring(i, 2), 16));
                    }

                    // The specified certificate must be in the store with a private key or else there will be an exception when we commit
                    binding.CertificateStoreName = Enum.GetName(typeof(StoreName), id.StoreName);
                    binding.CertificateHash      = bytes.ToArray();

                    if (requireSni.HasValue && requireSni.Value && binding.Schema.HasAttribute(sslFlagsAttribute))
                    {
                        binding.SslFlags |= SslFlags.Sni;
                    }
                }

                var ipModel = ipAddress.Equals(IPAddress.Any) ? "*" : ipAddress.ToString();
                binding.BindingInformation = $"{ipModel}:{port}:{hostname}";
            }
            else
            {
                //
                // Custom protocol
                if (string.IsNullOrEmpty(bindingInformation))
                {
                    throw new ApiArgumentException("binding.binding_information");
                }

                binding.BindingInformation = bindingInformation;
            }
        }
예제 #28
0
        public static void UpdateUrl(UrlRule url, dynamic model, Site site, string path, string configPath = null)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }
            if (url.Url == null)
            {
                throw new ArgumentNullException("url.Url");
            }
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            bool   allow  = DynamicHelper.To <bool>(model.allow) ?? url.Allow;
            string newUrl = DynamicHelper.Value(model.url);

            var section = RequestFilteringHelper.GetRequestFilteringSection(site, path, configPath);

            // Url is in as an allow url
            if (url.Allow)
            {
                AlwaysAllowedUrl targetUrl = section.AlwaysAllowedUrls.FirstOrDefault(u => u.Url.Equals(url.Url, StringComparison.OrdinalIgnoreCase));

                if (targetUrl == null)
                {
                    throw new NotFoundException("url");
                }

                section.AlwaysAllowedUrls.Remove(targetUrl);
            }
            // Url is in the configuration as a deny url sequence
            else
            {
                DenyUrlSequence denySequence = section.DenyUrlSequences.FirstOrDefault(u => u.Sequence.Equals(url.Url, StringComparison.OrdinalIgnoreCase));

                if (denySequence == null)
                {
                    throw new NotFoundException("url");
                }

                section.DenyUrlSequences.Remove(denySequence);
            }

            try {
                // The target url has been removed from either allow or deny collection.
                // Add updated url to proper collection

                if (allow)
                {
                    var elem = section.AlwaysAllowedUrls.CreateElement();
                    elem.Url = newUrl ?? url.Url;

                    section.AlwaysAllowedUrls.Add(elem);
                    url.Allow = true;
                }

                else
                {
                    var elem = section.DenyUrlSequences.CreateElement();
                    elem.Sequence = newUrl ?? url.Url;

                    section.DenyUrlSequences.Add(elem);
                    url.Allow = false;
                }

                url.Url = newUrl ?? url.Url;
            }
            catch (FileLoadException e) {
                throw new LockedException(section.SectionPath, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }
        }
예제 #29
0
        public void ChangeAllProperties()
        {
            using (HttpClient client = ApiHttpClient.Create()) {
                EnsureNoSite(client, TEST_SITE_NAME);
                JObject site       = CreateSite(client, TEST_SITE_NAME, TEST_PORT, Configuration.TEST_ROOT_PATH);
                JObject cachedSite = new JObject(site);

                WaitForStatus(client, ref site);

                Assert.True(site != null);

                site["server_auto_start"] = !site.Value <bool>("server_auto_start");
                site["physical_path"]     = Configuration.TEST_ROOT_PATH;
                site["enabled_protocols"] = site.Value <string>("enabled_protocols").Equals("http", StringComparison.OrdinalIgnoreCase) ? "https" : "http";

                // If site status is unknown then we don't know if it will be started or stopped when it becomes available
                // Utilizing the defaults we assume it will go from unkown to started
                site["status"] = Enum.GetName(typeof(Status),
                                              DynamicHelper.To <Status>(site["status"]) ==
                                              Status.Stopped ? Status.Started :
                                              Status.Stopped);

                JObject limits = (JObject)site["limits"];
                limits["connection_timeout"] = limits.Value <long>("connection_timeout") - 1;
                limits["max_bandwidth"]      = limits.Value <long>("max_bandwidth") - 1;
                limits["max_connections"]    = limits.Value <long>("max_connections") - 1;
                limits["max_url_segments"]   = limits.Value <long>("max_url_segments") - 1;

                JArray bindings = site.Value <JArray>("bindings");
                bindings.Clear();
                bindings.Add(JObject.FromObject(new {
                    port       = 63014,
                    ip_address = "40.3.5.15",
                    hostname   = "testhostname",
                    protocol   = "http"
                }));
                bindings.Add(JObject.FromObject(new {
                    port        = 63015,
                    ip_address  = "*",
                    hostname    = "",
                    protocol    = "https",
                    certificate = GetCertificate(client)
                }));

                string result;
                string body = JsonConvert.SerializeObject(site);

                Assert.True(client.Patch(Utils.Self(site), body, out result));

                JObject newSite = JsonConvert.DeserializeObject <JObject>(result);

                WaitForStatus(client, ref newSite);

                Assert.True(Utils.JEquals <bool>(site, newSite, "server_auto_start"));
                Assert.True(Utils.JEquals <string>(site, newSite, "physical_path"));
                Assert.True(Utils.JEquals <string>(site, newSite, "enabled_protocols"));
                Assert.True(Utils.JEquals <string>(site, newSite, "status", StringComparison.OrdinalIgnoreCase));

                Assert.True(Utils.JEquals <long>(site, newSite, "limits.connection_timeout"));
                Assert.True(Utils.JEquals <long>(site, newSite, "limits.max_bandwidth"));
                Assert.True(Utils.JEquals <long>(site, newSite, "limits.max_connections"));
                Assert.True(Utils.JEquals <long>(site, newSite, "limits.max_url_segments"));

                for (var i = 0; i < bindings.Count; i++)
                {
                    var oldBinding = (JObject)bindings[i];
                    var newBinding = (JObject)bindings[i];

                    Assert.True(Utils.JEquals <string>(oldBinding, newBinding, "protocol"));
                    Assert.True(Utils.JEquals <string>(oldBinding, newBinding, "port"));
                    Assert.True(Utils.JEquals <string>(oldBinding, newBinding, "ip_address"));
                    Assert.True(Utils.JEquals <string>(oldBinding, newBinding, "hostname"));

                    if (newBinding.Value <string>("protocol").Equals("https"))
                    {
                        Assert.True(JToken.DeepEquals(oldBinding["certificate"], newBinding["certificate"]));
                    }
                }

                Assert.True(DeleteSite(client, Utils.Self(site)));
            }
        }
        public static void Update(dynamic model, Site site, string path, string configScope = null)
        {
            if (model == null)
            {
                throw new ApiArgumentException("model");
            }

            // Cannot configure at any path below site
            if (site != null && path != "/")
            {
                throw new InvalidScopeTypeException(string.Format("{0}{1}", (site == null ? "" : site.Name), path ?? ""));
            }

            LogSection         logSection         = GetLogSection(site, path, configScope);
            HttpLoggingSection httpLoggingSection = GetHttpLoggingSection(site, path, configScope);

            // Site log settings are set in the site defaults if Configuration target is server
            // If target is a site then the site's logfile element is used
            SiteLogFile siteLogFile = site == null ? ManagementUnit.Current.ServerManager.SiteDefaults.LogFile : site.LogFile;

            try {
                bool?enabled = DynamicHelper.To <bool>(model.enabled);
                if (enabled != null)
                {
                    TrySetLoggingEnabled(enabled.Value, httpLoggingSection, logSection, siteLogFile, site, configScope);
                }

                // Extract rollover from model
                dynamic rollover = model.rollover;
                if (rollover != null && !(rollover is JObject))
                {
                    throw new ApiArgumentException("rollover", ApiArgumentException.EXPECTED_OBJECT);
                }

                // Only accessible at server level
                if (site == null)
                {
                    DynamicHelper.If <bool>((object)model.log_per_site, v => logSection.CentralLogFileMode = v ? CentralLogFileMode.Site : CentralLogFileMode.CentralW3C);
                    DynamicHelper.If <FileLogFormat>((object)model.log_file_format, v => {
                        // Site log mode exposes 4 possible log formats
                        if (logSection.CentralLogFileMode == CentralLogFileMode.Site)
                        {
                            switch (v)
                            {
                            case FileLogFormat.Custom:
                                siteLogFile.LogFormat = LogFormat.Custom;
                                break;

                            case FileLogFormat.Iis:
                                siteLogFile.LogFormat = LogFormat.Iis;
                                break;

                            case FileLogFormat.W3c:
                                siteLogFile.LogFormat = LogFormat.W3c;
                                break;

                            case FileLogFormat.Ncsa:
                                siteLogFile.LogFormat = LogFormat.Ncsa;
                                break;

                            default:
                                throw new ApiArgumentException("log_file_format");
                            }
                        }
                        // Server log mode exposes 2 possible log formats
                        else
                        {
                            switch (v)
                            {
                            case FileLogFormat.W3c:
                                logSection.CentralLogFileMode = CentralLogFileMode.CentralW3C;
                                break;

                            case FileLogFormat.Binary:
                                logSection.CentralLogFileMode = CentralLogFileMode.CentralBinary;
                                break;

                            default:
                                throw new ApiArgumentException("log_file_format");
                            }
                        }
                    });
                    DynamicHelper.If((object)model.log_file_encoding, v => {
                        switch (v.ToLower())
                        {
                        case "utf-8":
                            logSection.LogInUTF8 = true;
                            break;

                        case "ansi":
                            logSection.LogInUTF8 = false;
                            break;

                        default:
                            throw new ApiArgumentException("log_file_encoding");
                        }
                    });

                    // Binary log mode settings
                    if (logSection.CentralLogFileMode == CentralLogFileMode.CentralBinary)
                    {
                        dynamic bSettings = model;


                        CentralBinaryLogFile bFile = logSection.CentralBinaryLogFile;

                        DynamicHelper.If((object)bSettings.directory, v => bFile.Directory = v);

                        if (rollover != null)
                        {
                            DynamicHelper.If <LoggingRolloverPeriod>((object)PeriodFromRepresentation(rollover.period), v => bFile.Period = v);
                            DynamicHelper.If((object)rollover.truncate_size, 1048576, 4294967295, v => bFile.TruncateSize = v);
                            DynamicHelper.If <bool>((object)rollover.use_local_time, v => bFile.LocalTimeRollover         = v);
                        }
                    }

                    // W3C log mode settings
                    if (logSection.CentralLogFileMode == CentralLogFileMode.CentralW3C)
                    {
                        dynamic wSettings = model;

                        CentralW3CLogFile wFile = logSection.CentralW3CLogFile;

                        DynamicHelper.If((object)wSettings.directory, v => wFile.Directory = v);

                        if (rollover != null)
                        {
                            DynamicHelper.If <LoggingRolloverPeriod>((object)PeriodFromRepresentation(rollover.period), v => wFile.Period = v);
                            DynamicHelper.If((object)rollover.truncate_size, 1048576, 4294967295, v => wFile.TruncateSize = v);
                            DynamicHelper.If <bool>((object)rollover.use_local_time, v => wFile.LocalTimeRollover         = v);
                        }

                        if (wSettings.log_fields != null)
                        {
                            try {
                                wFile.LogExtFileFlags = SetLogFieldFlags(wFile.LogExtFileFlags, wSettings.log_fields);
                            }
                            catch (ApiArgumentException e) {
                                throw new ApiArgumentException("w3c_settings.log_fields", e);
                            }
                            catch (JsonSerializationException e) {
                                throw new ApiArgumentException("w3c_settings.log_fields", e);
                            }
                        }
                    }
                }

                //
                // Per site mode format
                DynamicHelper.If <FileLogFormat>((object)model.log_file_format, v => {
                    if (logSection.CentralLogFileMode == CentralLogFileMode.Site)
                    {
                        switch (v)
                        {
                        case FileLogFormat.Custom:
                            siteLogFile.LogFormat = LogFormat.Custom;
                            break;

                        case FileLogFormat.Iis:
                            siteLogFile.LogFormat = LogFormat.Iis;
                            break;

                        case FileLogFormat.W3c:
                            siteLogFile.LogFormat = LogFormat.W3c;
                            break;

                        case FileLogFormat.Ncsa:
                            siteLogFile.LogFormat = LogFormat.Ncsa;
                            break;

                        default:
                            throw new ApiArgumentException("log_file_format");
                        }
                    }
                });

                // Site settings
                if (logSection.CentralLogFileMode == CentralLogFileMode.Site)
                {
                    dynamic siteSettings = model;

                    DynamicHelper.If((object)siteSettings.directory, v => siteLogFile.Directory = v);

                    if (rollover != null)
                    {
                        DynamicHelper.If <LoggingRolloverPeriod>((object)PeriodFromRepresentation(rollover.period), v => siteLogFile.Period = v);
                        DynamicHelper.If((object)rollover.truncate_size, 1048576, 4294967295, v => siteLogFile.TruncateSize = v);
                        DynamicHelper.If <bool>((object)rollover.use_local_time, v => siteLogFile.LocalTimeRollover         = v);
                    }

                    if (siteSettings.log_fields != null)
                    {
                        try {
                            siteLogFile.LogExtFileFlags = SetLogFieldFlags(siteLogFile.LogExtFileFlags, siteSettings.log_fields);
                        }
                        catch (ApiArgumentException e) {
                            throw new ApiArgumentException("site_settings.log_fields", e);
                        }
                        catch (JsonSerializationException e) {
                            throw new ApiArgumentException("site_settings.log_fields", e);
                        }
                    }

                    if (siteSettings.log_target != null && siteLogFile.Schema.HasAttribute(LogTargetW3CAttribute))
                    {
                        try {
                            Dictionary <string, bool> logTargets = JsonConvert.DeserializeObject <Dictionary <string, bool> >(siteSettings.log_target.ToString());

                            if (logTargets == null)
                            {
                                throw new ApiArgumentException("site_settings.log_target_w3c");
                            }

                            LogTargetW3C logTargetW3C = siteLogFile.LogTargetW3C;

                            if (logTargets.ContainsKey("etw"))
                            {
                                if (logTargets["etw"])
                                {
                                    logTargetW3C |= LogTargetW3C.ETW;
                                }
                                else
                                {
                                    logTargetW3C &= ~LogTargetW3C.ETW;
                                }
                            }
                            if (logTargets.ContainsKey("file"))
                            {
                                if (logTargets["file"])
                                {
                                    logTargetW3C |= LogTargetW3C.File;
                                }
                                else
                                {
                                    logTargetW3C &= ~LogTargetW3C.File;
                                }
                            }

                            siteLogFile.LogTargetW3C = logTargetW3C;
                        }
                        catch (JsonSerializationException e) {
                            throw new ApiArgumentException("site_settings.log_fields", e);
                        }
                    }

                    if (siteSettings.custom_log_fields != null && siteLogFile.Schema.HasChildElement(CustomFieldsElement))
                    {
                        IEnumerable <dynamic> customFields = siteSettings.custom_log_fields;

                        List <CustomField> tempCustFields = new List <CustomField>();

                        foreach (dynamic field in customFields)
                        {
                            string fieldName  = DynamicHelper.Value(field.field_name);
                            string sourceName = DynamicHelper.Value(field.source_name);
                            CustomLogFieldSourceType?sourceType = SourceTypeFromRepresentation(field.source_type);

                            if (string.IsNullOrEmpty(fieldName))
                            {
                                throw new ApiArgumentException("custom_log_field.field_name");
                            }
                            if (string.IsNullOrEmpty(sourceName))
                            {
                                throw new ApiArgumentException("custom_log_field.source_name");
                            }
                            if (sourceType == null)
                            {
                                throw new ApiArgumentException("custom_log_field.source_type");
                            }

                            tempCustFields.Add(new CustomField()
                            {
                                FieldName  = fieldName,
                                SourceName = sourceName,
                                SourceType = sourceType.Value
                            });
                        }

                        siteLogFile.CustomLogFields.Clear();
                        tempCustFields.ForEach(f => siteLogFile.CustomLogFields.Add(f.FieldName, f.SourceName, f.SourceType));
                    }
                }


                if (model.metadata != null)
                {
                    DynamicHelper.If <OverrideMode>((object)model.metadata.override_mode, v => httpLoggingSection.OverrideMode = v);
                }
            }
            catch (FileLoadException e) {
                throw new LockedException(logSection.SectionPath + "|" + httpLoggingSection.SectionPath, e);
            }
            catch (DirectoryNotFoundException e) {
                throw new ConfigScopeNotFoundException(e);
            }
        }