GammaCyber

כתיבת קוד — שיעור 15

מבוא ל-Web: HTTP, DOM, CSS

כל 3 משימות הקוד שנשמרו מהשיעור מופיעות כאן, עם דרישות, דוגמאות וקוד פתיחה. אפשר לכתוב פתרון בעורך המקומי וללחוץ על „בדיקת AI” לקבלת ציון, רמזים והערות.

T2 · בסיסי150 נק'~12 דק'debug
תיקון באג — מגן XSS (HTML escaping)
פונקציית ה-escaping אמורה לחסן קלט משתמש לפני הזרקה ל-HTML, כדי למנוע XSS. אך היא שבורה: היא בורחת רק מ-< ו->, ומשאירה & ומרכאות ללא טיפול — מה שמאפשר הזרקת מאפיינים ותקיפה. תקן כך שהיא תברח מ- & (ראשון!), <, >, " ו-'. שים לב לסדר: & חייב להיות ראשון, אחרת תיווצר בריחה כפולה.
// הקוד השבור לתיקון
def html_escape(s: str) -> str: return s.replace('<', '&lt;').replace('>', '&gt;') # באג כאן
דוגמאות
html_escape('<b>') → '&lt;b&gt;'
html_escape('a & b') → 'a &amp; b'
html_escape('<a href="x">') → '&lt;a href=&quot;x&quot;&gt;'
פתרון-ייחוס תיקון באג — מגן XSS (HTML escaping) ›
def html_escape(s: str) -> str: return (s.replace('&', '&amp;') # & חייב להיות ראשון! .replace('<', '&lt;') .replace('>', '&gt;') .replace('"', '&quot;') .replace("'", '&#39;'))
הפתרון נשמר מקומית אוטומטית.
T2 · בסיסי200 נק'~15 דק'algorithmic
פרסור Query String של HTTP
ממש parse_query שמפרק query string לרשימת ערכים לכל מפתח. פצל על '&', ובכל זוג פצל על '=' הראשון (חסר '=' → ערך ריק). פענח percent-encoding (%XX → תו) ו-'+' → רווח, גם במפתח וגם בערך. מפתחות חוזרים נאספים לרשימה לפי הסדר. מחרוזת ריקה → מילון ריק.
דוגמאות
parse_query('a=1&b=2') → {'a': ['1'], 'b': ['2']}
parse_query('a=1&a=2') → {'a': ['1', '2']}
parse_query('x=hello+world') → {'x': ['hello world']}
פתרון-ייחוס פרסור Query String של HTTP ›
def _decode(s): out = []; i = 0 while i < len(s): c = s[i] if c == '+': out.append(' '); i += 1 elif c == '%' and i + 2 < len(s): out.append(chr(int(s[i+1:i+3], 16))); i += 3 else: out.append(c); i += 1 return ''.join(out) def parse_query(qs: str) -> dict: res = {} if not qs: return res for part in qs.split('&'): if '=' in part: k, v = part.split('=', 1) else: k, v = part, '' res.setdefault(_decode(k), []).append(_decode(v)) # מפתח חוזר -> רשימה return res
הפתרון נשמר מקומית אוטומטית.
T3 · בינוני350 נק'~25 דק'algorithmic
חישוב CSS Specificity
חשב את ה-specificity של selector של CSS והחזר שלשה (a, b, c): a = מספר מזהי-#id · b = מספר מחלקות .class + מאפיינים [attr] + מחלקות-פסאודו :hover · c = מספר אלמנטים (שמות תגיות) + אלמנטים-פסאודו ::before. '*' לא נספר. הפרד קטגוריות בזהירות: '::' (אלמנט-פסאודו) נספר כ-type ולא כמחלקה.
דוגמאות
specificity('#nav .item a:hover') → (1, 2, 1)
specificity('ul li.active') → (0, 1, 2)
specificity('a::before') → (0, 0, 2)
פתרון-ייחוס חישוב CSS Specificity ›
import re def specificity(sel: str) -> tuple: a = b = c = 0 pe = re.findall(r'::[\w-]+', sel); c += len(pe); sel = re.sub(r'::[\w-]+', ' ', sel) a += len(re.findall(r'#[\w-]+', sel)); sel = re.sub(r'#[\w-]+', ' ', sel) # ids b += len(re.findall(r'\.[\w-]+', sel)); sel = re.sub(r'\.[\w-]+', ' ', sel) # classes b += len(re.findall(r'\[[^\]]*\]', sel)); sel = re.sub(r'\[[^\]]*\]', ' ', sel) # attrs b += len(re.findall(r':[\w-]+', sel)); sel = re.sub(r':[\w-]+', ' ', sel) # pseudo-classes c += len(re.findall(r'[a-zA-Z][\w-]*', sel)) # elements return (a, b, c)
הפתרון נשמר מקומית אוטומטית.