| /* |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| using System; |
| using System.Collections.Generic; |
| using System.Diagnostics; |
| using System.IO; |
| using System.Linq; |
| using System.Text; |
| using System.Text.RegularExpressions; |
| using System.Windows; |
| using System.Windows.Resources; |
| using System.Xml.Linq; |
| |
| namespace WPCordovaClassLib.CordovaLib |
| { |
| class ConfigHandler |
| { |
| public class PluginConfig |
| { |
| public PluginConfig(string name, bool autoLoad = false, string className = "") |
| { |
| Name = name; |
| isAutoLoad = autoLoad; |
| ClassName = className; |
| } |
| public string Name; |
| public bool isAutoLoad; |
| public string ClassName; |
| } |
| |
| protected Dictionary<string, PluginConfig> AllowedPlugins; |
| protected List<string> AllowedDomains; |
| protected Dictionary<string, string> Preferences; |
| |
| public string ContentSrc { get; private set; } |
| |
| protected bool AllowAllDomains = false; |
| protected bool AllowAllPlugins = false; |
| |
| public ConfigHandler() |
| { |
| AllowedPlugins = new Dictionary<string, PluginConfig>(); |
| AllowedDomains = new List<string>(); |
| Preferences = new Dictionary<string, string>(); |
| } |
| |
| public string GetPreference(string key) |
| { |
| return Preferences.ContainsKey(key.ToLowerInvariant()) ? Preferences[key.ToLowerInvariant()] : null; |
| } |
| |
| protected static string[] AllowedSchemes = { "http", "https", "ftp", "ftps" }; |
| protected bool SchemeIsAllowed(string scheme) |
| { |
| return AllowedSchemes.Contains(scheme); |
| } |
| |
| protected void AddWhiteListEntry(string origin, bool allowSubdomains) |
| { |
| |
| if (origin == "*") |
| { |
| AllowAllDomains = true; |
| } |
| |
| if (AllowAllDomains) |
| { |
| return; |
| } |
| |
| string hostMatchingRegex = ""; |
| string hostName; |
| |
| try |
| { |
| |
| Uri uri = new Uri(origin.Replace("*", "replaced-text"), UriKind.Absolute); |
| |
| string tempHostName = uri.Host.Replace("replaced-text", "*"); |
| //if (uri.HostNameType == UriHostNameType.Dns){} |
| // starts with wildcard match - we make the first '.' optional (so '*.org.apache.cordova' will match 'org.apache.cordova') |
| if (tempHostName.StartsWith("*.")) |
| { //"(\\s{0}|*.)" |
| hostName = @"\w*.*" + tempHostName.Substring(2).Replace(".", @"\.").Replace("*", @"\w*"); |
| } |
| else |
| { |
| hostName = tempHostName.Replace(".", @"\.").Replace("*", @"\w*"); |
| } |
| // "^https?://" |
| hostMatchingRegex = uri.Scheme + "://" + hostName + uri.PathAndQuery; |
| //Debug.WriteLine("Adding regex :: " + hostMatchingRegex); |
| AllowedDomains.Add(hostMatchingRegex); |
| |
| } |
| catch (Exception) |
| { |
| Debug.WriteLine("Invalid Whitelist entry (probably missing the protocol):: " + origin); |
| } |
| |
| } |
| |
| /** |
| |
| An access request is granted for a given URI if there exists an item inside the access-request list such that: |
| |
| - The URI's scheme component is the same as scheme; and |
| - if subdomains is false or if the URI's host component is not a domain name (as defined in [RFC1034]), the URI's host component is the same as host; or |
| - if subdomains is true, the URI's host component is either the same as host, or is a subdomain of host (as defined in [RFC1034]); and |
| - the URI's port component is the same as port. |
| |
| **/ |
| |
| public bool URLIsAllowed(string url) |
| { |
| // easy case first |
| if (this.AllowAllDomains) |
| { |
| return true; |
| } |
| else |
| { |
| // start simple |
| Uri uri = new Uri(url, UriKind.RelativeOrAbsolute); |
| if (uri.IsAbsoluteUri) |
| { |
| if (this.SchemeIsAllowed(uri.Scheme)) |
| { |
| // additional test because our pattern will always have a trailing '/' |
| string matchUrl = url; |
| if (uri.PathAndQuery == "/") |
| { |
| matchUrl = url + "/"; |
| } |
| foreach (string pattern in AllowedDomains) |
| { |
| if (Regex.IsMatch(matchUrl, pattern)) |
| { |
| // make sure it is at the start, and not part of the query string |
| // special case :: http://some.other.domain/page.html?x=1&g=http://build.apache.org/ |
| if (Regex.IsMatch(uri.Scheme + "://" + uri.Host + "/", pattern) || |
| (!Regex.IsMatch(uri.PathAndQuery, pattern))) |
| { |
| return true; |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public string GetNamespaceForCommand(string key) |
| { |
| if(AllowedPlugins.Keys.Contains(key)) |
| { |
| return AllowedPlugins[key].Name; |
| } |
| |
| return ""; |
| } |
| |
| public bool IsPluginAllowed(string key) |
| { |
| return AllowAllPlugins || AllowedPlugins.Keys.Contains(key); |
| } |
| |
| public string[] AutoloadPlugins |
| { |
| get |
| { |
| // TODO: |
| var res = from results in AllowedPlugins.TakeWhile(p => p.Value.isAutoLoad) |
| select results.Value.Name; |
| |
| return res.ToArray<string>(); |
| } |
| } |
| |
| private void LoadPluginFeatures(XDocument document) |
| { |
| var features = from feats in document.Descendants() |
| where feats.Name.LocalName == "feature" |
| select feats; |
| |
| foreach (var feature in features) |
| { |
| string name = (string)feature.Attribute("name"); |
| var value = (from results in feature.Descendants() |
| where results.Name.LocalName == "param" && ((string)results.Attribute("name") == "wp-package") |
| select results).FirstOrDefault(); |
| |
| var autoloadNode = (from results in feature.Descendants() |
| where results.Name.LocalName == "param" && ((string)results.Attribute("name") == "onload") |
| select results).FirstOrDefault(); |
| bool isAutoLoad = false; |
| if (autoloadNode != null) |
| { |
| isAutoLoad = ((string)autoloadNode.Attribute("value") == "true"); |
| } |
| |
| if (value != null) |
| { |
| string key = (string)value.Attribute("value"); |
| Debug.WriteLine("Adding feature.value=" + key); |
| PluginConfig pConfig = new PluginConfig(key, isAutoLoad); |
| AllowedPlugins[name] = pConfig; |
| |
| |
| } |
| |
| |
| } |
| } |
| |
| public void LoadAppPackageConfig() |
| { |
| StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("config.xml", UriKind.Relative)); |
| |
| if (streamInfo != null) |
| { |
| StreamReader sr = new StreamReader(streamInfo.Stream); |
| //This will Read Keys Collection for the xml file |
| XDocument document = XDocument.Parse(sr.ReadToEnd()); |
| |
| LoadPluginFeatures(document); |
| |
| var preferences = from results in document.Descendants() |
| where results.Name.LocalName == "preference" |
| select new |
| { |
| name = (string)results.Attribute("name"), |
| value = (string)results.Attribute("value") |
| }; |
| |
| foreach (var pref in preferences) |
| { |
| Preferences[pref.name.ToLowerInvariant()] = pref.value; |
| } |
| |
| var accessList = from results in document.Descendants() |
| where results.Name.LocalName == "access" |
| select new |
| { |
| origin = (string)results.Attribute("origin"), |
| subdomains = (string)results.Attribute("subdomains") == "true" |
| }; |
| |
| foreach (var accessElem in accessList) |
| { |
| AddWhiteListEntry(accessElem.origin, accessElem.subdomains); |
| } |
| |
| var contentsTag = (from results in document.Descendants() |
| where results.Name.LocalName == "content" |
| select results).FirstOrDefault(); |
| |
| if (contentsTag != null) |
| { |
| var src = contentsTag.Attribute("src"); |
| ContentSrc = (string)src.Value; |
| } |
| } |
| else |
| { |
| // no config.xml, allow all |
| AllowAllDomains = true; |
| AllowAllPlugins = true; |
| } |
| } |
| } |
| } |