1 //
2 // System.Web.UI.WebControls.BaseCompareValidator
3 //
4 // Authors:
5 //	Chris Toshok (toshok@novell.com)
6 //
7 // (C) 2005-2010 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 
29 using System.Text;
30 using System.Threading;
31 using System.Globalization;
32 using System.ComponentModel;
33 using System.Security.Permissions;
34 using System.Web.Util;
35 
36 namespace System.Web.UI.WebControls
37 {
38 	// CAS
39 	[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
40 	[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
41 	public abstract class BaseCompareValidator : BaseValidator
42 	{
BaseCompareValidator()43 		protected BaseCompareValidator ()
44 		{
45 		}
46 
AddAttributesToRender(HtmlTextWriter writer)47 		protected override void AddAttributesToRender (HtmlTextWriter writer)
48 		{
49 			if (RenderUplevel) {
50 				if (Page != null) {
51 					RegisterExpandoAttribute (ClientID, "type", Type.ToString ());
52 
53 					switch (Type) {
54 						case ValidationDataType.Date:
55 							DateTimeFormatInfo dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
56 							string pattern = dateTimeFormat.ShortDatePattern;
57 							string dateorder = (pattern.StartsWith ("y", true, Helpers.InvariantCulture) ? "ymd" : (pattern.StartsWith ("m", true, Helpers.InvariantCulture) ? "mdy" : "dmy"));
58 							RegisterExpandoAttribute (ClientID, "dateorder", dateorder);
59 							RegisterExpandoAttribute (ClientID, "cutoffyear", dateTimeFormat.Calendar.TwoDigitYearMax.ToString ());
60 							break;
61 						case ValidationDataType.Currency:
62 							NumberFormatInfo numberFormat = CultureInfo.CurrentCulture.NumberFormat;
63 							RegisterExpandoAttribute (ClientID, "decimalchar", numberFormat.CurrencyDecimalSeparator, true);
64 							RegisterExpandoAttribute (ClientID, "groupchar", numberFormat.CurrencyGroupSeparator, true);
65 							RegisterExpandoAttribute (ClientID, "digits", numberFormat.CurrencyDecimalDigits.ToString());
66 							RegisterExpandoAttribute (ClientID, "groupsize", numberFormat.CurrencyGroupSizes [0].ToString ());
67 							break;
68 					}
69 				}
70 			}
71 
72 			base.AddAttributesToRender (writer);
73 		}
74 
CanConvert(string text, ValidationDataType type)75 		public static bool CanConvert (string text,
76 					       ValidationDataType type)
77 		{
78 			object value;
79 
80 			return Convert (text, type, out value);
81 		}
82 
Convert(string text, ValidationDataType type, out object value)83 		protected static bool Convert (string text,
84 					       ValidationDataType type,
85 					       out object value)
86 		{
87             		return BaseCompareValidator.Convert(text, type, false, out value);
88 		}
89 
Compare(string leftText, string rightText, ValidationCompareOperator op, ValidationDataType type)90 		protected static bool Compare (string leftText, string rightText, ValidationCompareOperator op, ValidationDataType type)
91 		{
92             		return BaseCompareValidator.Compare(leftText, false, rightText, false, op, type);
93 		}
94 
DetermineRenderUplevel()95 		protected override bool DetermineRenderUplevel ()
96 		{
97 			/* presumably the CompareValidator client side
98 			 * code makes use of newer dom/js stuff than
99 			 * the rest of the validators.  but ours
100 			 * doesn't for the moment, so let's just use
101 			 * our present implementation
102 			 */
103 			return base.DetermineRenderUplevel();
104 		}
105 
GetDateElementOrder()106 		protected static string GetDateElementOrder ()
107 		{
108 			// I hope there's a better way to implement this...
109 			string pattern = Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;
110 			StringBuilder order = new StringBuilder();
111 			bool seen_date = false;
112 			bool seen_year = false;
113 			bool seen_month = false;
114 
115 			pattern = pattern.ToLower (Helpers.InvariantCulture);
116 
117 			for (int i = 0; i < pattern.Length; i ++) {
118 				char c = pattern[ i ];
119 				if (c != 'm' && c != 'd' && c != 'y')
120 					continue;
121 
122 				if (c == 'm') {
123 					if (!seen_month) order.Append ("m");
124 					seen_month = true;
125 				} else if (c == 'y') {
126 					if (!seen_year) order.Append ("y");
127 					seen_year = true;
128 				} else /* (c == 'd') */ {
129 					if (!seen_date) order.Append ("d");
130 					seen_date = true;
131 				}
132 			}
133 
134 			return order.ToString ();
135 		}
136 
GetFullYear(int shortYear)137 		protected static int GetFullYear (int shortYear)
138 		{
139 			/* This is an implementation that matches the
140 			 * docs on msdn, but MS doesn't seem to go by
141 			 * their docs (at least in 1.0). */
142 			int cutoff = CutoffYear;
143 			int twodigitcutoff = cutoff % 100;
144 
145 			if (shortYear <= twodigitcutoff)
146 				return cutoff - twodigitcutoff + shortYear;
147 			else
148 				return cutoff - twodigitcutoff - 100 + shortYear;
149 		}
150 
151 		[DefaultValue (false)]
152 		[Themeable (false)]
153 		public bool CultureInvariantValues {
154 			get { return ViewState.GetBool ("CultureInvariantValues", false); }
155 			set { ViewState ["CultureInvariantValues"] = value; }
156 		}
157 
158         	protected static int CutoffYear {
159 			get { return CultureInfo.CurrentCulture.Calendar.TwoDigitYearMax; }
160 		}
161 
162 
163 		[DefaultValue(ValidationDataType.String)]
164 		[Themeable (false)]
165 		[WebSysDescription("")]
166 		[WebCategory("Behavior")]
167 		public ValidationDataType Type {
168 			get { return ViewState ["Type"] == null ? ValidationDataType.String : (ValidationDataType) ViewState ["Type"]; }
169 			set { ViewState ["Type"] = value; }
170 		}
171 
CanConvert(string text, ValidationDataType type, bool cultureInvariant)172 		public static bool CanConvert (string text, ValidationDataType type, bool cultureInvariant)
173 		{
174             		object value;
175             		return Convert(text, type, cultureInvariant, out value);
176 		}
177 
Compare(string leftText, bool cultureInvariantLeftText, string rightText, bool cultureInvariantRightText, ValidationCompareOperator op, ValidationDataType type)178 		protected static bool Compare (string leftText,
179 					       bool cultureInvariantLeftText,
180 					       string rightText,
181 					       bool cultureInvariantRightText,
182 					       ValidationCompareOperator op,
183 					       ValidationDataType type)
184 		{
185 			object lo, ro;
186 
187 			if (!Convert(leftText, type, cultureInvariantLeftText, out lo))
188 				return false;
189 
190 			/* DataTypeCheck is a unary operator that only
191 			 * depends on the lhs */
192 			if (op == ValidationCompareOperator.DataTypeCheck)
193 				return true;
194 
195 			/* pretty crackladen, but if we're unable to
196 			 * convert the rhs to @type, the comparison
197 			 * succeeds */
198 			if (!Convert(rightText, type, cultureInvariantRightText, out ro))
199 				return true;
200 
201 			int comp = ((IComparable)lo).CompareTo((IComparable)ro);
202 
203 			switch (op) {
204 				case ValidationCompareOperator.Equal:
205 					return comp == 0;
206 				case ValidationCompareOperator.NotEqual:
207 					return comp != 0;
208 				case ValidationCompareOperator.LessThan:
209 					return comp < 0;
210 				case ValidationCompareOperator.LessThanEqual:
211 					return comp <= 0;
212 				case ValidationCompareOperator.GreaterThan:
213 					return comp > 0;
214 				case ValidationCompareOperator.GreaterThanEqual:
215 					return comp >= 0;
216 				default:
217 					return false;
218 			}
219 		}
220 
Convert(string text, ValidationDataType type, bool cultureInvariant,out object value)221 		protected static bool Convert (string text, ValidationDataType type, bool cultureInvariant,out object value)
222 		{
223 			try {
224 				switch (type) {
225 					case ValidationDataType.String:
226 						value = text;
227 						return value != null;
228 
229 					case ValidationDataType.Integer:
230 						IFormatProvider intFormatProvider = (cultureInvariant) ? NumberFormatInfo.InvariantInfo :
231 						NumberFormatInfo.CurrentInfo;
232 						value = Int32.Parse(text, intFormatProvider);
233 						return true;
234 
235 					case ValidationDataType.Double:
236 						IFormatProvider doubleFormatProvider = (cultureInvariant) ? NumberFormatInfo.InvariantInfo :
237 						NumberFormatInfo.CurrentInfo;
238 						value = Double.Parse(text, doubleFormatProvider);
239 						return true;
240 
241 					case ValidationDataType.Date:
242 
243 						IFormatProvider dateFormatProvider = (cultureInvariant) ? DateTimeFormatInfo.InvariantInfo :
244 						DateTimeFormatInfo.CurrentInfo;
245 
246 						value = DateTime.Parse(text, dateFormatProvider);
247 						return true;
248 
249 					case ValidationDataType.Currency:
250 						IFormatProvider currencyFormatProvider = (cultureInvariant) ? NumberFormatInfo.InvariantInfo :
251 						NumberFormatInfo.CurrentInfo;
252 						value = Decimal.Parse(text, NumberStyles.Currency, currencyFormatProvider);
253 						return true;
254 
255 					default:
256 						value = null;
257 						return false;
258 				}
259 			} catch {
260 				value = null;
261 				return false;
262 			}
263 		}
264 	}
265 }
266 
267 
268 
269 
270 
271 
272 
273