דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
yossizY

yossiz

@yossiz
אודות
פוסטים
6.1k
נושאים
126
שיתופים
0
קבוצות
0
עוקבים
26
עוקב אחרי
0

פוסטים

פוסטים אחרונים הגבוה ביותר שנוי במחלוקת

  • ניתוח חולשת PwnKit
    yossizY yossiz

    פרק ב - מבאג לאקספלויט

    (אקספלויט = תוכנה שמנצלת חולשה)

    תקציר

    בפרק הקודם ראינו איך שאפשר לנצל באג בפקודת pkexec כדי לגרום לזרימה לא צפויה של הקוד ולשלוט על אחת ממשתני הסביבה שלה. אבל עדיין לא הסברנו איך נוכל לנצל עובדה זו כדי להריץ קוד אקראי כרוט.

    רק נחדד, תוכנת pkexec לא מאפשרת הרצת פקודות אקראיות כרוט בלי להעביר מבחן, המבחן יכול להיות תיבת דו-שיח שמחייבת הזנת סיסמת מנהל, או זה יכול להיות בדיקה של הרשאה מיוחדת בקובץ תצורה במקום מוגדר במערכת הקבצים (הגישה לקובץ תצורה זו ניתנת רק לרוט). המטרה שלנו הוא לאפשר לפורץ להריץ את הקוד שלו עם הרשאות גבוהות בלי צורך להזין את סיסמת המנהל, ובלי צורך לרשיון מיוחד שהוגדר על ידי המנהל.

    בינתיים קיבלנו את האפשרות לגרום לתוכנה לפענח את משתנה הסביבה הראשונה כשם של פקודה, ובנוסף התוכנה מחפשת את הפקודה הזו ב-PATH ומכניסה חזרה למשתני הסביבה את הנתיב לפקודה.
    אבל עדיין פקודה זו לא תעבור את המבחן.

    אז איך ננצל את החולשה כדי להריץ קוד אקראי שלנו?

    (אגב, יש מישהו שטוען שהוא עלה על הבאג כבר בשנת 2013, אבל לא מצא את הדרך איך לנצל אותו. עיין כאן העתק של מייל שהוא כתב לפרוייקט polkit בנושא, לא ידוע למה התעלמו ממנו)

    משתני סביבה מסוכנים

    התשובה: רמזנו כבר למעלה, יש משתני סביבה "מסוכנים" שמערכת ההפעלה מנקה לפני הרצת תוכנה עם setuid. אם נוכל להזריק שוב לתוך הסביבה משתנה מסוכנת, נוכל לנצל אותה כדי להריץ קוד אקראי.

    (במקרה של pkexec יש רק חלון הזדמנות קטן לנצל את זה, כי די קרוב למקום הבאג, התוכנה עצמה עושה שוב נקיון משתני הסביבה. למרבה המזל (?) עדיין מצאו אפשרות ניצול בתוך קטע הקוד הקצר עד לנקיון החוזר)

    GCONV_PATH

    הרכיב שאחראי על טעינת תוכנות לזכרון והכנתם להרצה בלינוקס הוא ld.so, בתיעוד של הרכיב (man ld.so או כאן) ניתן למצוא רשימה של משתני סביבה מסוכנים שהרכיב מנקה לפני הרצת תוכנות עם setuid. בתוכם נמצא את המשתנה GCONV_PATH.

    המשתנה GCONV_PATH מוכרת על ידי ספריית iconv. ספרייה זו נמצאת ברוב ככל מערכות לינוקס (זה חלק מתקן POSIX שמגדיר מה אפשר לצפות ממערכת UNIX-ית) והיא אחראית על המרת טקסט בין קידודים שונים. כאשר תוכנה כלשהי קוראת לפונקציה מתוך ספריית iconv לבקש המרת טקסט לקידוד כלשהו, הספרייה בודקת את משתנה הסביבה GCONV_PATH כדי למצוא את הנתיב לקובץ תצורה. בתוך קובץ זה ניתן להגדיר נתיבים לספרייות קוד שנטענות בצורה דינאמית כדי לבצע את ההמרה. (ע"ע man iconv או כאן)

    g_printerr ומשתנה הסביבה CHARSET

    בקטע הקצר של הקוד מהבאג ועד לניקיון חוזר של משתני הסביבה יש קריאה לפונקציה g_printerr. פונקציה זו היא חלק מספריית glib (ספריית היסוד של GTK ש-polkit הוא חלק ממנה). פונקציה זו (כשמה) מדפיסה שגיאות לקונסול, והיא מכבדת את משתנה הסביבה CHARSET כדי לבחור קידוד להדפסה זו. שינוי הקידוד מהמחרוזת המקורית לקידוד הרצוי מתבצעת על ידי... iconv.

    והנה קטע הקוד (הנוגע לענינינו) שמדפיס את הודעת השגיאה:

     383 validate_environment_variable (const gchar *key,
     384                                const gchar *value)
     385 {
     ...
     406           log_message (LOG_CRIT, TRUE,
     407                        "The value for the SHELL variable was not found the /etc/shells file");
     408           g_printerr ("\n"
     409                       "This incident has been reported.\n");
    

    מה שחשוב להבין היא שהעובדה שמשתנה הסביבה SHELL מצביעה על shell לא חוקי תגרום להדפסת השגיאה, ולקריאת פונקציית iconv.

    עכשיו הדרך לאקספלויט מלא פתוחה לפנינו... 😎

    עוד לא הבנת? זה בסדר, זה מצריך קצת יצירתיות. תעקוב אחרי:

    האקספלויט

    בתור הכנה, נעשה את השלבים הבאים (אח"כ אנסה להסביר):

    • נבחר תיקייה כלשהו כ"תיקיית הבית" של האקספלויט.
    • ניצור תיקייה (בתוך "תקיית הבית" שלנו) בשם GCONV_PATH=.‎ (כן, ה-= וה-. הם חלק מהשם)
    • בתוך תיקייה זו נשים קובץ EXE כלשהו (כלומר, קובץ שיש לו הרשאות ריצה). לא משנה איזה. נקרא לקובץ שם כלשהו, לצורך הענין נבחר בשם "xxx" ונוסיף את התווים ‎:.‎‎ בסוף השם. השם המלא יוצא: xxx:.‎ (ההסבר יבוא)
    • ניצור קובץ קינפוג ל-iconv ב"תיקיית הבית" שלנו. בתוך הקובץ יש שורה אחת שאומרת ל-iconv שכדי להמיר קידוד UTF-8 לקידוד (שהמצאנו לצורך הענין) "PWNKIT" צריך לטעון את הקוד של ספרייה בשם "pwnkit.so". (השורה נראית משהו כזה: module UTF-8// PWNKIT// pwnkit. לעוד פרטים עיין בתיעוד). נקרא לקובץ בשם iconv_modules
    • ניצור קובץ בינארי (ספרייה - מה שנקרא DLL בעולם הווידוס) בתוך "תקיית הבית" שלנו, ונקרא אותו בשם pwnkit.so. הספרייה הזו מתחזה כמודול של iconv (ז.א. הוא מממש את הפונקציות gconv_init ו-gconv) בתוך הקוד של פונקציית gconv_init נוכל להריץ קוד אקראי עם הראשות רוט... ☠
    • ניצור עוד תוכנה שמריצה את pkexec עם פרמטרים מיוחדים:
      • argv של אבר אחד שהוא null pointer.
      • envp שכולל מספר ערכים:
        • הראשון: xxx:.‎ (כן, זה לא נראה כמשתנה סביבה. נראה בהמשך מה יקרה עם זה)
        • PATH=GCONV_PATH=.‎
        • SHELL=/i/do/not/exist
        • CHARSET=PWNKIT

    טוב, סיימנו את ההכנות, נצא לדרך!

    נעקוב אחרי זרימת הקוד ואני מקוה שתוכלו להבין איך האקספלויט עובד

    1. נריץ את התוכנה שיצרנו בשלב האחרון של ההכנות
    2. זה מריץ את הקוד של pkexec
    3. כפי בתיארנו בפוסט הראשון, pkexec יטעה, ויחשוב שמשתנה הסביבה הראשונה היא היא שם הפקודה שהעברנו אליה
    4. היא מעבירה את זה לפוקנציה שמחפשת פקודה זו ב-PATH ומחזירה את הנתיב לפקודה (שורה 632 בקטע הקוד בפוסט הראשון)
    5. מכיון שה-PATH שלנו מכילה ערך אחד: GCONV_PATH=.‎, הפוקנציה תחפש תיקייה בשם GCONV_PATH=.‎ ובתוכה קובץ בשם: xxx:.‎
    6. הפונקציה תמצא את הקובץ שהכנו, והיא תחזיר לתוכנה את הנתיב אליה: GCONV_PATH=./xxx:.‎
    7. pkexec תיקח תוצאה זו ותכניס אותה חזרה ל... משתנה הסביבה הראשונה. יוצא שהצלחנו להזריק משתנה הסביבה לא בטוחה לתוך התהליך. משתנה הסביבה נראית כך עכשיו: GCONV_PATH=./xxx:.‎
    8. התוכנה תמשיך לרוץ ומכיון שהגדרנו משתנה SHELL לא חוקית, נגיע להודעת השגיאה...
    9. פונקציית ההדפסה מכבדת את משתנה הסביבה CHARSET שערכו אצלנו "PWNKIT", לכן היא מנסה להמיר את טקסט ה-UTF-8 שבקוד המקור, לקידוד "PWNKIT"
    10. כדי לבצע את ההמרה היא מחפשת את הגדרות iconv לפי משתנה הסביבה GCONV_PATH. משתנה זו אמורה להכיל רשימה של נתיבים מופרדים באמצעות תו :. אצלנו יש שני ערכים ברשימה: ‎./xxx ו-..
    11. הפונקציה מחפשת בשני הנתיבים לקובץ בשם iconv_modules. הנתיב הראשון לא קיים כמובן, אבל השני קיים. ה-. מסמל את התיקייה הנוכחית. בינגו! יש שם קובץ תצורה. בוא נראה מה כתוב:
    12. הופ! כתוב שלהמיר קידוד UTF-8 לקידוד PWNKIT אני צריך לטעון את הספרייה בשם pwnkit, אז בוא נחפש ספרייה בשם זה בתקייה הנוחכית...

    אתם יכולים לנחש את הסוף העצוב של הסיפור...

    ☠

    (קרדיט: נעזרתי בשני מקורות אלו להכנת המאמר:

    • https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
    • https://github.com/berdav/CVE-2021-4034)
    תכנות

  • תכנות | איך להתחיל?
    yossizY yossiz

    @למה אמר בתכנות | איך להתחיל?:

    אוקיי קיבלתי תשובה אחת על מה [לא] צריך

    לא הבנת את המסר.

    שוב:

    לא צריך כ-ל-ו-ם

    פשוט תתחיל.

    אני רוצה לשתף איתך סיפור על אחד שאני מכיר די טוב (ב"ה, לא כולם זוכים להכיר את עצמם...). כאשר הוא התחתן הוא לא ידע כלום על מחשבים. וכאשר אני אומר כלום, אני מתכוון לכלום. שום דבר. לא איך מדליקים ולא איך מכבים. שום כלום.
    אבל הוא קיבל ג'וק בראש שהוא חייב להבין איך מחשב עובד. (אני לא ממליץ על זה. זה מה שקרה. אני לא אומר שזה דבר טוב.)
    ההוא פשוט התחיל לקרוא כל פיסת מידע שהוא יכל להשיג בנושאים שקשורים למחשבים.
    היום הוא מתכנת עם ידע לא רע במחשבים.

    תכנות

  • לחצן סגירת התוכנה - vs code
    yossizY yossiz

    @ליבל הנה סיקור מלא שתבין מי פה אחראי על מה, קצת מעבר למה שביקשת...

    נתחיל עם תרשים השכבות:

    ┌───────────┐
    │    You    │
    ├─────▼─────┤
    │   VSCode  │
    ├─────▼─────┤
    │  Electron │
    ├─────▼─────┤
    │  Windows  │
    ├─────▼─────┤
    │  Hardware │
    └───────────┘
    

    כל שכבה שולטת על השכבה שמתחתיה, ומשתמשת בשירותים של השכבה שמתחתיה

    השכבה התחתונה זה החומרה שבסוף מציגה את החלון על המסך. אין לה בד״כ השפעה על מיקום הפקדים, כי החומרה צייתנית (וטיפשה) ועושה בדיוק מה שהשכבות העליונות פוקדים עליה

    השכבה השנייה (מלמטה) זה ווינדוס,
    אין לשום תוכנה רשות לצייר על המסך בלי לבקש רשות של מערכת ההפעלה. אחרי בקשת רשות כדבעי, וינדוס נותן לתוכנה חלק מהנד(ל)ן של המסך (המכונה ״חלון״) לקשקש עליו (אפשר גם לבקש להגדיל/להקטין את האזור)
    האזור שווינודס נותן לתוכנה הוא קוביה ריקה בעיקרון, לא מצוייר עליו בהתחלה כלום גם לא המסגרת של החלון. זה האחריות התוכנה לצייר שם דברים שימושיים. יש לתוכנה רשות לקשקש על כל האזור ששייך לחלון כולל האזור של המסגרת והפקדים שיש בו.
    אך, רוב התוכנות לא מעוניינים לצייר מסגרת ופקדים ולממש את ההתנהגות הנכונה עבורם, לכן ברוב התוכנות שאתה משתמש, ווינדוס הוא זה שמצייר אותם, כלומר התוכנה מוסרת את האחריות לווינדוס, והתוכנה עצמה ממלאת רק את התוך של החלון אבל הוא לא שולט על המסגרת
    זה מה שהכי מומלץ בד״כ כדי שהמשתמשים יקבלו חוויה עקבית ואיכותית
    במקרה כזה, ווינדוס הוא זה שמחליט על המיקום של הפקדים
    אבל ווינדוס גם נותן לך את האופציה לצייר את הפקדים האלו בעצמך ואז אתה יכול לצייר אותם איך ואיפה שאתה רוצה

    שכבה הבאה - אלקרון:
    פלטפורמת אלקטרון מאפשר לבנות תוכנות דסקטופ עם טכנולוגיות ווב,
    אלקטרון מייצרים בשיבלך את החלון (כלומר, מבקשים יפה מווינדוס להקצות חלון בשבילך) ונותנים לך את האפשרות לבחור אם לצייר בעצמך את המסגרת עם הפקדים או לא.

    שכבה הבאה: VSCODE:
    תוכנת vscode בנוייה על גבי פלטפורמת אלקטרון,
    vscode נותן לך - המשתמש - את הבחירה לבחור מי יצייר את המסגרת ופקדים של החלון
    ההגדרה window.titleBarStyle נועד לזה, אם זה native זה פוקד ל-vscode שיפקוד על אלקטרון שהוא ימסור את ציור הפקדים לאחריות מערכת ההפעלה.
    אם זה disabled אז vscode בעצמם מציירים את זה באמצעות HTML ו-CSS (או קנבס) כמו שאר התוכן של החלון
    לאחרונה נכנס לתמונה אפשרות חדשה שזה מה ש- @ivrtikshoret הביא
    זה מאפשר להציג את הפקדים האוריגינלים של מערכת ההפעלה אבל תחת שליטת התוכנה. אני עוד לא בקי באפשרות זו. צריך לבדוק לעומק כאן מי מחליט באיזה צד של החלון לשים את זה.

    שכבה אחרונה - אתה:
    אתה כמשתמש צריך להגיד ל-vscode מה הוא אמור להגיד לאקטרון שיגיד למערכת ההפעלה שיגיד לחומרה להציג, חד גדיא חד גדיא...

    תוכנה

  • "חידה מתמטית פשוטה" או "למה אין לי אינטואיציה מתמטית בריאה?"
    yossizY yossiz

    ראובן הביא הביתה 100ק"ג תפו"א ש-99% ממשקלם הם מים. (זה לא האחוז האמיתי של מים בתפוחי אדמה, אבל לצורך השאלה זה היה האחוז). הוא השאירם בחוץ ללילה, ואחרי שבמשך הלילה התאדו חלק מהמים, בבוקר אחוז המים היה רק 98%.
    מה היה המשקל הכללי של התפו"א בבוקר?
    או בנוסח אחר, מה כמות המים שהתאדה?

    תחשבנו את התשובה.
    האם זה התאים לאינטואיציה שלך?
    אם לא, האם תוכל להסביר למה לא?
    האם תדע לטפל באינטואיציה שלך כך שבפעם הבא יהיה לך אינטואיציה נכונה?

    תכנות

  • שעון נוכחות בטביעת אצבע או קוד לכולל אברכים
    yossizY yossiz

    שעון נוכחות לאברכים זה זלזול בכבודם. וגם לא יהיה יעיל במיוחד.
    אני כותב את זה כמי שלמד כמה שנים טובות בכולל. לא הייתי מסכים ללמוד בכולל עם שעון נוכחות.
    אני לא מתכחש לעובדה שיש אברכים שמתקשים קצת בשמירת הסדרים. אבל אני לא חושב ששעון נוכחות הוא פתרון טוב.

    תוכנה

  • כללים לחיפושי גוגל יעילים
    yossizY yossiz

    הנה נסיון להעלות על הכתב תהליך שעברתי בחיפוש על בעיה ספציפית,
    החיפוש ארך דקות ספורות או פחות מזה, ההעלאה על הכתב ארכה הרבה מעבר לזה...

    (הכלל הראשון הוא שאין כללים מוצקים, אני רק מתאר את התהליך שאני עברתי בחיפוש בנוגע לבעיה זו, כל אחד יכול מוזמן לנסח כללים לעצמו ולראות מה עובד בשבילו...)

    @שרגה-קליין שאל פה על הודעת שגיאה זו:

    אז מה אמור להיות התהליך לחפש פתרון?

    קודם כל, לפני חיפוש כלשהו, ננסה להבין מה נמצא בתמונה שלפננו.
    יש הודעת שגיאה די ג'נרית (error launching installer = שגיאה בעת הפעלת ההתקנה) זה לא אומר לנו הרבה.
    מה שיכול לתרום יותר פרטים הוא הכותרת "NSIS Error"
    בהתאם לכלל א' שכתבתי בפוסט הראשון, קודם כל ננסה להבין מה זה אומר NSIS Error?
    errror = שגיאה, אבל מה זה NSIS?
    אני דוקא הכרתי מקודם מה זה NSIS אבל אם לא הכרת, חיפוש מהיר למילה NSIS ייתן לך להבין שמדובר בתוכנה שעושה "תוכנות התקנה" עבור מפתחי תוכנות.
    אז הצלחנו למקד קצת את השאלה: מה גורם ל-installer שמגיע מייצור NSIS לזרוק שגיאה שנוסחתו "error launching installer".
    במקום לחפש "error launching installer" נחפש "NSIS error launching installer".
    (דוקא במקרה זו, נראה שרוב תוצאות החיפוש גם של "error launching installer" מדברים על NSIS, כנראה שהניסוח הספציפי הזאת הוא ייחודי ל-NSIS, אבל בכל זאת יש תוצאות טובות יותר בחיפוש של "NSIS error launching installer")

    עכשיו נעבור על התוצאות וננסה להשתמש קצת ג"כ בשכל בריא להגיע לתשובה הנכונה ביותר:

    תוצאה ראשונה הוא מאתר appuals. אם אתה לא מכיר מכבר את האתר, אז מהסתכלות קצרה באתר תוכל להבין שמדובר שאתר מהסוג הזה שהזכרתי למעלה, שהם יותר מומחים ב-SEO והבאת תעבורה של אנשים תמימים מאשר בפתרון בעיות תוכנה...

    (א. הקטע הראשון של הכתבה הוא תיאור הבעיה, התיאור לא נכון עד כמה שאני מבין (אני אסביר למטה למה). המטרה של התיאור המיותר והמוטעה הוא א) לתת לגולש הרגשה נעימה שהם מבינים מה הבעיה, ב) SEO = מיטוב המעמד שלהם במנועי חיפוש, ככל שירבו במילים על הבעיה, דף זה יתאים לחיפושים רחבים יותר - סימן מובהק לאתר ספמי.
    ב. כל סגנון הכתיבה באתר מראה א. שזה לא נכתב על ידי אדם אינטלגנטי ביותר, ב. זה לא נכתב בשביל ציבור אינטלגנטי... דבר כזה קל יותר להריח אם אתה שולט בשפה...).

    אבל בכל זאת, אפשר לקבל מהם קצת תועלת. בכל זאת הם ליקטו פתרונות מרחבי האינטרנט וייתכן שיש משהו שיעזור.
    בודקים את רשימת הפתרונות ומנסים להבין אם מדובר במשהו שנראה ג'נרי כזאת, "אם לא יועיל לא יזיק" כזאת, או שחוש הריח תופס משהו עם יותר סיכוי לעבוד...

    אבל לפני שנעבור על הפתרונות המוצעים, ננתח את ניתוח הבעיה שלהם,
    הם טוענים שבעיה כזאת מגיע בגלל שקובץ ההתקנה משובש
    אבל -
    א. לגמרי במקרה, יש לי קצת ידע מנסיון העבר, וזכור לי שיש שגיאה אחרת במקרה כזאת.
    ב. נוסח השגיאה לא ממש משקפת את הבעיה

    ליתר ביטחון עשיתי חיפוש משני למצוא איך נראה שגיאה שמגיעה משיבוש קבצי ההתקנה.
    איך עשיתי את החיפוש?
    לקחתי את הפתרון הרביעי בדף. שם הם מציעים להריץ את תוכנת ההתקנה עם הפרמטר NCRC/ , מכיון שהבנתי מה שהפרמטר עושה, ושזה מיועד בדיוק בשביל בעיה של שיבוש קבצי ההתקנה, ידעתי שאם אחפש "NSIS NCRC" אגיע בוודאות לדף שיתאר את השגיאה כי זה צירוף מילים שלא יופיע בשום הקשר אחר (כלל ב). ואכן בתוצאה השנייה יש תיאור איך השגיאה אמורה ליראות:

    Installer integrity check has failed. Common causes include
    incomplete download and damaged media. Contact the
    installer's author to obtain a new copy.
    More information at:
    http://nsis.sf.net/NSIS_Error

    אבל נשים את הבקורות בצד לרגע, ונעבור על הפתרונות

    METHOD 1: נראה כשטויות במיץ,, נעבור לשיטה הבאה
    (כלל ברזל: אל תוריד שום תוכנה אף פעם אם אתה לא חיפשת אותה אלא היא חיפשה אותך... )
    METHOD 2: נעביר את השיטה במבחן השכל הישר (ונסיון העבר),
    לדעתי, אפשר קצת להבין למה זה יכול לעזור, כי יש תוכנות שלא אוהבים רווחים בנתיב שלהם או תווים לא נפוצים, אבל לא כ"כ מסתבר שבתוכנה נפוצה ובתשע"ט יהיה בעיה כזו, אז נרשום את זה לשימוש אפשרי ונעבור הלאה.
    METHOD 3: מבוסס על התיאור הלא נכון של הבעיה שבקטע הראשון, מכיון שכבר החלטתי (מתוך ידע מוקדם) שתיאור הבעיה לא נכונה, פסלתי אותו.
    METHOD 4: שיטה זו נראה מאוד ספציפי ולא ג'נרי, אבל הוא גם מבוסס על תיאור לא נכון של הבעיה
    כל השאר לא שווים לייחד עליהם את הדיבור בכלל....

    ברפרוף על תוצאות האחרות שגוגל מביא, יש כמה שלא נראים כל כך מבטיחים.

    • https://answers.microsoft.com - מנסיון העבר, קשה למצוא שם פתרונות טובים
    • https://www.sevenforums.com/ - נו נו
    • How to Solve NSIS Error: 4 Steps
      https://www.instructables.com
      שוב אתר ספמי מובהק

    עד שהגעתי לתוצאה האחרונה בדף הראשון -
    Error Launching Installer - NSIS
    https://nsis.sourceforge.io/Error_Launching_Installer

    זה התוצאה הסמכותית והאיכותית ביותר. זה האתר של מפתח התוכנה.
    דוקא במקרה זו אני לא בטוח שהם קלעו לבעיה... נראה...

    אם נצטרך להוציא מסקנה אחת מכל המגילה הארוכה הזאת,
    נראה לי שהמסקנא המתבקשת הוא:

    להשתמש בגוגל כעזר לשכל הישר ולא כתחליף לשכל הישר... 🙂

    בכל שלב נעזרתי בנסיון העבר ושכל הישר (לפחות לדעתי...)

    אינטרנט

  • המרת תוכנה לאתר
    yossizY yossiz

    @כוספים-למשיח איך אפשר להמיר מטוס למסוק?

    כלומר, בד"כ אי אפשר.

    אינטרנט

  • תודה רבה לחברי הפורום
    yossizY yossiz

    חברה, תשמעו,
    מסתבר שכל הדיבורים החמים שיצאו מן הלב, לאט לאט חלחלו ועשו את שלהם...
    אני מקבל איתותים שהניק הכי אהוב בפורום (מבלי למעט בחשיבותו של כל האחרים כל אחד בשמו הטוב יבורך) שוקל ברצינות לחזור. (מי באמת חשב שהוא יעזוב לנצח?). ייתכן שבקרוב (אפילו הערב) נראה את האור הירוק 0f0fec22-5311-4b61-97fc-7b7d54fc1c31-image.png מבלי להזדקק לפיטשופים 🙂
    👏 👏 👏 👏

    על הפורום

  • בקשת אישור מתוך קובץ BAT בממשק גראפי
    yossizY yossiz

    לא מצאתי פתרון מוכן ברשת, אז הנה עכשיו יש... (מצאתי דומה, כמעט, אבל לא בדיוק)

    chcp 1255
    (echo WScript.Quit msgbox("האם אתה בטוח שהנך רוצה ל_____?" ^& _
        echo vbcrlf ^& _
        echo "פעולה זו לא ניתנת לביטול!!!", _
        echo 1+16+256+1048576, _
        echo "אישור"^)) > %temp%\prompt_for_confirmation.vbs & cscript %temp%\prompt_for_confirmation.vbs
    if ERRORLEVEL 2 goto END
    
    REM שים את הקוד שלך פה
    
    :END
    del %temp%\prompt_for_confirmation.vbs
    

    2019-11-17 12_42_56-אישור.png

    ⚠ לשמור את הקובץ בקידוד ANSI אחרת העברית יצא משובש.

    נ.ב. אפשר לשנות את הפרמטרים כדי לקבל לחצנים ואייקונים שונים. עיין: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/msgbox-function

    תכנות

  • חידה מתמטית לשמחת החג ולחדד את מוחות הילדים (והמבוגרים)
    yossizY yossiz

    החידה ופתרונה די ידועים, אז סליחה אם אני לא מחדש משהו למישהו...

    החידה:
    אסיר נמצא בבית סוהר, והסוהר קם בוקר אחד על רגל ימין והוא מציע לאסיר לשחק את המשחק הבא.
    "לפניך שלוש דלתות, מאחורי אחת מהם מתחבאת הדרך לחירות, מאחורי האחרים אין כלום. אם אתה מצליח להצביע על הדלת הנכונה הדרך לחירות פתוחה לפניך!"
    כל הדלתות זהות ולאסיר אין שום דרך לדעת מאחורי איזה מהן מסתתרת לה הדרך לחירות.
    האסיר אומר לעצמו "מה יש לי להפסיד?" והוא מצביע על אחת מהדלתות בצורה אקראית.
    ברגע של חסד הסוהר אומר לו: "אני רוצה לתת לך סיכוי יותר טוב". הוא פותח אחת משתי הדלתות הנותרות שעליהם לא הצביע האסיר וחושף מאחוריה קיר.
    "עכשיו", אומר לו הסוהר, "נשארו רק שתי דלתות, ז.א. שיש לך צ'אנס של חמישים אחוז לנצח במשחק, האם אתה נשאר עם הבחירה הקודמת שלך או שאתה רוצה לשנות אותה?"
    מה על האסיר לעשות?

    1. להישאר עם הבחירה הקודמת.
    2. לשנות את הבחירה הקודמת ולהצביע על הדלת השלישית.
    3. לא משנה מה הוא יעשה יש לו סיכוי של 50% לנצח.
    תכנות

  • החיסון לקורונה
    yossizY yossiz

    @פלורידה במחילה מכבודך, השאלה שלך, למרות שאני מבין את המניע ורצון לקבל תשובה, אבל להציב אותה כאן הוא רעיון טפשי לגמרי. אחרי קריאת כל התשובות אין סיכוי שתהיה יותר חכם מלפני, אולי יותר מבולבל, אולי יותר טיפש, אבל אני מבטיח לך שלא תהיה יותר חכם מקריאת התשובות שתקבל פה.
    יש שני דרכים לפניך,
    א. לשמוע לעצת אנשים שאתה סומך על שיקול דעתם.
    ב. ללמוד את הנושא בעצמך עד מקום שיד אנוש מגעת, וכולי האי ואולי, ואז להחליט בעצמך.

    לשאול בפורום של סתם אנשים שלא מבינים ברפואה (וחלקם לא מבינים בסתם עניני העולם...) לא יביא לך שום תועלת.

    גומלין - כללי

  • בעלי אתרי וורדפרס + אלמנטור פרו + woocommerce: עדכנו מיד!
    yossizY yossiz

    לכל בעלי אתרים שמשתמשים בוורדפרס + אלמנטור פרו + woocommerce חובה לעדכן מיד! את גירסת אלמנטור פרו
    יש באג באלמנטור פרו שבצירוף התקנה של woocommerce מאפשר למשתמש רגיל לשנות הגדרות האתר, אפשר להגדיר שכל משתמש חדש בברירת מחדל יקבל את הרשאות אדמין
    פרטים טכניים על הבאג פה
    הבאג קל למישוש, בדקתי בעצמי על אתר של חבר וזה עובד
    נתקלתי באתר גדול בארץ שמישהו כבר פרץ אליהם, עשיתי חשבון חדש וקיבלתי מיד הרשאות מנהל!

    נ.ב. חשבון המשתמש שלי בפרוג חסום (כי פעם העזתי להתלונן בצורה קצת חריפה על כמות פרסומות באתר, בכל מקרה,) מי שיש לו חשבון שם, אולי יהיה כדאי לעשות טובה לבעלי אתרים ולפרסם גם שם

    אינטרנט

  • חידת היגיון
    yossizY yossiz

    חידת הגיון

    איזו תשובה ברשימה זו היא התשובה הנכונה לשאלה זו?

    1. כל התשובות דלהלן.
    2. אף אחד מהאפשרויות דלהלן.
    3. כל אחד מן הנזכרים למעלה.
    4. אחד מן הנזכרים למעלה.
    5. אף אחד מן הנזכרים למעלה.
    6. אף אחד מן הנזכרים למעלה.

    מקור
    מי שלומד גמרא לא אמור להיות לו שום קושי בזה

    תכנות

  • צלילה לעומק TS: טייפ X לא זהה ל-union של כל הערכים האפשריים שהטייפ כולל
    yossizY yossiz

    בפוסט הזה אולי לא נתקדם הלאה כי אני רוצה להבהיר כמה נקודות ולחזור על חלק מהמושגים מהפוסט הקודם

    הודעות

    א. תודה לכל מי שטרח להשאיר לי משוב, אם בצורת הצבעה על הפוסט ואם בערוצים פרטיים (כמה חברים כתבו אלי בערוצים אחרים), אני מעריך את זה!
    ב. לכל מי שהתקשה להבין את הפוסט הקודם:
    אל תאשים את עצמך. זה לא היה פוסט קל להבנה! כתבתי דברים בקיצור, ולפעמים השמטתי לגמרי הסברים נחוצים.
    הנושא עצמו מאוד תיאורטי, וגם הדוגמאות לא היו ממש מעשיות.
    אני מתנצל. (אנסה להבא להביא דוגמאות יותר מעשיות)
    ולמי שלא התקשה כלל: או שיש לך הכירות קודמת עם הנושא, או שאתה מוכשר, או שלא הבנת באמת
    ג. חשוב להבהיר! אין שום צורך להכיר את כל התוכן התיאורטי שכתבתי כדי לקבל תועלת מ-TS. גם אם הנושא לא מושך אותך או אפילו דוחה אותך, אני עדיין ממליץ בחום להשתמש ב-TS כי אפשר לקבל רוב התועלת בלי להבין את הרקע התיאורטי. הפוסט שלי חשוב למי שרוצה ליצור טייפים. רוב הזמן אתה צורך טייפים שאחרים כתבו ולא יוצר טייפים חדשים. וגם רוב הטייפים שתיצור יהיו פשוטים בלי צורך בידע תיאורטי עמוק.
    ד. העירו לי על כמה דברים שלא הסברתי די הצורך בפוסט הקודם ואנסה להבהיר אותם כאן

    מה זה טייפ?

    (הרחבה של הקטע "מה זה טייפ" בפוסט הקודם)

    התפקיד של טייפים בשפות תכנות זהה לכל השפות: בהנתן ערך כלשהו, המתכנת רוצה לדעת בצורה סטטית (כלומר, בלי להריץ את התוכנה בפועל) איזה פעולות זמינים לו על ערך זה, איך מותר להשתמש בערך.
    אבל יש הבדל מהותי בין ההתעסקות עם טייפים בשפות סטטיות (statically typed) "קלאסיות" (JAVA, C++, C#, etc) לטייפים ב-TS
    כי בשפות קלאסיות אין עיסוק ישיר עם טייפים עצמם. עוסקים עם קלאסים, שהם "תבניות" או "אב טיפוס" לערכים, קלאס מגדיר איזה שדות הערך חייב להכיל, ובאיזה פעולות הוא צריך לתמוך. וכתוצאה נוצר "טייפ" (שהוא הסט של כל הערכים האפשריים שמתאימים לתבנית) אבל אין עיסוק ישיר עם טייפים עצמם
    ב-TS יש עיסוק ישיר עם טייפים עצמם. מחברים טייפים אחד לשני, מחסרים טייפים אחד מהשני, בונים טייפים מטייפים אחרים, דברים שלא קיימים בשפות קלאסיות.
    בשפה קלאסית אין מושג של literal type (הטייפ של ערך literal, סט בעל ערך יחיד). כי כל טייפ הוא תוצאה מהצהרה של קלאס שהוא תבנית להרבה ערכים כי העיקר של הטייפ הוא הפעולות שזמינים עליו.
    לא כן ב-TS שאפשר לעסוק ישירות עם המושג טייפ.
    לכן חשוב לחשוב על טייפים ב-TS כסטים, במקום כתבניות כמו בשפות קלאסיות

    GENERICS

    הדוגמה שהבאתי בפוסט הקודם לא היה מספיק ברור וגם לא כל כך מעשי
    אביא דוגמה מעשי ביותר
    נגיד שאתה בונה קליינט ל-API
    אתה יודע שה-API המדובר תמיד מחזיר תשובות בתבנית זה:

    type ApiResponse = {
      success: boolean
      data: object | undefined
      error: string | undefined
    }
    

    השימוש ככה:

    type User = { ... }
    type Transaction = { ... } 
    
    class ApiClient {
      // users
      getUserById(id: number): ApiResponse { ... }
      updateUser(newUser: User): ApiResponse { ... }
      // transactions
      listTransactions(userId: number): ApiResponse { ... }
      // ...
    }
    
    const apiClient = new ApiClient
    
    const res: ApiResponse = apiClient.getUserById(id)
    
    if (res.success) {
      const user = res.data
      // do something with user
    } else {
      console.error(error)
    }
    

    הבעיה בקוד הזה הוא שבשורה 18, הדבר היחיד ש-TS יודע על המשתנה user הוא שזה מסוג object אבל הוא לא יודע איזה סוג אובייקט.
    דרך אחת לטפל בזה הוא להצהיר על טייפ בשם UserApiResponse ושם להצהיר על הטייפ המלא של שדה data
    הבעיה היא שצריך לחזור שוב ושוב על הצהרה זו לכל סוג של XXXApiResponse
    אפשרות אחרת הוא להצהיר שהטייפ של res.data הוא User

    const user = res.data as User
    

    אבל בצורה זו מאבדים את הבטחת האבטחה של TS וצריך לסמוך על המתכנת שהצהיר נכון על הטייפ
    הפתרון הוא להשתמש ב-generic שהוא "טייפ בונה טייפים"
    ככה:

    type ApiResponse<T> = {
      success: boolean
      data: T | undefined
      error: string | undefined
    }
    
    type User = { ... }
    type Transaction = { ... } 
    
    class ApiClient {
      // users
      getUserById(id: number): ApiResponse<User> { ... }
      updateUser(newUser: User): ApiResponse<User> { ... }
      // transactions
      listTransactions(userId: number): ApiResponse<Transaction[]> { ... }
      // ...
    }
    
    const apiClient = new ApiClient
    
    const res: ApiResponse = apiClient.getUserById(id)
    
    if (res.success) {
      const user = res.data
      // user is type User
    } else {
      console.error(error)
    }
    

    בפסאודו קוד ההצהרה דומה לקוד כזה:

    const ApiResponse = function(T: type): type {
      return new Type(`{
        success: boolean
        data: ${T} | undefined
        error: string | undefined
      }`)
    }
    

    תנאים

    יש כמה בעיות בדוגמה שהבאתי למעלה עבור שימוש בתנאי
    א. זה לא כל כך מעשי
    ב. יש באג (הטייפ לא עושה מה שהתכוונתי שהוא יעשה - אולי אכתוב על זה בפוסט אחר) ואין לי ממש דרך לפתור את הבאג
    ג. השתמשתי בתחביר שלא הצגתי מקודם (אינדוקס)

    אני רוצה להביא דוגמה מעשית פשוטה שבונה על הדוגמה הקודמת

    נגיד שה-API מחזיר לפעמים אובייקט יחיד ולפעמים מערך
    אם הוא מחזיר מערך אז יש שדות נוספות בתשובה
    אולי נגיד שדה count שמחזיר כמה אובייקטים יש בסה"כ
    איך נגדיר type כזה?

    type BaseApiResponse<T> = {
      success: boolean
      data: T | undefined
      error: string | undefined
    }
    
    type ApiResponse<T> = T extends any[] ? BaseApiResponse<T> & { count: number } : BaseApiResponse<T>
    

    אפשר לתרגם את זה לקוד פסאודו זה:

    function ApiResponse(T: type): type {
      const base = `{
        success: boolean
        data: ${T} | undefined
        error: string | undefined
      }`
      if (T instanceof Array(any)) {
        return `base & { count: number }`
      } else {
        return base
      }
    }
    

    Mapped Types

    הבאנו למעלה דוגמה שהיא גם מסובכת מדי וגם לא כל כך מעשי לשימוש יומיומי
    אני רוצה להביא דוגמה נורמלית מתוך הטייפים המובנים (TS מגיע עם "ספרייה סטנדרטית" של טייפים מובנים)
    נבנה על הדוגמה הקודמת שלנו של קליינט API
    אז אתה רוצה להגדיר שהפונקציה updateUser מקבל אובייקט מסוג User אבל בשונה מ-User, כל השדות הם אופציונליות. (כי מי שרוצה לעדכן רק שדה אחת לא צריך לשלוח את כל השדות)

    אז אפשר לכתוב טייפ חדש

    type User = {
      name: string
      foo: string
      bar: number
    }
    
    type UserUpdate = {
      name?: string
      foo?: string
      bar?: number 
    }
    

    אבל זה בזבוז נייר דיו וביטים, וכמובן זה לא DRY מה שאמור לזעזע כל מתכנת ששוה משהו

    הפתרון הוא:

      updateUser(newUser: Partial<User>): ApiResponse<User> { ... }
    

    השתמשנו ב-helper (כך נקראים "פקונציות" אלו שעוזרים לבניית טייפים מבוססים טייפים קיימים) בשם Partial שלוקח טייפ ומחזיר טייפ עם אותם שדות, רק שכולם נהיים אופציונליים
    איך עובד ה-helper הזה?
    נסתכל בקוד המקור:

    type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
    

    מילת המפתח in עובד ככה: עבור כל חבר ב-union שצד הימני מייצג, הוא מריץ את הביטוי שאחרי הנקדותיים כאשר המשתנה P מייצג את החבר הזה מה-union

    שימו לב לתחביר שלא הצגנו מקודם: T[P] - זה אינדוקס בטייפ שעובד בדיוק כמו אינדוקס אובייקט רגיל. T[P] הוא הטייפ של שדה P בתוך טייפ T

    נתרגם את זה לפסאודו קוד:

    function keyOf(o: object): union {
        return new Union(Object.keys(o))
    }
    
    function Partial(T: type): type {
        const res = {}
        for (const P in keyOf(T)) {
            res[P] = T[P] | undefined
        }
        return res
    }
    

    (סליחה. בפסאודו קוד הזה השתמשתי במוסכמות אחרות מהקטעים הקודמים. בקודמים יצרתי טייפ על ידי העברת מחרוזת ל"בנאי של הטייפ" - כביכול. הפעם לשם נוחות התייחסתי לטייפ כאובייקט. זה רק פסאודו קוד כמובן ואני מקווה שהכוונה ברורה)

    תכנות

  • מתחיל לבנות אתר? תשקול להתשמש ב-filament
    yossizY yossiz

    מתחיל לבנות אתר? תשקול להתשמש ב-filament
    קיבלתי פרוייקט של בניית אתר. אני ממש לא מתכנת פרונט, לכן קצת חששתי מקבלת הפרוייקט
    מישהו המליץ לי על filament
    אחרי שימוש אינטנסיבי בזה בשבועיים האחרונים, אני מרגיש חובה להודיע לציבור כדי לא להיות מונע טוב מבעליו
    התאהבתי לגמרי
    זה נותן לך גם צד שרת וגם צד לקוח בצורה מאוד נוחה (לטעמי) עם הרבה אפשרות קסטומיזציה מהעיצוב עד לשכבות הנמוכות ביותר של הסטאק
    מכיון שזה בנוי על Laravel, מקבלים את כל הספרייות המצויינות של האקוסיסטם הלרבל-י

    זה פשוט תענוג, צד שרת וצד לקוח,
    אני ממליץ לנסות
    אגב, זה תומך לגמרי בעברית ו-RTL
    (אפשר להתרשם מהיכולות הבסיסיות המובנות באתר הדוגמה שלהם)

    אם יש שאלות בנושא, אני פה בפורום ואשמח לענות כמיטב יכולתי על נושאים קשורים לLaravel/Filament

    תכנות

  • איזה ספרייה/פריימוורק (מה זה בכלל, בעצם?...) מומלץ ללמוד כיום?
    yossizY yossiz

    למה צריך פריימוורק? ("מה זה בכלל בעצם?")

    פריימוורקים בעיקר מיועדים עבור ממשקים אינטראקטיביים לא טריוויאליים.

    איך שאני רואה את זה, הפריימוורקים מביאים לשולחן בעיקר שני דברים. (אולי פיספסתי כמה, בינתיים זה מה שעולה לי בראש)

    צורך מספר 1, data binding

    כדי לממש אינטראקטיביות בצד לקוח צריך: להאזין לאירועים של קלט מהמשתמש ← לתרגם את הקלט לפקודה ← לשנות את ה-state של האפלקציה לפי הפקודה הספציפית ← לעדכן את התצוגה בצורה שהיא תשקף את ה-state הנוכחי.

    (כדוגמה קונקרטית ניקח אפליקציית ניהול משימות (TODO) (- זה ה-hello world של ספרייות לבניית ממשקים אינטראקטיביים).
    כמובן אני מדבר על דוגמה שבו הרינדור הוא בצד הלקוח, כלומר, פקודה משנה את התצוגה מיד בדפדפן בלי ללכת לשרת להביא HTML חדש.
    מה נצרך לממש את זה?

    • נבנה ממשק פשוט שמציג רשימה של משימות, ליד כל משימה יש לחצן שמסמן אותו כ-"done". למטה יש תיבת טקסט שמקבל טקסט למשימות חדשות עם לחצן לידו "הוספה".
    • נשמור את רשימת המשימות במשתנה כלשהו
    • נאזין לכמה אירועים:
      • לחיצה על לחצן ה-done ליד אחד מהאירועים,
      • לחיצה על "הוספה" להוספת משימה חדשה
    • בכל אירוע צריך לעשות את התהליך הזה: לתרגם את האירוע לפקודה קונקרטית (לדוגמה: מחק משימה עם מזהה X, הוסף משימה עם הטקסט "XYZ") ← לבצע את הפקודה, (למחוק את המשימה ממערך המשימות, או להוסיף משימה למערך) ← לעדכן את התצוגה עם הרשימה העדכנית

    החלק של עדכון התצוגה לשקף את ה-state של האפליקציה, זה נקרה data binding כלומר אתה מאגד (binding) חלקים של הממשק, (תוכן טקסטואלי או עיצוב) לדאטה כלשהו. בחלק הזה הפריימוורקים עוזרים המון. ב-jquery או ב-JS פשוט אתה צריך להחזיק ראש על כל שינוי מה צריך לעדכן. וככל שהאפליקציה גודלת, כך המשימה נהיה יותר ויותר מסובכת עד בלתי אפשרית.
    מה שהפריימוורק מביא לשולחן זה האפשרות להצהיר בצורה דקלרטיבית על האיגודים שאתה רוצה, (תוכן span זה מאוגד למשתנה JS זה, או ul זה תקבל את רשימת המשימות ממערך זה), ולא צריך לטפל כלל בעדכון התצוגה. הפריימוורק מטפל בזה בצורה מושלמת. אתה פשוט מוסיף אבר למערך המשימות, והופ! התצוגה מתעדכנת עם עוד שורה.

    צורך מספר 2: חלוקה לרכיבים ובידוד בין הרכיבים

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

    דבר זה נכון גם בבניית ממשקים. ובזה הפריימוורקים מאוד עוזרים, הם נותנים לך מסגרת שבו תוכל לחלק את הממשק לרכיבים (קומפוננטים) כאשר כל רכיב מכיל את ה- state שלו, והלוגיקה שלו, והוא מבודד מחביריו, ומתממשק עם חבריו רק באמצעות ממשקים מוגבלים ומוגדרים.

    זה שינוי חשיבה חשוב מאוד כדי להצליח לשלוט בסיבוכיות של ממשק גדול.

    זה עוזר גם לשימוש חוזר לחלקים של הקוד, וגם לשליטה יותר קלה על הקוד.

    תכנות

  • פיצוח קאפצ'ה
    yossizY yossiz

    אתמול יצא לי לכתוב קוד לפצח קאפצ'ה של אתר מסויים. (אני לא נכנס כרגע לשיקולי אתיקה...).
    מכיון שנהניתי מאוד מהקלות וההצלחה רציתי לשתף את החברים...

    קאפצה לדוגמה:
    orig.png

    ועוד אחד:
    orig.png

    הרעיון ברור - 4 ספרות, קשקוש אחד או שניים ש(אמורים ל)עבור תוך הספרות, וזריית קצת פלפל שחור לשם קינוח.

    ℹ אגב, מעניין לדעת מי יוצר הקאפצ'ה? במקרה שלי מדובר באתר ASP .NET ושימוש בקומפוננט מחברת telerik בשם RadCaptcha. ראיתי במקום אחר שיש להם קאפצ'ות יותר מסובכות, אני לא יודע אם פה מדובר בגירסה ישנה או בהגדרות שונות.

    איך נפצח את זה?
    א) ננקה את התמונה עד כמה שנוכל,
    ב) נשתמש בספריית OCR כלשהו לקרוא את התוכן של התמונה הנקייה.
    השפה המועדפת עלי כרגע הוא JS.

    איך מנקים את התמונה?

    אם ננסה למצוא מכנה משותף לשני סוגי ה"רעשים" (דהיינו הנקודות והקשקוש) שלא נמצא בחלק שאנחנו רוצים לשמור, קל לשים לב שהרעש דק יותר מהספרות. אז יש לנו אסטרגיה פשוטה: שהתמונה תעבור דיאטה, כלומר, נמצא דרך לדלל את הכל החלק השחור, כך שהרעש ייעלם ונישאר עם התוכן.
    בתחום עיבוד תמונות דיגיטליות, הפעולה הזו של דיאטה נקרא dilate. הפעולה ההפוכה (השמנה) נקרא erode.

    ℹ בעצם זה הפוך, המשמעות של המילה dilate קשור להשמנה מכיון שהוא משמין את החלקים הלבנים, והמילה erode קשור לדילול מכיון שהוא מדלל את החלקים הלבנים. למה הפעולות מתייחסות לחלקים הלבנים? כי כידוע בגרפיקה דיגיטלית שחור הוא העדר צבע -- 0 ולבן הוא 255.

    טוב! הלאה לביצוע!

    בחרתי בספרייה זו לשם עיבוד התמונה ובספרייה זו לשם ביצוע ה-OCR.

    הנה שורת הקוד שמבצע את הניקוי:

    const image = await Image.load(imageBuffer);
    const resultImage = image.grey().dilate().erode().mask();
    

    יש כאן כמה נקודות לשים לב אליהם:

    • בייצוג הדיגיטלי של התמונה יש בברירת מחדל 4 ערוצים: RGBA, פעולות ה-dilate ו-erode אפשריים על ערוץ אחד בלבד, לשם כך קודם הופכים את התמונה לבעלת ערוץ אחד על ידי קריאה לפונקציית grey.
    • פעולות dilate ו-erode מקבלות פרמטר של כמה פיקסלים להשמין אותו או להיפך בכמה פיקסלים לדלל אותו. השתמשתי בברירת המחדל שהוא פיקסל לכל צד.
    • הפעולה האחרונה (mask) נקרא גם threshold הוא פעולה שהופכת את כל האפור לשחור או לבן. פיקסל שעובר את אחוז החסימה נהיה לבן ואם לא הוא נהיה שחור. אני עושה את זה כי אחרי ה-dilate עדיין נשארים רשמים אפורים.

    איך נראה התוצאה?

    res.png

    והשני:
    res.png

    יפה!

    עכשיו ל-OCR:

    const { createWorker, PSM, OEM } = require('tesseract.js');
    
    const worker = createWorker();
    await worker.load();
    await worker.loadLanguage('eng');
    await worker.initialize('eng', OEM.LSTM_ONLY);
    await worker.setParameters({
      tessedit_char_whitelist: '0123456789',
      init_oem: OEM.LSTM_ONLY,
      tessedit_pageseg_mode: PSM.SINGLE_BLOCK,
    });
    
    const res = await worker.recognize(resultBuffer);
    await worker.terminate();
    
    console.log(res.data.text);
    

    נקודות לשימת לב:

    • יש כמה פרמטרים שעוד לא למדתי את משמעותן ואולי יעזרו לשיפור הדיוק.
    • הפרמטר העיקרית הוא: tessedit_char_whitelist - כלומר רשימה לבנה של תווים מותרים. זה משפר את הדיוק מאוד.

    התוצאה:

    2964
    3582
    

    מגניב! התוכנה הצליחה!
    (יש עדיין טעויות בפחות מ-10% של המקרים. ויש עדיין מה לשפר בפרמטרים של ה-OCR).

    תכנות

  • עוקבים אחרי? מה לעשות?
    yossizY yossiz

    @חבר
    א. תתעלם
    ב. המהדרין ימצאו דרך להשבית הודעות כאלו
    ג. המהדרין מן המהדרין יסירו את האנטי וירוס לגמרי ויתקינו אנטי וירוס שלא משגעת את המח 🙂
    חנוכה שמח 🕎

    תוכנה

  • אשף הפקס נפתח לשניה ומיד נעלם, הבו פתרון
    yossizY yossiz

    @shraga אין לי פתרון, אבל כמה רעיונות, (סליחה על הפוסט הארוך, אתה לא חייב לקרוא הכל :))

    מה קורה כאשר תוכנה "נפתח לשבריר שניה ונעלם"? לכאורה יש 1 מתוך 2 אופציות - או שהתוכנה קרסה (בגלל חריגה שאינו מטופל ע"י התוכנה ואז ווינדוס מסיימת את התהליך) או שהתוכנה עצמה הבחינה במשהו חריג וסגרה את עצמה.

    איך נאבחן את הבעיה?

    שלב מינוס א. חיפוש גוגל... אני מאמין שזה כבר עשית 🙂

    (בעצם יש שלב שלפני חיפוש גוגל. שלב מינוס ב: צריך מינימום הבנה במחשבים כדי להבין את הבעיה מספיק לעשות חיפוש נבון, אם תחפש "פקס לא עובד, מה עושים!?!" לא תקבל כלום... זה גם בטח ידוע לך)

    (יש עוד שלב של נסיונות לפתור את הבעיה בלי להבין אותה, הסרה והתקנה מחדש, איתחול המחשב וכו' וכו' מדובר אחרי שנסית כל זה וזה לא עובד)

    עכשיו נלך מהקל אל הכבד...

    א. יש תכונה מאוד שימושי של תוכנת Everything, שאני משתמש בו כל הזמן, תוסיף עמודה "שינויים אחרונים" וסדר את הרשימה לפי עמודה זו, כך תראה בזמן אמת קבצים שנוצרים או משתנים במערכת. (בעצם אצלי ככה זה מוגדר כל הזמן, וכך יש לי תצוגה חיה של מה שקורה במחשב כל הזמן במחינת יצירת ושנויי קבצים. שמרת קובץ לפני שנייה ושכחת איפה שמרת? תפתח everything וזה יהיה בראש הרשימה. התקנת תוכנה - איפה הקבצים? תפתח Everything. וכן הלאה...)

    0_1546245596369_a60ebf03-eb4e-4b71-9ee9-d48082b2f6f8-image.png

    0_1546245265188_b25a97fc-498e-41d7-9743-8a00eeb7e0f0-image.png

    במקרה של קריסה מסתבר שתראה קבצים שנוצרים בתקיית WER (כלומר, Windows Error Reporting) ואז ייווצר קובץ בשם "Report.wer" שכולל בתוכו פרטי הקריסה.

    במקרה שהתוכנה עצמה הבחינה במשהו לא תקין ייתכן שיש קובץ LOG עם יותר מידע, ע"י Everything תראה מיד איפה זה.

    ב. מכיון שא"א שפתרון כל בעיה בכל תוכנה יהיה כתוב איפה שהו ברשת, צריך להכיר כלים לאבחון בעיות, והכלי בה"א הידיעה לבעיות כאלה הוא Procmon. חובה לכל משתמש מתקדם להכיר אותו! בכלי זה תוכל לראות כל מה שקורה במחשב. כל מפתח רג'יסטרי, כל קובץ, כל חיבור רשת שכל תהליך יוצר או פותח או מוחק וכו'. התוכנה כוללת יכולת סינון מתקדם כך שתוכל לקבל רק הרשומות שמעניינים אותך.

    בד"כ תראה שברגעים שלפני הקריסה, התהליך שקרסה ניסתה לגשת לקובץ או מפתח רג'יסטרי והגישה נדחתה או שהנתיב לא קיים.

    שוב פעם, אחרי גוגל, זה הכלי בה"א הידיעה לאיבחון בעיות!!!

    דוגמא קטנה: איפה ברג'יסטרי טמונות הגדרות רזולוצית מסך?
    http://tchumim.com/post/43748
    איך מגיעים לזה? באמצעות Procmon תוך כמה שניות!

    ג. במקרה של חריגה שלא טופלה וא"א לאבחן אותה באמצעות procmon אז מתשמשים ב-debugger. אבל זה לא לבעלי לב חלש...

    תוכנה

  • תכנה לניהול רשימות עם תגיות
    yossizY yossiz

    @www @מעלה-ומוריד תודה חברים על המחמאות 😊 אפשר לחזור חזרה לנושא...

    תוכנה
  • 1
  • 2
  • 3
  • 4
  • 5
  • 255
  • 256
  • 2 / 256
  • התחברות

  • אין לך חשבון עדיין? הרשמה

  • התחברו או הירשמו כדי לחפש.
  • פוסט ראשון
    פוסט אחרון
0
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום