יום ראשון, 18 בדצמבר 2011

המרות של סוגי קבצים

ImageMagick
convert

יום חמישי, 27 באוקטובר 2011

Linux Run Level and Services Deamon config

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

הדברים מוסברים בצורה פשוטה כאן:
http://en.wikipedia.org/wiki/Runlevel
http://www.ubuntu-unleashed.com/2007/09/i-personally-like-gui-tools-but-i-also.html

אבל שתי תוכנות חמודות חדשות שמצאתי עוזרות לנהל את ספריית ה- rc בצורה נוחה:
rcconfig
ו - sysv-rc-conf
שתי התוכנות עם ממשק TUI שאני כל כך אוהב. (TUI - Text User Interface)
בניגוד ל - command line שדורשות פקודות בשורת הפקודה ובניגוד ל - GUI שמחייב הרצה של ממשק גרפי מלא (XServer) תוכנות TUI מאפשרות עבודה נוחה ב - text.

התוכנות מאפשרות ניהול והחלטה אילו deamons (שרותים) יופעלו באיזה runlevel.




יום שני, 19 בספטמבר 2011

UTF8 ובסיסי נתונים MySQL Database

זה כבר כמה זמן אני מעוניין לכתוב על ניהול נכון של Encoding בבניית אתרי אינטרנט. אנשים נוטים לבצע טעויות רבות ולא מבינים את המשמעות שבין UTF-8 לבין תקני ISO ותקנים של Windows כגון Windows-1255. הבעיות מופיעות בבחירה לא נכונה של Charset הן בבניית העמוד והן בשמירה ב - Database.

לצערי אין לי את הזמן כרגע, אבל אני בוודאי שעוד אחזור לכך ואסביר את כל שלבי ה - Encoding מה - Datbase דרך ה - Webserver וכלה בדף ה- HTML והתצוגה בדפדפן.

כרגע אני משתף קוד קצר ל - mysql שימיר לנו שדות טקסט ששמרנו בהם עברית ב - Charset latin1 ל - UTF8.


ALTER TABLE files ADD COLUMN temp TEXT CHARACTER SET utf8 COLLATE utf8_general_ci AFTER text; -- add the temp column

UPDATE files SET temp=CONVERT(CONVERT(text USING binary) USING utf8); -- convert the data to the new column


ALTER TABLE files DROP COLUMN text; -- drop original column


ALTER TABLE files CHANGE temp text TEXT CHARACTER SET utf8 COLLATE utf8_general_ci; -- rename temp column


Change hebrew / or other charset inside MySQL to UTF-8.


יום ראשון, 10 ביולי 2011

PHP וחילוץ נתונים מתוך HTML

במקרים רבים (ואנשים רבים שואלים אותי) אנחנו צריכים לחלץ נתונים מאתרי אינטרנט ודפי HTML.
מהי הדרך הטובה ביותר לעשות זאת? ומהי הדרך הנוחה ביותר לעשות זאת?

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

אך מה קורה אם אין אפשרות לגשת לאתר לקבלת מידע בפורמטים מקובלים כמו XML/RSS או JSON, ואנו נאלצים לפרסס (Parsing)\ לנתח את הדף בעצמנו?

לכך מצאתי כמה פתרונות נחמדים:
הראשון, הפשוט יותרת שימוש בפונקציה אשר מחלצת נתונים המופיעים בין שתי מחרוזות (strings).
השני המתוחכם יותרת והנוח יותר הוא שימוש בספריית php המיצרת לנו DOM בתוך ה - PHP ומאפשרת לבצע שאילתות DOM וכן Selectors מתוך קוד ה - php על דף ה - HTML אותו אנו מנסים לפענח.



לפתרון הראשון:
// $text - is the full text we are searching on
// $from - is the opening text we start taking data from
// $to - is array of optional ending text we will fetch text until
// text_between('this is a full text', 'is', array('text')) - will return: ' is a full '
function text_between($text, $from, array $to)
{
$start = strpos($text, $from);
if($start === false)
return null;

$end = array();
for($i = 0; isset($to[$i]); ++$i)
{
$e = strpos($text, $to[$i], $start + strlen($from));
if($e !== false)
$end[] = $e;
}

$end = min($end);
return substr($text, $start + strlen($from), $end - $start - strlen($from));
}



הפתרון השני, שימוש בספרייה חיצונית הנקראת PHP Html DOM Parser
אשר מאפשר לבצע שאילתות DOM ישירות מתוך קוד ה - PHP גם באמצעות CSS Selectors כאילו אנחנו עובדים מתוך JavaScript או כל XML אחר.



// Create DOM from URL or file
$html = file_get_html('http://www.google.com/');

// Find all images
foreach($html->find('img') as $element)
echo $element->src . '';

// Find all links
foreach($html->find('a') as $element)
echo $element->href . '';




יום חמישי, 2 ביוני 2011

הפיכת XML ל - JSON

דינוזאורים עדיין עובדים על XML בכל מיני מקומות לצערי. זה נכון XML נותן הרבה יותר יכולות ש - JSON לא, אבל עדיין, JSON זה פשוט כיף.

לעיתים אנחנו נתקלים בצורך להמיר XML ל - JSON מתוך JavaScript, כמו לדוגמא בשימוש בתוך Firefox Extension או קריאות Ajax ו - XSS Cross Sites ּScripting.

ישנן הרבה ספריות ברשת להמרת XML ל - JSON רק חלקן ב - JavaScript ורובן לא עובדות.
מצאתי אחת שכן עובדת:
http://michael.hinnerup.net/blog/wp-content/uploads/2008/01/JsonXml.js
http://michael.hinnerup.net/blog/2008/01/26/converting-json-to-xml-and-xml-to-json/



/*
The below work is licensed under Creative Commons GNU LGPL License.

Original work:

License: http://creativecommons.org/licenses/LGPL/2.1/
Author: Stefan Goessner/2006
Web: http://goessner.net/

Modifications made:

Version: 0.9-p5
Description: Restructured code, JSLint validated (no strict whitespaces),
added handling of empty arrays, empty strings, and int/floats values.
Author: Michael Schøler/2008-01-29
Web: http://michael.hinnerup.net/blog/2008/01/26/converting-json-to-xml-and-xml-to-json/
*/

/*global alert */
var xmlJsonClass = {
// Param "xml": Element or document DOM node.
// Param "tab": Tab or indent string for pretty output formatting omit or use empty string "" to supress.
// Returns: JSON string
xml2json: function(xml, tab) {
if (xml.nodeType === 9) {
// document node
xml = xml.documentElement;
}
var nws = this.removeWhite(xml);
var obj = this.toObj(nws);
var json = this.toJson(obj, xml.nodeName, "\t");
return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
},

// Param "o": JavaScript object
// Param "tab": tab or indent string for pretty output formatting omit or use empty string "" to supress.
// Returns: XML string
json2xml: function(o, tab) {
var toXml = function(v, name, ind) {
var xml = "";
var i, n;
if (v instanceof Array) {
if (v.length === 0) {
xml += ind + "<"+name+">__EMPTY_ARRAY_\n";
}
else {
for (i = 0, n = v.length; i < n; i += 1) {
var sXml = ind + toXml(v[i], name, ind+"\t") + "\n";
xml += sXml;
}
}
}
else if (typeof(v) === "object") {
var hasChild = false;
xml += ind + "<" + name;
var m;
for (m in v) if (v.hasOwnProperty(m)) {
if (m.charAt(0) === "@") {
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
}
else {
hasChild = true;
}
}
xml += hasChild ? ">" : "/>";
if (hasChild) {
for (m in v) if (v.hasOwnProperty(m)) {
if (m === "#text") {
xml += v[m];
}
else if (m === "#cdata") {
xml += "";
}
else if (m.charAt(0) !== "@") {
xml += toXml(v[m], m, ind+"\t");
}
}
xml += (xml.charAt(xml.length - 1) === "\n" ? ind : "") + "";
}
}
else {
if (v.toString() === "\"\"" || v.toString().length === 0) {
xml += ind + "<" + name + ">__EMPTY_STRING_";
}
else {
xml += ind + "<" + name + ">" + v.toString() + "";
}
}
return xml;
};
var xml = "";
var m;
for (m in o) if (o.hasOwnProperty(m)) {
xml += toXml(o[m], m, "");
}
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
},

// Internal methods
toObj: function(xml) {
var o = {};
if (xml.nodeType === 1) {
// element node ..
if (xml.attributes.length) {
// element with attributes ..
var i;
for (i = 0; i < xml.attributes.length; i += 1) {
o["@" + xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue || "").toString();
}
}
if (xml.firstChild) {
// element has child nodes ..
var textChild = 0, cdataChild = 0, hasElementChild = false;
var n;
for (n = xml.firstChild; n; n = n.nextSibling) {
if (n.nodeType === 1) {
hasElementChild = true;
}
else if (n.nodeType === 3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) {
// non-whitespace text
textChild += 1;
}
else if (n.nodeType === 4) {
// cdata section node
cdataChild += 1;
}
}
if (hasElementChild) {
if (textChild < 2 && cdataChild < 2) {
// structured element with evtl. a single text or/and cdata node ..
this.removeWhite(xml);
for (n = xml.firstChild; n; n = n.nextSibling) {
if (n.nodeType === 3) {
// text node
o["#text"] = this.escape(n.nodeValue);
}
else if (n.nodeType === 4) {
// cdata node
o["#cdata"] = this.escape(n.nodeValue);
}
else if (o[n.nodeName]) {
// multiple occurence of element ..
if (o[n.nodeName] instanceof Array) {
o[n.nodeName][o[n.nodeName].length] = this.toObj(n);
}
else {
o[n.nodeName] = [o[n.nodeName], this.toObj(n)];
}
}
else {
// first occurence of element ..
o[n.nodeName] = this.toObj(n);
}
}
}
else {
// mixed content
if (!xml.attributes.length) {
o = this.escape(this.innerXml(xml));
}
else {
o["#text"] = this.escape(this.innerXml(xml));
}
}
}
else if (textChild) {
// pure text
if (!xml.attributes.length) {
o = this.escape(this.innerXml(xml));
if (o === "__EMPTY_ARRAY_") {
o = "[]";
} else if (o === "__EMPTY_STRING_") {
o = "";
}
}
else {
o["#text"] = this.escape(this.innerXml(xml));
}
}
else if (cdataChild) {
// cdata
if (cdataChild > 1) {
o = this.escape(this.innerXml(xml));
}
else {
for (n = xml.firstChild; n; n = n.nextSibling) {
o["#cdata"] = this.escape(n.nodeValue);
}
}
}
}
if (!xml.attributes.length && !xml.firstChild) {
o = null;
}
}
else if (xml.nodeType === 9) {
// document.node
o = this.toObj(xml.documentElement);
}
else {
alert("unhandled node type: " + xml.nodeType);
}
return o;
},
toJson: function(o, name, ind) {
var json = name ? ("\"" + name + "\"") : "";
if (o === "[]") {
json += (name ? ":[]" : "[]");
}
else if (o instanceof Array) {
var n, i;
for (i = 0, n = o.length; i < n; i += 1) {
o[i] = this.toJson(o[i], "", ind + "\t");
}
json += (name ? ":[" : "[") + (o.length > 1 ? ("\n" + ind + "\t" + o.join(",\n" + ind + "\t") + "\n" + ind) : o.join("")) + "]";
}
else if (o === null) {
json += (name && ":") + "null";
}
else if (typeof(o) === "object") {
var arr = [];
var m;
for (m in o) if (o.hasOwnProperty(m)) {
arr[arr.length] = this.toJson(o[m], m, ind + "\t");
}
json += (name ? ":{" : "{") + (arr.length > 1 ? ("\n" + ind + "\t" + arr.join(",\n" + ind + "\t") + "\n" + ind) : arr.join("")) + "}";
}
else if (typeof(o) === "string") {
o = o.toString();
var objRegExp = /(^-?\d+\.?\d*$)/;
if (objRegExp.test(o)) {
// int or float
json += (name && ":") + o;
}
else {
json += (name && ":") + "\"" + o + "\"";
}
}
else {
json += (name && ":") + o.toString();
}
return json;
},
innerXml: function(node) {
var s = "";
if ("innerHTML" in node) {
s = node.innerHTML;
}
else {
var asXml = function(n) {
var s = "", i;
if (n.nodeType === 1) {
s += "<" + n.nodeName;
for (i = 0; i < n.attributes.length; i += 1) {
s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue || "").toString() + "\"";
}
if (n.firstChild) {
s += ">";
for (var c = n.firstChild; c; c = c.nextSibling) {
s += asXml(c);
}
s += "";
}
else {
s += "/>";
}
}
else if (n.nodeType === 3) {
s += n.nodeValue;
}
else if (n.nodeType === 4) {
s += "";
}
return s;
};
for (var c = node.firstChild; c; c = c.nextSibling) {
s += asXml(c);
}
}
return s;
},
escape: function(txt) {
return txt.replace(/[\\]/g, "\\\\").replace(/[\"]/g, '\\"').replace(/[\n]/g, '\\n').replace(/[\r]/g, '\\r');
},
removeWhite: function(e) {
e.normalize();
var n;
for (n = e.firstChild; n; ) {
if (n.nodeType === 3) {
// text node
if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) {
// pure whitespace text node
var nxt = n.nextSibling;
e.removeChild(n);
n = nxt;
}
else {
n = n.nextSibling;
}
}
else if (n.nodeType === 1) {
// element node
this.removeWhite(n);
n = n.nextSibling;
}
else {
// any other node
n = n.nextSibling;
}
}
return e;
}
};


יום חמישי, 26 במאי 2011

jlinq הכיף שב - JavaScript

ספריית JavaScript חמודה שנתקלתי בה הינה ספריית jlinq.

jlinq היא ספריית JavaScript לביצוע שאילתות וחיתוכים על אובייקטי JSON מתוך JavaScript. משהו כמו לבצע שאילתות SQL על אובייקטים בזכרון במהלך הריצה של קוד JavaScript.

נניח ויש לנו אובייקט כזה:
data.users = [{id:1,name:'x', last:'y',age:32},
{id:2,name:'john', last:'do',age:10},
{id:3,name:'zoe', last:'brown',age:45},
{id:4,name:'jz', last:'kin',age:56}];

ננח שנרצה את כל המשתמשים שהשם שלהם מתחיל ב - j:
jlinq.from(data.users)
.starts('first', 'j').select()

ונניח שנרצה את כל אלו שהשם שלהם מתחיל ב - j והם מעל גיל 20 מסודרים לפי גיל:

jlinq.from(data.users)
.starts('first', 'j').greater('age',20).order('age').select()

הכוח של הספרייה הזו מאוד חזק. ומאפשרת המון שאילתות מאוד מתוחכמות שחוסכות לנו את כל לולאות ה - for שהיינו צריכים לכתוב.
הספרייה איננה דורשת jQuery ואפשר להשתמש בה בכל מקום ותואמת את כל הדפדפנים המתקדמים.

לאתר jLine


יום ראשון, 27 במרץ 2011

השוואת ביצועי JavaScript במנועי IE9 אל מול FireFox 4 ו - Chrome


השוואת ביצועי JavaScript במנועי IE9 אל מול FireFox 4 ו - Chrome,

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

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

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

למאמר המלא



יום שני, 14 במרץ 2011

שימוש בסלולרים של הקהל ליצירת מחשב על

באוגוסט 2008 יצרתי ביחד עםשני חברים תחת פרוייקט geekcon הדגמה מעניינת. הראנו כיצד שימוש בטלפונים הסלולריים של הקהל יכול לשמש כמחשב אחד חזק. הדגמנו זאת על ידי חישוב PI (פאי) לסיפרה ה - 20,000. מי ינצח, שימוש במחשב (לאפטופ Dual Core) או המחשב המבוזר המורכב מהטלפונים הסלולריים של באי הכנס.

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

אתם מוזמנים לצפות בהדגמה ב - YouTube.
חלק 1
חלק 2


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

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

ולסרטים עצמם:








בברכה.



יום ראשון, 6 במרץ 2011

המסנן - תוסף לכרום לסינון פרסומות מאתרי חדשות ישראליים

המסנן - תוסף לכרום לסינון פרסומות מאתרי חדשות ישראליים.

ובונוס, מסנן סמולנים.

http://www.c2kb.com/mesanen

יום ראשון, 27 בפברואר 2011

Data URI scheme שמירת תמונות בתוך HTML ללא שימוש בקבצים חיצוניים


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

  1. אנחנו רוצים לייצר מסמך word מתוך html שמכיל תמונות
  2. אנחנו רוצים לשלוח אימייל html
  3. שימוש ב - extensions שונים
  4. או סתם פשוט לייצר קובץ אחד גדול המכיל הכל

לשם כך קיים לנו Data URI scheme שמאפשר לנו לצרף (embed) מידע לתוך url בדף שלנו ובאותו אופן גם להחזיק תמונות.

דבר זה מתבצע באמצעות url שהוא בעצם המידע שלנו מקודד ב - 7Bit uuencode והוא נראה כך:

<img src="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP
C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA
AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J
REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq
ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0
vr4MkhoXe0rZigAAAABJRU5ErkJggg==" alt="Red dot" />

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

לקריאה נוספת:
http://en.wikipedia.org/wiki/Data:_URL

המרת תמונות ל - Data Url:
http://www.sveinbjorn.org/dataurlmaker





יום שישי, 4 בפברואר 2011

משחק זכרון עם תמונות שלכם או מהרשת

החזרתי לחיים את משחק הזכרון הממוחשב שכתבתי. המשחק על טהרת ה - JavaScript כמו שאני אוהב :)

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

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

יום חמישי, 20 בינואר 2011

שחזור grub לאחר התקנת Windows

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

ולכן, אין מתקינים מחשב עם ווינדוס ולינוקס ביחד?

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

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

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

נעלה מדיסק (Live Disk) של לינוקס.
נפתח את ה - Terminal.
ראשית נבדוק אלו מחיצות קיימות לנו על הדיסק:
sudo fdisk -l
נתחבר למחיצת הלינוקס הראשית שלנו.
sudo mount /dev/sda3 ./tmp/sda3
(יש להחליף את /dev/sda3 במחיצה הרלוונטית אצלכם במחשב)
(לא לשכוח לייצר את ספריית sda3 ב - tmp)

בספרייה זו ניתן להיכנס לספריית /boot/grub
נריץ את הפקודה הבאה לשחזור ה- grub
sudo grub-install --root-directory=/tmp/sda3 /dev/sda
(לא לשכוח להחליף את שמות הספרייה המתאימים)

עכשיו כאשר נתחיל את המחשב מחדש, נקבל ה - grub loader לבחירת טעינת מערכת ההפעלה.
במידה וווינדוס לא מופיע שם. ניתן לעלות על הלינודס הקיים ולהריץ:
sudo grub-update מתוך ה - Terminal.

קישורים:
RecoveringUbuntuAfterInstallingWindows
http://erickoo.wordpress.com/2009/06/14/how-to-add-vista-partition-to-grub-2-ubuntu-9-10-karmic-koala/
http://www.dreamincode.net/forums/topic/132272-how-to-recover-grub-after-windows-re-install/