/*
* 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));
}
}
}
}
}