Beispiel #1
0
        /// <summary>
        /// Process method checks for presence of a session id and sequence
        /// number. If they do not exist then they are initialized in evidence.
        /// If they do exist in evidence then the sequence number is incremented
        /// and added back to the evidence.
        /// </summary>
        /// <param name="data">
        /// The <see cref="IFlowData"/> instance to process.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown if the supplied data instance is null
        /// </exception>
        protected override void ProcessInternal(IFlowData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            var evidence = data.GetEvidence().AsDictionary();

            // If the evidence does not contain a session id then create a new one.
            if (evidence.ContainsKey(Constants.EVIDENCE_SESSIONID) == false)
            {
                data.AddEvidence(Constants.EVIDENCE_SESSIONID, GetNewSessionId());
            }

            // If the evidence does not have a sequence then add one. Otherwise
            // increment it.
            if (evidence.ContainsKey(Constants.EVIDENCE_SEQUENCE) == false)
            {
                data.AddEvidence(Constants.EVIDENCE_SEQUENCE, 1);
            }
            else if (evidence.TryGetValue(Constants.EVIDENCE_SEQUENCE, out object sequence))
            {
                if (sequence is int result || (sequence is string seq && int.TryParse(seq, out result)))
                {
                    data.AddEvidence(Constants.EVIDENCE_SEQUENCE, result + 1);
                }
                else
                {
                    data.AddError(new Exception(Messages.MessageFailSequenceNumberParse), this);
                    Logger.LogError(Messages.MessageFailSequenceNumberIncrement);
                }
            }
        /// <summary>
        /// Process the math operation by parsing the text and computing the
        /// result.
        /// </summary>
        /// <param name="data">FlowData to add the result to</param>
        protected override void ProcessInternal(IFlowData data)
        {
            MathData elementData = (MathData)data.GetOrAdd(
                ElementDataKeyTyped,
                (f) => base.CreateElementData(f));
            string operation = ((string)data.GetEvidence()[EvidenceKeys[0]]);

            if (operation != null)
            {
                // Parse the text representation of the mathematical operation.
                elementData.Operation = operation
                                        .Replace("plus", "+")
                                        .Replace("minus", "-")
                                        .Replace("divide", "/")
                                        .Replace("times", "*");
                // Compute the value of the operation.
                elementData.Result = Convert.ToDouble(
                    new DataTable().Compute(elementData.Operation, ""));
            }
            else
            {
                // Nothing provided, so just set zeros.
                elementData.Operation = "0";
                elementData.Result    = 0;
            }
        }
        /// <summary>
        /// Generate the Content to send in the POST request. The evidence keys
        /// e.g. 'query.' and 'header.' have an order of precedence. These are
        /// added to the evidence in reverse order, if there is conflict then
        /// the queryData value is overwritten.
        ///
        /// 'query.' evidence should take precedence over all other evidence.
        /// If there are evidence keys other than 'query.' that conflict then
        /// this is unexpected so an error will be logged.
        /// </summary>
        /// <param name="data"></param>
        /// <returns>Evidence in a FormUrlEncodedContent object</returns>
        private FormUrlEncodedContent GetContent(IFlowData data)
        {
            var queryData = new Dictionary <string, string>();

            queryData.Add("resource", _resourceKey);

            if (string.IsNullOrWhiteSpace(_licenseKey) == false)
            {
                queryData.Add("license", _licenseKey);
            }

            var evidence = data.GetEvidence().AsDictionary();

            // Add evidence in reverse alphabetical order, excluding special keys.
            AddQueryData(queryData, evidence, evidence
                         .Where(e =>
                                KeyHasPrefix(e, Core.Constants.EVIDENCE_QUERY_PREFIX) == false &&
                                KeyHasPrefix(e, Core.Constants.EVIDENCE_HTTPHEADER_PREFIX) == false &&
                                KeyHasPrefix(e, Core.Constants.EVIDENCE_COOKIE_PREFIX) == false)
                         .OrderByDescending(e => e.Key));
            // Add cookie evidence.
            AddQueryData(queryData, evidence, evidence
                         .Where(e => KeyHasPrefix(e, Core.Constants.EVIDENCE_COOKIE_PREFIX)));
            // Add header evidence.
            AddQueryData(queryData, evidence, evidence
                         .Where(e => KeyHasPrefix(e, Core.Constants.EVIDENCE_HTTPHEADER_PREFIX)));
            // Add query evidence.
            AddQueryData(queryData, evidence, evidence
                         .Where(e => KeyHasPrefix(e, Core.Constants.EVIDENCE_QUERY_PREFIX)));

            var content = new FormUrlEncodedContent(queryData);

            return(content);
        }
Beispiel #4
0
        /// <summary>
        /// Perform processing for this engine
        /// </summary>
        /// <param name="data">
        /// The <see cref="IFlowData"/> instance containing data for the
        /// current request.
        /// </param>
        /// <param name="deviceData">
        /// The <see cref="IDeviceDataHash"/> instance to populate with
        /// property values
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown if a required parameter is null
        /// </exception>
        protected override void ProcessEngine(IFlowData data, IDeviceDataHash deviceData)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (deviceData == null)
            {
                throw new ArgumentNullException(nameof(deviceData));
            }

            using (var relevantEvidence = new EvidenceDeviceDetectionSwig())
            {
                foreach (var evidenceItem in data.GetEvidence().AsDictionary())
                {
                    if (EvidenceKeyFilter.Include(evidenceItem.Key))
                    {
                        relevantEvidence.Add(new KeyValuePair <string, string>(
                                                 evidenceItem.Key,
                                                 evidenceItem.Value.ToString()));
                    }
                }

                // The results object is disposed in the dispose method of the
                // DeviceDataHash object.
#pragma warning disable CA2000 // Dispose objects before losing scope
                (deviceData as DeviceDataHash).SetResults(new ResultsSwigWrapper(_engine.process(relevantEvidence)));
#pragma warning restore CA2000 // Dispose objects before losing scope
            }
        }
Beispiel #5
0
        /// <summary>
        /// Generate any required parameters for the JSON request.
        /// Any query parameters from this request that were ingested by
        /// the Pipeline are added to the request URL by the JavaScript.
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        protected virtual Dictionary <string, string> GetParameters(IFlowData data)
        {
            if (data == null)
            {
                throw new ArgumentException(Messages.ExceptionFlowDataIsNull);
            }

            var parameters = data
                             .GetEvidence()
                             .AsDictionary()
                             .Where(e => e.Key.StartsWith(Core.Constants.EVIDENCE_QUERY_PREFIX,
                                                          StringComparison.OrdinalIgnoreCase))
                             .Where(e => ExcludedParameters.Contains(e.Key) == false)
                             .ToDictionary(k =>
            {
                var dotPos = k.Key.IndexOf(Core.Constants.EVIDENCE_SEPERATOR,
                                           StringComparison.OrdinalIgnoreCase);
                return(WebUtility.UrlEncode(k.Key.Remove(0, dotPos + 1)));
            }, v => WebUtility.UrlEncode(v.Value.ToString()));

            // Serialise the parameters
            var paramsObject =
                JsonConvert.SerializeObject(parameters, Formatting.Indented);

            return(parameters);
        }
Beispiel #6
0
        protected override void ProcessInternal(IFlowData data)
        {
            TestElementData elementData = data.GetOrAdd(
                ElementDataKeyTyped,
                (p) => new TestElementData(p));
            int value = (int)data.GetEvidence()[EvidenceKeys[0]];

            elementData.Result = value * 5;
        }
Beispiel #7
0
        /// <summary>
        /// Process the client IP address by splitting the segments into an
        /// array
        /// </summary>
        /// <param name="data">FlowData to add the result to</param>
        protected override void ProcessInternal(IFlowData data)
        {
            SplitIpData elementData = (SplitIpData)data.GetOrAdd(
                ElementDataKeyTyped,
                (f) => base.CreateElementData(f));
            string ip = ((string)data.GetEvidence()[EvidenceKeys[0]]);

            elementData.ClientIp = ip.Split('.', ':');
        }
Beispiel #8
0
        public void ValidateData(IFlowData data, bool validEvidence = true)
        {
            var elementData = data.GetFromElement(_engine);
            var dict        = elementData.AsDictionary();

            foreach (var property in _engine.Properties
                     .Where(p => p.Available &&
                            // The JavascriptImageOptimiser property is deprecated.
                            // It exists in the meta-data but is never populated
                            // so we need to ignore it here.
                            p.Name.Equals("JavascriptImageOptimiser", StringComparison.OrdinalIgnoreCase) == false))
            {
                Assert.IsTrue(dict.ContainsKey(property.Name));
                IAspectPropertyValue value = dict[property.Name] as IAspectPropertyValue;
                if (validEvidence)
                {
                    Assert.IsTrue(value.HasValue);
                }
                else
                {
                    if (property.Category.Equals("Device Metrics"))
                    {
                        Assert.IsTrue(value.HasValue);
                    }
                    else
                    {
                        Assert.IsFalse(value.HasValue);
                        if (EvidenceContainsUserAgent(data) == false)
                        {
                            Assert.AreEqual("The evidence required to determine" +
                                            " this property was not supplied. The most" +
                                            " common evidence passed to this engine is" +
                                            " 'header.user-agent'.", value.NoValueMessage);
                        }
                        else
                        {
                            Assert.AreEqual("No matching profiles could be " +
                                            "found for the supplied evidence. A 'best " +
                                            "guess' can be returned by configuring more " +
                                            "lenient matching rules. See " +
                                            "https://51degrees.com/documentation/_device_detection__features__false_positive_control.html", value.NoValueMessage);
                        }
                    }
                }
            }
            Assert.IsTrue(string.IsNullOrEmpty(elementData.DeviceId.Value) == false);
            if (validEvidence == false)
            {
                Assert.AreEqual("0-0-0-0", elementData.DeviceId.Value);
            }

            var validKeys = data.GetEvidence().AsDictionary().Keys.Where(
                k => _engine.EvidenceKeyFilter.Include(k)).Count();

            Assert.AreEqual(validKeys, elementData.UserAgents.Value.Count);
        }
        /// <summary>
        /// Generate the Content to send in the POST request
        /// </summary>
        /// <param name="data"></param>
        /// <returns>Evidence in a FormUrlEncodedContent object</returns>
        private FormUrlEncodedContent GetContent(IFlowData data)
        {
            var evidence = data.GetEvidence().AsDictionary();

            var queryData = new Dictionary<string, string>();

            queryData.Add("resource", _resourceKey);

            if(string.IsNullOrWhiteSpace(_licenseKey) == false)
            {
                queryData.Add("license", _licenseKey);
            }

            foreach (var item in evidence) {
                var key = item.Key.Split(Core.Constants.EVIDENCE_SEPERATOR.ToCharArray());
                queryData.Add(key[key.Length - 1], item.Value.ToString());
            }

            var content = new FormUrlEncodedContent(queryData);
            return content;
        }
Beispiel #10
0
        /// <summary>
        /// Process the flow data
        /// </summary>
        /// <param name="data">
        /// The <see cref="IFlowData"/>
        /// </param>
        protected override void ProcessInternal(IFlowData data)
        {
            ListSplitterElementData elementData = data.GetOrAdd(
                ElementDataKeyTyped,
                (p) => new ListSplitterElementData(p));
            // Get the source string
            string source = (string)data.GetEvidence()[EvidenceKeys[0]];
            // Split the source string using the configured delimiter.
            var results = source
                          .Split(_delimiters, StringSplitOptions.RemoveEmptyEntries)
                          .ToList();

            elementData.Result = new List <string>();
            // Iterate through the resulting strings, checking if they are
            // over the max length.
            // If any string is too long then it is split into chunks of
            // max length.
            for (int i = 0; i < results.Count; i++)
            {
                var result = results[i];
                while (result.Length > _maxLength)
                {
                    // Take the first _maxLength characters and add them
                    // to the element data result.
                    elementData.Result.Add(result.Remove(_maxLength));
                    // Remove the first _maxLength characters from the
                    // string and repeat.
                    result = result.Substring(_maxLength);
                }
                // Add the string to the element data result.
                if (result.Length > 0)
                {
                    elementData.Result.Add(result);
                }
            }
        }
Beispiel #11
0
        private void SetUp(IFlowData data)
        {
            var  host     = Host;
            var  protocol = Protocol;
            bool supportsPromises;

            if (string.IsNullOrEmpty(host))
            {
                // Try and get the request host name so it can be used to request
                // the Json refresh in the JavaScript code.
                data.TryGetEvidence(Constants.EVIDENCE_HOST_KEY, out host);
            }
            if (string.IsNullOrEmpty(protocol))
            {
                // Try and get the request protocol so it can be used to request
                // the JSON refresh in the JavaScript code.
                data.TryGetEvidence(Constants.EVIDENCE_PROTOCOL, out protocol);
            }
            // Couldn't get protocol from anywhere
            if (string.IsNullOrEmpty(protocol))
            {
                protocol = Constants.DEFAULT_PROTOCOL;
            }

            // If device detection is in the Pipeline then we can check
            // if the client's browser supports promises.
            // This can be used to customize the JavaScript response.
            try
            {
                var promise = data.GetAs <IAspectPropertyValue <string> >("Promise");
                supportsPromises = promise != null && promise.HasValue && promise.Value == "Full";
            }
            catch (PipelineDataException) { supportsPromises = false; }
            catch (InvalidCastException) { supportsPromises = false; }
            catch (KeyNotFoundException) { supportsPromises = false; }

            // Get the JSON include to embed into the JavaScript include.
            string jsonObject = string.Empty;

            try
            {
                jsonObject = data.Get <IJsonBuilderElementData>().Json;
            }
            catch (KeyNotFoundException ex)
            {
                throw new PipelineConfigurationException(
                          Messages.ExceptionJsonBuilderNotRun, ex);
            }

            // Generate any required parameters for the JSON request.
            List <string> parameters = new List <string>();

            // Any query parameters from this request that were ingested by
            // the Pipeline are added to the request URL that will appear
            // in the JavaScript.
            var queryEvidence = data
                                .GetEvidence()
                                .AsDictionary()
                                .Where(e => e.Key.StartsWith(Core.Constants.EVIDENCE_QUERY_PREFIX,
                                                             StringComparison.OrdinalIgnoreCase))
                                .Select(k =>
            {
                var dotPos = k.Key.IndexOf(Core.Constants.EVIDENCE_SEPERATOR,
                                           StringComparison.OrdinalIgnoreCase);
                return($"{WebUtility.UrlEncode(k.Key.Remove(0, dotPos + 1))}" +
                       $"={WebUtility.UrlEncode(k.Value.ToString())}");
            });

            parameters.AddRange(queryEvidence);

            string queryParams = string.Join("&", parameters);
            string endpoint    = Endpoint;

            Uri url = null;

            if (string.IsNullOrWhiteSpace(protocol) == false &&
                string.IsNullOrWhiteSpace(host) == false &&
                string.IsNullOrWhiteSpace(endpoint) == false)
            {
                var endpointHasSlash = endpoint[0] == '/';
                var hostHasSlash     = host[host.Length - 1] == '/';
                // if there is no slash between host and endpoint then add one.
                if (endpointHasSlash == false && hostHasSlash == false)
                {
                    endpoint = $"/{endpoint}";
                }
                // if there are two slashes between host and endpoint then remove one.
                else if (endpointHasSlash == true && hostHasSlash == true)
                {
                    endpoint = endpoint.Substring(1);
                }

                url = new Uri($"{protocol}://{host}{endpoint}" +
                              (String.IsNullOrEmpty(queryParams) ? "" : $"?{queryParams}"));
            }

            // With the gathered resources, build a new JavaScriptResource.
            BuildJavaScript(data, jsonObject, supportsPromises, url);
        }