تعليم لغة بيرل Perl و سي جي آي CGI
الدرس الخامس
ابتكار نماذج هتمل فعلية مع CGI و بيرل :
النماذج Forms في هتمل هي التي تجعل الشبكة العالمية متفاعلة ، فهي تجعلها شيء أكثر من مجرد مجموعة من الرسومات و الصور جيدة المنظر . النماذج هي التي سيستعملها زوار موقعك في الويب للاتصال بك كمسئول عن الموقع . هتمل تقدم النموذج و الشكل ، سي جي آي هي قلب الاتصال و البيرل هي المخ . بهذا تستطيع جعل موقعك على الويب مفيد لك و لزوارك .
بناء النماذج في الهتمل :
مفهوم النموذج في هتمل بسيط ، فهو يعطي المستخدم القدرة على إدخال معلومات بدلاً من عرضها فقط . و لكن هتمل لا تفعل أي شيء بالمعلومات أكثر من إرسالها لشيء ما يستطيع التعامل معها .
يمكنك بناء نموذج هتمل بسيط كالآتي :
<html>
<head>
<title>Visitor Information Form</title>
</head>
<body>
<H1 ALIGN="LEFT">Visitor Information Form</H1>
<HR>
<FORM ACTION="perl.htm" METHOD="GET">
<B>
Last Name: <INPUT TYPE="text" NAME="LastName" SIZE=16>
First Name: <INPUT TYPE="text" NAME="FirstName" SIZE=16>
<BR><BR>
Address: <INPUT TYPE="text" NAME="Address" SIZE=32>
City: <INPUT TYPE="text" NAME="City" SIZE=32>
<BR><BR>
<center>
<INPUT TYPE="submit" VALUE="Send Information">
<INPUT TYPE="reset" VALUE="Clear Form Fields"
</B>
</form>
</body>
</html>
احفظ هذه السطور بإسم form1.htm و افتحه بالمتصفح ، يجب أن تبدو النتيجة مشابهة للصورة :
يمكنك أن تجد دليل للواصفات Tags الخاصة بهتمل في موقعي في ركن الهتمل .
يوجد طريقتان لإرسال معلومات النموذج (أي المعلومات التي تم إدخالها في النموذج) و هاتان الطريقتان هما : GET و POST و يتم استعمالهما كوسيلة METHOD في الواصفة <FORM> استعملنا في هذا المثال GET ، و بشكل عام يتم استعمال GET للكميات الصغيرة من المعلومات و POST للكميات الكبيرة أو عندما تريد إخفاء المعلومات من المستخدم .
لكي نخدع المتصفح يمكنك ابتكار ملف اسمه perl.htm ليس فيه أي شيء سوى كلمة perl ، و احفظه في نفس المكان الذي حفظت فيه الملف form1.htm ثم شغل ملف الهتمل من المتصفح ، و املأ النموذج بأي شيء ملائم ثم اضغط على زر Send information . يجب أن ترى صورة مشابهة لهذا :
يستعمل هذا النموذج form1.htm القليل من تقنيات هتمل لأنه للغرض التعليمي ليس إلاّ .
سي جي آي و عناوين URL :
عناوين URL تم تطويرها كطريقة لتحديد المصادر على الإنترنت بسطر واحد من نصوص ASCII قابل للطبع . و ضع 3 خطوط تحت كلمة (قابل للطبع) ، و ستفهمها فيما بعد . و عناوين URL ليست مقيدة بالشبكة العالمية World Wide Web ، فمعظم أنظمة الإنترنت الكبيرة مثل FTP و HTTP و Gopher يمكن أن تقرأ و تفهم عناوين URL فقد تم تأسيسها بحيث تحتوي على :
بروتوكول خادم URL مثل (HTTP و Gopher و FTP) .
اسم مجال الخادم Domain Name .
رقم قناة TCP/IP أو البورت Port Number الخاصة بالخادم ، إذا تم حذفه سنعود إلى القناة الأساسية المعروفة للبروتوكول الذي تم به الاتصال .
مكان المصدر على الخادم Resource Location .
و يمكن تبعاً لذلك أن تقرأ عنوان URL الموجود في سطر العنوان في المتصفح بعد الضغط على زر Send Information كالتالي :
بالطبع المتصفح الخاص بك لن يظهر هذا العنوان عند الضغط على زر Send Information . و هذا لأنك لم تشغله على الإنترنت من موقع له إسم مجال Domain Name . سنناقش العنوان الذي ظهر لك في سطر العنوان في المتصفح في الفقرة التالية .
رموز قابلة للطبع :
مثل معظم أنظمة الإنترنت فإن عناوين URL كانت مصممة أصلاً لتأكيد أنه يمكن إرسالهم عن طريق البريد الإلكتروني . و معظم أنظمة البريد القديمة قادرة على التعرف على الرموز ذات 7 بتات فقط ، لذلك فإن الرموز المستعملة في URL يجب أن تخضع لهذا . بالإضافة إلى أن بعض هذه الرموز لها معنى خاص في عناوين URL ، على سبيل المثال الرمز (&) يستعمل لفصل الوسائط في سلسلة العنوان المطلوبة . و إذا اضطررت إلى استعمال مثل هذه الرموز يجب عليك أن تشفرها في شكل nn% حيث أن علامة النسبة المئوية توضح أن الرمزين التاليين لها هما القيمة الست عشرية للرمز الأصلي . مثال ذلك علامة الاستفهام إذا كانت موجودة ضمن المعلومات في النموذج فإنها يتم تشفيرها عند إرسالها كعنوان URL في سطر العنوان في المتصفح كالتالي :
%3f
لأن 3f هي القيمة الست عشرية لعلامة الاستفهام في جدول ASCII . أي أنك إذا كتبت كلمة ما تتضمن علامة الاستفهام فيها مثل Sin?gle سوف تجدها في سطر العنوان كالتالي Sin%3fgle .
الترقيم الست عشري (Hex) هو نظام ترقيم يسمح ب 16 رقم صحيح فقط . الأرقام من صفر إلى 9 تظل كما هي ، أما الأرقام من 10 إلى 15 تمثلها الحروف من A إلى F . مثلاً الرقم الست عشري FF يساوي في الترقيم العشري العادي 225 .
الجدول التالي به القيم الست عشرية المقابلة لبعض الرموز الخاصة في URL :
الرمز |
القيمة الست عشرية |
---|---|
Space |
20 |
Tab |
09 |
! |
21 |
" |
22 |
# |
23 |
$ |
24 |
% |
25 |
& |
26 |
` |
27 |
( |
28 |
) |
29 |
* |
2a |
+ |
2b |
, |
2c |
- |
2d |
. |
2e |
/ |
2f |
: |
3a |
; |
3b |
< |
3c |
= |
3d |
> |
3e |
? |
3f |
@ |
40 |
[ |
5b |
\ |
5c |
] |
5d |
^ |
5e |
_ |
5f |
` |
60 |
{ |
7b |
| |
7c |
} |
7d |
~ |
7e |
و بما أنك مبرمج CGI فسوف تكون في الطرف الآخر من هذا المخطط ، و لا يجب عليك أن تهتم بقيم ASCII المقابلة للرموز التي ستجدها ، بيرل يوجد بها العديد من المهارات البسيطة لتحويل القيم الست عشرية إلى حروف آسكي كما سترى قريباً ، الذي يجب عليك فعله في طرفك هو التعرف على الرمز المشفر و فصل علامة النسبة المئوية ، و إرسال الباقي إلى وظيفة بيرل التي ستترجمه لك بكل بساطة .
الآن إلى العنوان في المتصفح . عندما تستعمل طريقة GET لتمرير المعلومات من النموذج فإن المعلومات يتم إضافتها إلى نهاية عنوان URL كسلسلة لتطبيق CGI و مفصولة عن إسم التطبيق بعلامة الاستفهام ؟ و يتم بناء المعلومات في العنوان كأزواج تتكون من name=value أو الاسم=القيمة ، و يفصل كل زوج عن آخر بعلامة & . و كل المسافات في العنوان يتم استبدالها بعلامة الإضافة + . هذه الرموز الثلاثة ؟ & + بالإضافة إلى علامة النسبة المئوية % التي سوف تميز أي رموز مشفرة ، و علامة المساواة = التي تفصل بين الإسم و القيمة في كل زوج ، هؤلاء هم ما ستحتاج إلى التعامل معهم في برنامج البيرل و السي جي آي الذي ستكتبه .
هل تذكر متغير CGI المحيطي QUERY_STRING ؟ قد تكون لم تفهمه عندما قرأته في جدول المتغيرات في الدرس الثالث ، الآن تستطيع فهمه . إنه يحصل على المعلومات القادمة من نموذج هتمل إلى برنامج سي جي آي من خلال طريقة GET .
سنقوم الآن بكتابة تمرين بسيط بهذه المفاهيم و نتعلم بعض المفاهيم الجديدة في بيرل . هذا البرنامج سوف يقرأ المتغير QUERY_STRING و يفك شفرته و يطبع كل أسمائه و قيمه في صفحة هتمل . و إليك البرنامج :
#!perl/bin
# geturl.pl
# A little perl script to read, decode and print the names
# and values passed to it from an HTML form through CGI.
# Get HTML header, ender, define the page title.
require "html.pl"; # Full path.
$Title="Get Information from a URL";
# Get the query string.
$QueryString = $ENV{'QUERY_STRING'};
# Use split to make an array of name-value pairs broken at
# the ampersand character.
@NameValuePairs = split (/&/, $QueryString);
# Put up an HTML header, page title and a rule.
&HTML_Header ($Title);
print "<body>\n";
print "<H1>$Title</H1>\n";
print "<HR>\n";
# Split each of the name-value pairs and print them on the page.
foreach $NameValue (@NameValuePairs)
{
($Name, $Value) = split (/=/, $NameValue);
print "Name = $Name, Value = $Value<BR>\n"
}
# End the HTML document.
&HTML_Footer;
# End geturl.pl
احفظ البرنامج بإسم geturl.pl في فهرس cgi-bin ثم عدل الجملة ACTION=perl.htm في الملف form1.htm إلى المسار الصحيح إلى geturl.pl أنا مثلاً جعلته :
<FORM ACTION="/cgi-bin/geturl.pl" METHOD="GET">
ثم احفظ الملف في فهرس c:\program files\sambar\docs و شغل sambar server ثم شغل الملف form1.htm في المتصفح و أدخل بعض المعلومات في النموذج و لكن هذه المرة استعمل بعض الرموز التي سيتم تشفيرها عن طريق المتصفح عند شحنها من خلال CGI مثل + و ! ، ثم اضغط زر Send Information . يجب أن تكون النتيجة شبيهة لما هو موضح في الصورة التالية مع اختلاف المعلومات التي أدخلتها إلى النموذج بالطبع :
لاحظت بالطبع أن المعلومات المعروضة بواسطة البرنامج الذي كتبناه مليئة برموز غريبة و فواصل حسناً سوف نهتم بذلك في النسخة المعدلة . الآن دعنا نفحص كيف نقسم عنوان URL من سطر واحد إلى سلاسل من أزواج الأسماء و القيم Name و Value .
البطل في هذا البرنامج هو split ، و هي وظيفة قوية في بيرل شكلها العام هو :
split (/PATTERN/, STRING, LIMIT);
حيث PATTERN هي المحدد أو نقطة الفصل بين الأزواج / و في برنامجنا هي & .
أما STRING فهي السلسلة المراد تقسيمها ، و في برنامجنا هي المتغير QueryString$ .
أما LIMIT فهي اختيارية تخبر split ألا تفعل أكثر من انفصالات محددة .
تنتج split مجموعة من السلاسل منفصلة عن بعضها البعض ب PATTERN . و PATTERN توضع دائماً بين شرطتين مائلتين أماميتين ، و لكن يمكن ترك PATTERN إذا أردنا أن نضع مسافة فارغة للفصل بين السلاسل . كذلك يمكن أن يكون PATTERN تعبيراً منتظماً Regular Expression و هو موضوع سنغطيه بالدراسة لاحقاً .
لقد استعملنا المتغير المحيطي QUERY_STRING للحصول على عنوان URL مقدم من form1.htm و قد قسم إلى أزواج من name=value باستعمال split للفصل عند الرمز & . و قد قسمت الأزواج إلى أجزائهم المكونة لهم و وضعت علامة المساواة = بين كل جزء و الآخر كـ PATTERN .
و مع هذا فإن السلاسل لا يزال لديها رموز URL المشفرة و لكي نزيلهم منها سنعدل البرنامج و نضيف إليه سطرين فقط .
قوة التعبيرات المنتظمة Regular Expressions :
غير دوران foreach في geturl.pl للتالي :
foreach $NameValue (@NameValuePairs)
{
($Name, $Value) = split (/=/, $NameValue);
$Value =~ tr/+//;
$Value =~ s/%([\dA-Fa-f][\dA-Fa-f])/ pack ("C", hex ($1))/eg;
print "Name = $Name, Value = $Value<BR>\n";
}
إذا لم تعمل أبداً مع التعبيرات المنتظمة Regular Expressions فإن السطرين الجديدين من المحتمل أن يكونا أعجب الأشياء التي رأيتها في حياتك . و مع ذلك عدل البرنامج ، و املأ الفراغات في form1.htm باستعمال كل الرموز التي تريدها و النتيجة ستكون مشابهة لهذا :
إذا كان لديك شك في قوة بيرل فإن هذه المهارة البسيطة يجب أن تبدد هذا الشك . إذا أخافتك القواعد الغريبة و المحيرة للتعبيرات المنتظمة فيجب أن تشعر بالإثارة لتعلمهم ، فقد أنجزت في سطرين من الشفرة ما كان يحتاج في الماضي إلى برنامجاً كاملاً لعمله في C أو ++C .
السطر الأول الجديد سهل إلى حد ما :
$Value =~ tr/+//;
التعبير العام لها هو :
"$String =~/PATTERN/"
الرمز ~= هو مشغل Operator التناسب ، و يكون صحيحاً إذا كان المتغير String$ يحتوي على ال PATTERN . و بوجه عام هو يبحث في سلسلة المتغير String$ عن النموذج PATTERN الموجود بين الشرطتين التاليتين .
أما tr فهي وظيفة الترجمة Translate ، التي تحول كل الرموز الموجودة بين أول شرطتين مائلتين أماميتين إلى الرموز الموجودة بعدهما . و شكلها العام هو :
tr/SEARCH_LIST/REPLACE_LIST/
حيث SEARCH_LIST هي الرموز التي نريد استبدالها ، و في حالتنا هنا هي علامة الإضافة + . أما REPLACE_LIST فهي الرموز التي سيتم وضعها مكان SEARCH_LIST , و في حالتنا هي فراغ لأننا لم نضع مكانها شيء .
هناك وسائط إختيارية تأتي بعد الشرطة المائلة الأخيرة لوظيفة tr و هم : c و d و s و U و C . نحن لا نحتاجهم في هذه النقطة . و لكن سنبين معناهم للتوضيح :
c: تكون لتكملة الرموز التي نريد استبدالها .
d: تحذف الرموز التي وجدت و لم يتم استبدالها .
s: يسحق الرموز التي تم تغييرها مرتين .
U: يحول من و إلى تنسيق UTF-8 .
C: يحول من و إلى رموز 8 بت .
و هكذا يفحص هذا السطر سلسلة المتغير Value$ و تستبدل كل حدوث لعلامة + بمسافة .
السطر الثاني أكثر حيلة و أصعب في الفهم :
$Value =~ s/%([\dA-Fa-f][\dA-Fa-f])/ pack ("C", hex ($1))/eg;
هذا السطر يحول رموز URL المشفرة أي المسبوقة بعلامة % ، إلى رموز قابلة للطبع .
الوظيفة s هي وظيفة الاستبدال في بيرل و هي مثل tr تأخذ كل شيء تجده في سلسلة المتغير Value$ مناسباً للسلسلة بين أول شرطتان مائلتان و تستبدله بما هو موجود بين الشرطتان المائلتان الثانيتان .
في هذا المثال تم إخبار الوظيفة s أن تبحث علامة % متبوعة برمزين ، كل رمز منهم قيمه محددة بين قوسين مربعين [ ] . الآن انظر داخل القوسين المربعين الأولين ، و هو يخبر s أن الرمز الأول بعد علامة النسبة المئوية % ، إما أن يكون رقم صحيح و يرمز له برمز الهروب متبوع بحرف d أي d\ ، و إما أن يكون حرف من A إلى F أو من a إلى f ، و هي أرقام ست عشرية كما عرفنا تدل على الأرقام من 10 إلى 15 . كذلك القوسين المربعين التاليين يحددان قيم الرمز الثاني بعد علامة % مثل قيم الرمز الأول تماماً بدون أي اختلاف . و هكذا فإن الرمزين بعد علامة % في عنوان URL إما أن يكونا رقم صحيح من صفر إلى 9 أو رقم ست عشري من A إلى F أو من a إلى f أو خليط منهما معاً .
وظيفة pack هي وظيفة تأخذ مجموعة من القيم و تحولها إلى سلسلة باستخدام تعليمات القالب المعطى لها كسلسلة بين علامتي اقتباس و هو في هذه الحالة C . و السلسلة الناتجة تكون مرتبة بنفس تسلسل القيم التي أخذتها وظيفة pack . و القالب C يخبر pack أن تعبيء القيمة في رمز .
وظيفة hex تأخذ التعبير التالي لها (و هي تتوقع أن يكون رقم ست عشري) و تحوله إلى رقم عشري صحيح .
($1) تسمى predefined name أي اسم معرف من قبل ، و هو ذي معنى خاص في بيرل . و هو يعود على الأقواس المربعة التي تحدد قيم الرمزين المشفرين بعد علامة % .
الحرف e في نهاية السطر يوضح للوظيفة s أن كل ما هو موجود في REPLACE_LIST إنما هو تعبير expression و ليس سلسلة . و بدون هذا الحرف فإن الرموز بعد علامة % في المتغير Value$ سوف يتم استبدالها حرفياً بـ :
pack ("C", hex ($1))
و لن يتم استبدالها بنتيجة هذا التعبير و إنما بالتعبير نفسه .
الحرف g بعد e يخبر s أن تقوم باستبدال شامل أي أن تستبدل كل مثال من SEARCH_LIST تجده في Value$ بما تم حسابه في التعبير الموجود في REPLACE_LIST . و إذا تركت هذا الوسيط جانباً فإن s قد تقوم بالعملية في أول تكرار ثم تقف .
القاعدة التي ستراها غالباً في التعبيرات المنتظمة هي استخدام 1$ و 2$ , 3$ إلى آخره ، هذه المتغيرات العددية تتطابق من اليسار إلى اليمين مع التعبيرات بين الأقواس في SEARCH_LIST . على سبيل المثال السلسلة :
19 May 1997
قد تنقسم إلى أجزائها كالتالي :
$String =~ /(..)(...)(....)/;
$day = $1;
$month = $2;
$year = $3;
و لكن ضع في اعتبارك أن هذه المتغيرات مساوية للتعبيرات المنتظمة و ليس للحروف و الأعداد ، بل أياً كان الغرض من التعبير المنتظم فإن نتيجته سوف يعبر عنها المتغير 1$ ... إلخ .
أنت محق : التعبيرات المنتظمة صعبة :
لا تقلق إذا لم تستطع الفهم سريعاً ، بالتدريج و التدريب سوف تستطيع فهمها ، كلما اكتسبت خبرة أو مهارة جديدة فإن برامجك ستستفيد من هذه المعرفة .
و سوف تتعلم بعض التفاصيل الصعبة للتعبيرات المنتظمة في هذا المقال الذي وجدته على الإنترنت في هذا الموقع و هو أسهل مقال تعليمي عن التعبيرات المنتظمة وجدته حتى الآن و قد ترجمته إلى العربية لتعم الفائدة بإذن الله .
استفسار ؟ راسلني