/* * Copyright (C) Alibaba Cloud Computing * All rights reserved. * * 版权所有 (C)阿里云计算有限公司 */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; namespace Aliyun.OSS { /// /// Conditions匹配方式。 /// public enum MatchMode { /// /// 未知的 /// Unknown, /// /// 精确匹配 /// Exact, /// /// 前缀匹配 /// StartWith, /// /// 范围匹配 /// Range }; /// /// Conditions元组类型,目前支持二元组({ ... })、三元组([ ... ])。 /// internal enum TupleType { Unknown, Two, Three }; /// /// 抽象Condition项。 /// internal abstract class AbstractConditionItem { public string Name { get; set; } public MatchMode MatchMode { get; set; } public TupleType TupleType { get; set; } protected AbstractConditionItem(string name, MatchMode matchMode, TupleType tupleType) { Name = name; MatchMode = matchMode; TupleType = tupleType; } public abstract string Jsonize(); } /// /// Equal类型条件项。 /// internal class EqualConditionItem : AbstractConditionItem { public string Value { get; set; } public EqualConditionItem(string name, string value) : this(name, value, TupleType.Two) { } public EqualConditionItem(string name, string value, TupleType tupleType) : base(name, MatchMode.Exact, tupleType) { Value = value; } public override string Jsonize() { string jsonizedCond = null; switch (TupleType) { case TupleType.Two: jsonizedCond = String.Format("{{\"{0}\":\"{1}\"}},", Name, Value); break; case TupleType.Three: jsonizedCond = String.Format("[\"eq\",\"${0}\",\"{1}\"],", Name, Value); break; default: throw new InvalidEnumArgumentException("Invalid tuple type " + TupleType.ToString()); } return jsonizedCond; } } /// /// StartWith类型条件项。 /// internal class StartWithConditionItem : AbstractConditionItem { public string Value { get; set; } public StartWithConditionItem(string name, string value) : base(name, MatchMode.StartWith, TupleType.Three) { Value = value; } public override string Jsonize() { return String.Format("[\"starts-with\",\"${0}\",\"{1}\"],", Name, Value); } } /// /// ContentLengthRange类型条件项。 /// internal class RangeConditionItem : AbstractConditionItem { public long Minimum { get; set; } public long Maximum { get; set; } public RangeConditionItem(string name, long min, long max) : base(name, MatchMode.Range, TupleType.Three) { Minimum = min; Maximum = max; } public override string Jsonize() { return String.Format("[\"content-length-range\",{0},{1}],", Minimum, Maximum); } } /// /// Conditions列表,用于指定 Post 请求表单域的合法值。 /// public class PolicyConditions { /// /// 文件长度范围 /// public const string CondContentLengthRange = "content-length-range"; /// /// 文件被下载时的网页的缓存行为 /// public const string CondCacheControl = "Cache-Control"; /// /// RFC2616中定义的HTTP请求内容类型 /// public const string CondContentType = "Content-Type"; /// /// 文件被下载时的名称 /// public const string CondContentDisposition = "Content-Disposition"; /// /// 文件被下载时的内容编码格式 /// public const string CondContentEncoding = "Content-Encoding"; /// /// 过期时间 /// public const string CondExpires = "Expires"; /// /// 名称 /// public const string CondKey = "key"; /// /// 成功时的重定向 /// public const string CondSuccessActionRedirect = "success_action_redirect"; /// /// 成功时的状态 /// public const string CondSuccessActionStatus = "success_action_status"; /// /// 用户自定义meta元素的前缀x-oss-meta- /// public const string CondXOssMetaPrefix = "x-oss-meta-"; private IList _conds = new List(); /// /// 采用默认匹配方式(精确匹配)添加Conditions项。 /// /// Condition名称。 /// Condition数值。 public void AddConditionItem(string name, string value) { MatchRuleChecker.Check(MatchMode.Exact, name); _conds.Add(new EqualConditionItem(name, value)); } /// /// 采用指定匹配模式添加Conditions项。 /// /// Conditions匹配方式。 /// Condition名称。 /// Condition数值。 public void AddConditionItem(MatchMode matchMode, string name, string value) { MatchRuleChecker.Check(matchMode, name); switch (matchMode) { case MatchMode.Exact: _conds.Add(new EqualConditionItem(name, value, TupleType.Three)); break; case MatchMode.StartWith: _conds.Add(new StartWithConditionItem(name, value)); break; default: throw new InvalidEnumArgumentException("Unsupported match mode " + matchMode); } } /// /// 采用范围匹配模式添加Conditions项。 /// /// Condition名称。 /// 范围最小值。 /// 范围最大值。 public void AddConditionItem(string name, long min, long max) { if (min > max) throw new ArgumentException(String.Format("Invalid range [{0}, {1}].", min, max)); _conds.Add(new RangeConditionItem(name, min, max)); } internal string Jsonize() { var jsonizedConds = new StringBuilder(); jsonizedConds.Append("\"conditions\":["); foreach (var cond in _conds) jsonizedConds.Append(cond.Jsonize()); if (_conds.Count > 0) jsonizedConds.Remove(jsonizedConds.Length - 1, 1); jsonizedConds.Append("]"); return jsonizedConds.ToString(); } } internal static class MatchRuleChecker { private static IDictionary> _supportedMatchRules = new Dictionary>(); static MatchRuleChecker() { var ordinaryMatchModes = new List {MatchMode.Exact, MatchMode.StartWith}; var specialMatchModes = new List {MatchMode.Range}; _supportedMatchRules.Add(PolicyConditions.CondContentLengthRange, specialMatchModes); _supportedMatchRules.Add(PolicyConditions.CondCacheControl, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondContentType, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondContentDisposition, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondContentEncoding, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondExpires, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondKey, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondSuccessActionRedirect, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondSuccessActionStatus, ordinaryMatchModes); _supportedMatchRules.Add(PolicyConditions.CondXOssMetaPrefix, ordinaryMatchModes); } public static void Check(MatchMode matchMode, string condName) { if (_supportedMatchRules.ContainsKey(condName)) { var mms = _supportedMatchRules[condName]; if (!mms.Contains(matchMode)) { throw new ArgumentException( String.Format("Unsupported match mode for condition item {0}", condName)); } } } } }