ארכיון חודשי: נובמבר 2012

Working with Shared Libraries in Perl

Here are my slides for a lecture I gave at Perl mongers:

In case you'll download the slides, you'll also have my notes inside.
Enjoy 🙂

כשהשעון מראה 25

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

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

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

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

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

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

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

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

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

מוגש כחומר למחשבה

מלח הארץ

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

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

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

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

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

מידע, כריית מידע ואתם

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

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

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

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

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

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

שירים מתקדמים עם סינטרה חלק ראשון

יש לי פרוייקט ארוך טווח, שדורש ממני ליצור גם API מבוסס web, גם ממשק גרפי שידבר איתו, ועוד מספר דברים שונים.

כאשר התחלתי לחקור מה אני צריך לנושא, התחלתי לעשות בדיקות של הרבה מאוד סביבות עבודה, בניהם django, rails, ramaze, dancer, padrino, tornado ועוד מספר מערכות מבוססות Node.js.

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

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

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

Why PHP must be abandoned (in my opinion)‎

Foreword

Every now and then, I find myself using PHP as a programming language.
I started using it since the early of 2000, and never really liked it.
Most people like it not because it is good, but because it is easy to "get inside" and start developing stuff with it.

But that's exactly one of it's biggest problems in the world.
I do not want that a programming language will be "easy" to start with, I want it to be good with what it suppose to provide.

First of all, easy is a relative word. That is, you must compare it to something. Back in the days, it was easier to start with PHP then with Perl for example. But when you actually start to "enter" inside the language, well, it's not really a programming language per-se, but a group of a lot of tools that allow you to have some sort of glue to use them.
It does not really act as a language (like with Perl), but a borrow stuff from other languages, such as Perl, C and few others.

Recently I found yet another problem with PHP. I got a 3rd party source code that explains to me how to implement a protocol that reinvent the wheel of HTTP REST using "JSON" like code, but with it's own TCP header, rather then to use plain old HTTP.

Problem

The way that they implement it, is really weird, because instead of using the "pack" function, they are using their own bit manipulation code (poorly), and use the "chr" function to convert each byte into an ASCII value representative.

They code it like so:

 chr(1000 >> 0) . chr(1000 >> 8) ....
The problem is that chr(1000)  (shift right by 0, keeps 1000 as 1000) must report an error, because 1000 is bigger then the last ASCII code (127), or extended ASCII code (255).
I'll explain it again: 1000 is bigger then the range of 255 . ASCII is only at the range of 0..127 chars, but extended ASCII provides extra chars up to 255 (full byte length).
Note: Even a numeric value of 256 is bigger then one byte !
With Ruby for example, I get "RangeError" exception for such action, so does with Python, Pascal, Perl (with strict bytes) and few other programming languages.
While with PHP, well it returns the value of 232.
You must shout out loud, "wait, WHAT ?" if you haven't done it by now.
I'll say it again: "chr(1000)" with PHP returns the value of 232.
It is doing so due to bit manipulation ($value & 255), but it's actually type of an integer overflow IMHO.Why you ask ? Well, the aim of "chr" is to provide one character of ASCII value. The spec of ASCII chars is very very very simple:
Range of a char is 0 to 127 (they write ASCII and not extended ASCII).If you are converting an integer value to it's ASCII value, and the last value is 255 (going extended ASCII here), then what is the representation of the 1000 value in extended ASCII ?
Answer: You do not have one.
That's why normal languages (give or take) return an error that you are out of range.When you give an answer that is not an error, then it means that there is a representation for the value. but 1000 is not 232, it's 1000, and 1000 is out of range.So you might call it a bug right ?
Well according to a person that works at Zend, it is a feature, and the bug is that it is undocumented feature.

Here it is (typos are from the original email):

First of all, this is not integer overflow. integer overflow is hwen the aritmethic result can not be held in integer. here, the function translate what it can and should, which is the last significant byte. I don't see a problem with that except of that is should be documented. if you test 1000 & 255 (the last byte of 1000) you will see that the result is indeed 232.

Oh, and this is the bug I opened for it, so you can follow it yourself.
And It's not the first or last of such "features" within the so called "language".

End

I for one, do not welcome our PHP overlords.
And I think that it's time to abandon this patched "ship" you call a language. The benefits of going in fast, are payed in the long run. with many problems that you actually require an IDE for not loosing your leg by hitting a mine.

יחידות בדיקה עם fpcUnit

הקדמה

ישנם מספר ספריות לבדיקה עבור שפת פסקל. הספרייה הכי וותיקה שאני מכיר נקראת DUnit, והיא שוחררה לראשונה ב1999, כמימוש jUnit עבור דלפי. ד"א jUnit למיטב ידיעתי היא מימוש ג'אווה של SUnit עבור שפת Smalltalk.
fpcUnit הוא סוג של מימוש מחודש עבור FPC ולזרוס. fpcUnit מגיע בשני טעמים:

  1. הצגה גרפית של בדיקות
  2. הצגה טקסטואלית (כולל ייצוא למספר פורמטרים) של בדיקות

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

צורת עבודה

הרעיון:

הרעיון הכללי הוא ליצור "תוכנה" אחת שמריצה הרבה unit tests, שבפסקל, זה באמת יחידות :). היחידות נרשמות בחלק ה initialization של היחידה, באמצעות RegisterTest. אשר לוקח את המחלקה של הבדיקות ורץ על הפרוצדורות השונות לבדיקה.
המחלקה יורשת מ TTestCase, וכל פרוצדורות הבדיקה (הרי אנחנו רוצים לפרק את הבדיקות לחלקים הגיוניים), חייבת להיות בחלק ה published, בשביל שתוכל לרוץ.
ישנה מתודה אחת שבמידה וצריך לאתחל מידע, צריך להגדיר אותה (בחלק ה protected) בשם SetUp. במידה והגדרנו את SetUp מומלץ גם להגדיר מתודה בשם TearDown שעושה בדיוק הפוך.

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

יצירת מסד נתונים בזמן ריצה

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

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

createdb

אם אתם עוקבים אחרי הבלוג שלי, אתם יודעים כבר כי המסך הזה נוצר באמצעות לזרוס, ומדובר בסה"כ בLabel ו Edit , עם קינוח של Button.
בנוסף זרקתי רכיב לא וויזואלי של TIBConnection, שמטפל לנו בחיבור למסד נתונים מבוסס Firebird.

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

לאחר מכן, באירוע של הכפתור, אצור את הקוד הבא:

procedure TfrmDBCreate.btnCreateClick(Sender: TObject);
var Transaction : TSQLTransaction;
begin
  FBConnection.DatabaseName := edtDatabaseName.Text;
  FBConnection.CharSet      := 'UTF8';
  FBConnection.HostName     := edtHost.Text;
  FBConnection.UserName     := edtUserName.Text;
  FBConnection.Password     := edtPassword.Text;
  Transaction               := TSQLTransaction.Create(nil);
  FBConnection.Transaction  := Transaction;
  try
   FBConnection.CreateDB;
   FBConnection.ExecuteDirect('CREATE table test1 (name varchar(24) not null)');
   Transaction.Commit;
   MessageDlg('Info', 'The database was created.', mtInformation,
             [mbClose], -1);
  except
    on e : EIBDatabaseError do
     begin
       MessageDlg('Error', 'Could not create database : ' + LineEnding +
                  e.Message, mtError, [mbClose], -1);
     end;

     on e : Exception do
       begin
        MessageDlg('Error', 'Unknown error : ' + LineEnding + e.Message,
                 mtError, [mbClose], -1);
       end;
  end;
  Transaction.Free;
end;

קודם כל אנחנו מזינים לTIBConnection את הפרמטרים שהוזנו, כדוגמת קובץ מסד הנתונים, הכתובת של השרת, בנוסף החלטתי להשתמש ב UTF8 כקידוד למחרוזות.
בנוסף יצרתי רכיב עבור טרנזאקציות, הוא צריך להיות בשימוש לשאילתא שאריץ לאחר יצירת מסד הנתונים (כל השימוש בו).
בתוך try אני אומר למנהל החיבור למסד נתונים ליצור את מסד הנתונים. חשוב לדעת כי זה קיים בכל החיבורים שלנו למסדי נתונים המבוססים DataSet, ולא ייחודי ל Firebird.
לאחר מכן, החלטתי גם להציג כיצד ניתן ליצור בתוך אותו קוד טבלה, אז יצרתי טבלה בשם test1 עם שדה בשם name שהוא מסוג varchar ומסוגל לקבל עד 24 תווים.
נעשה על השאילת commit, ואנחנו מוכנים !

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

מי אמר שעבודה עם מסדי נתונים צריכה להיות כואבת ?

את קוד המקור תוכלו למצוא כאן