../images/Emo26.gif המשך
קטע קוד מפחיד ומזעזע לכל הדעות (ועוד בלי השמות האמיתיים של הפרמטרים), אבל נוכל לשים לב כאן בערך מה הולך. יש משתנה בשם text3 והוא הופך להיות ה-NavigateURL שלנו. אז נביט עליו קצת. הוא מתאתחל בתחילת הקטע קוד הזה ומקבל ערך רק של text4. המשתנה text4 עובר כל מיני מניפולציות מפחידות משהו ובדיקה הגיונית יחסית של CrossSiteScriptingValidation.IsDangerousUrl. בואו נביט על התוכן של המתודה שעושה את הבדיקה הזו:
internal static bool IsDangerousUrl(string s) { if (string.IsNullOrEmpty(s)) { return false; } s = s.Trim(); int num1 = s.Length; string maltioPrefix = "mailto:"; if (((((num1 > 4) && ((s[0] == 'h') || (s[0] == 'H'))) && ((s[1] == 't') || (s[1] == 'T'))) && (((s[2] == 't') || (s[2] == 'T')) && ((s[3] == 'p') || (s[3] == 'P')))) && ((s[4] == ':') || (((num1 > 5) && ((s[4] == 's') || (s[4] == 'S'))) && (s[5] == ':')))) { return false; } int num2 = s.IndexOf(':'); if (num2 == -1) { return false; } return true; }
והנה, גילינו את האשם שלנו! לפני קביעת NavigateURL מתבצעת בדיקה שנועדה להגן עלינו שהמידע שאנחנו מכניסים לתוך הקישור, הוא אכן קישור שמתחיל בטקסט "http://". זאת אכן דרך מוזרה משהו לבדוק את זה, אבל ניחא. אז עכשיו, גילינו שאין לנו שום דרך לעבוד עם HyperLinkField ובאמת להוסיף תחילית של mailto. אז נעשה מה שתמיד צריך לעשות במצב הזה - נירש את HyperLinkField ונשנה את ההתנהגות שלו.
namespace Controls { public class MailtoHyperLinkField : HyperLinkField { public MailtoHyperLinkField() { } } }
ראינו שכל הקוד הבעייתי נמצא במתודה InitlizeCell, אז נדרוס אותה. וניגש לאותו HyperLink שהוסיפה המתודה של InitlizeCell ששייך ל-HyperLinkField המקורי. כלומר, ניתן ל-HyperLinkField.InitlizeCell להתבצע, אבל אחר-כך אנחנו נתפוס שליטה וניגש ל-HyperLink שהיא הוסיפה. למה חטפנו את השליטה? כדי להשיג את היכולת לבצע בעצמנו את OnDataBindField.
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex) { base.InitializeCell(cell, cellType, rowState, rowIndex); if (cellType == DataControlCellType.DataCell) { HyperLink link1 = (HyperLink) cell.Controls[0]; if (((rowState & DataControlRowState.Insert) == DataControlRowState.Normal) && base.Visible) { if ((this.DataNavigateUrlFields.Length != 0) || (this.DataTextField.Length != 0)) { link1.DataBinding += new EventHandler(this.OnDataBindFieldWithMailTo); } cell.Controls.Add(link1); } } }
נשנה בגירסה שלנו של OnDataBindField את בדיקת האותיות התחיליות שיבדוק אם המחרוזת היא Mailto.
public static bool IsDangerousUrl(string s) { if (string.IsNullOrEmpty(s)) { return false; } s = s.Trim(); int num1 = s.Length; string maltioPrefix = "mailto:"; if ((((((num1 > 4) && ((s[0] == 'h') || (s[0] == 'H'))) && ((s[1] == 't') || (s[1] == 'T'))) && (((s[2] == 't') || (s[2] == 'T')) && ((s[3] == 'p') || (s[3] == 'P')))) && ((s[4] == ':') || (((num1 > 5) && ((s[4] == 's') || (s[4] == 'S'))) && (s[5] == ':')))) || ((num1 > maltioPrefix.Length) && (s.StartsWith(maltioPrefix)))) { return false; } int num2 = s.IndexOf(':'); if (num2 == -1) { return false; } return true; }
ועכשיו במקום הבדיקה של CrossSiteScriptingValidation.IsDangerousUrl נשתמש ב-IsDangerousUrl שלנו.
if (!IsDangerousUrl(text4)) text3 = text4;
אז הכל טוב ויפה, יש לנו פקד חדש שעושה בדיוק מה שרצינו. נרצה עכשיו לפרוס אותו כדי שבאמת נוכל להשתמש בו. אפשרות אחת ולא מומלצת היא לזרוק את קובץ ה-cs שלו לתיקיית App_Code של האתר שלנו. אפשרות שנייה