تعليم لغة بيرل Perl و سي جي آي CGI (تكملة)
الكاتب: غير معروف
http://www.angelfire.com/rnb/forarabs
الدرس
الخامس
الدرس
السادس
الدرس الخامس
ابتكار نماذج هتمل فعلية مع 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$ ... إلخ .
أنت
محق : التعبيرات المنتظمة صعبة :
لا تقلق إذا لم تستطع الفهم
سريعاً ، بالتدريج و التدريب سوف تستطيع فهمها ، كلما اكتسبت خبرة أو مهارة
جديدة فإن برامجك ستستفيد من هذه المعرفة .
الدرس السادس
في الدرس السابق قمنا بعمل
نموذج هتمل HTML Form يمكن لزائريك إدخال المعلومات فيه وإرسالها إلى برنامج
بيرل عبر السي جي آي . و مع ذلك فقد كان هذا تدريب بسيط ، فأنت قد أرجعت
المعلومات كما هي للزائر .
في هذا الدرس سوف نبني صفحة ويب أكثر صعوبة
و برنامج للتعامل معها ، سوف نصمم نموذج استفهام و نرسل معلوماته و نعيد
الحقول الخالية فيها إلى الزائر ليملئها ، و سوف نستعمل طريقة POST لإرسال
المعلومات من النموذج إلى برنامج CGI .
أفضل طريقة لتتعلم شيئاً ما هي
أن تفعله بنفسك ، دعنا نقوم بعمل نموذج استفهام بسيط و بذلك يمكننا رؤية كيف
يعمل . اكتب صفحة هتمل التالية و احفظها بإسم quiz.htm :
<html
dir="rtl">
<head>
<title>Quiz
Form</title>
</head>
<body>
<H1
ALIGN="CENTER">A Little Quiz
Form</H1>
<HR>
<H3 ALIGN="RIGHT">في كل فئة
اختر ما يناسبك أو يناسب تفضيلاتك</H3>
<FORM
ACTION="/cgi-bin/quiz.pl"
METHOD="POST">
<table>
<tr>
<td
VALIGN="top">
<B>الجنس</B><BR>
<INPUT
TYPE="radio" NAME="gender" VALUE="0">ذكر<BR>
<INPUT
TYPE="radio" NAME="gender" VALUE="1">أنثى<BR>
<INPUT
TYPE="radio" NAME="gender"
VALUE="2">غيرهما<BR>
</td>
<td
VALIGN="top">
<B>العمر</B><BR>
<INPUT
TYPE="radio" NAME="age" VALUE="0">12-18<BR>
<INPUT
TYPE="radio" NAME="age" VALUE="1">19-25<BR>
<INPUT
TYPE="radio" NAME="age" VALUE="2">26-30<BR>
<INPUT
TYPE="radio" NAME="age" VALUE="3">أكبر من 30<BR>
<INPUT
TYPE="radio" NAME="age" VALUE="4">شيخ
قبيلة<BR>
</td>
<td
VALIGN="top">
<B>فيلمك
المفضل</B><BR>
<INPUT TYPE="radio" NAME="film"
VALUE="0">Matirx<BR>
<INPUT TYPE="radio" NAME="film"
VALUE="1">Gladiator<BR>
<INPUT TYPE="radio" NAME="film"
VALUE="2">Mission Impossible2<BR>
<INPUT TYPE="radio"
NAME="film" VALUE="3">الكيت كات<BR>
<INPUT TYPE="radio"
NAME="film" VALUE="4">الإرهاب و الكباب<BR>
<INPUT
TYPE="radio" NAME="film" VALUE="5">ليس
فيهم<BR>
</td>
<td
VALIGN="top">
<B>هل تعتقد أن عادل إمام قد صار كبيراً على
التمثيل</B>
<INPUT TYPE="checkbox"
NAME="OldAdil">
</td>
</tr>
</table>
<h3
ALIGN="RIGHT">معلومات
اختيارية</h3>
<B>الإسم</B><BR>
الأول<INPUT
TYPE="text" NAME="firstname" SIZE="16">
الأخير<INPUT
TYPE="text" NAME="lastname"
SIZE="16"><BR>
<BR>
<CENTER>
<INPUT
TYPE="submit" VALUE="إرسل">
<INPUT TYPE="reset"
VALUE="إمسح">
</CENTER>
</form>
</body>
</html>
المفترض أن يبدو الشكل كما في الصورة :
هذا الشكل يستعمل أزرار راديو و صندوق اختيار و صندوقين للنص ، و لذلك
سيعطي برنامج بيرل مزيج جيد نوعاً ما من أنواع المداخل المختلفة ، بالإضافة
إلى أنه يستعمل طريقة POST لتمرير المعلومات بدلاً من طريقة GET التي
استعملناها في الدرس السابق . و كما ترى فقد حفظته في فهرس Docs في Sambar في
Program files .
الآن سنقوم بعمل تعديلات بسيطة على برنامج geturl
الذي كتبناه في الدرس السابق . الفرق الرئيسي بين طريقتي GET و POST هو في
كيفية تمرير المعلومات ، GET تضع المعلومات في عنوان URL بالفعل و تشحنها إلى
المحيط و يمكنك رؤيتها في صندوق العنوان في المتصفح ، بينما POST تضع
المعلومات في مجرى مدخل برنامج بيرل ، كما لو كنت تكتب المعلومات في الداخل
من لوحة المفاتيح . لذلك فإن برنامج geturl سوف يحتاج إلى تعديلين لمجاراة
الاختلافات :
# Get HTML header, ender, define the page
title.
require "/cgi-bin/html.pl"; # Full path.
$Title =
"GEt POST Information From a URL";
# Get the length of the
data.
$DataLen = $ُENV{'CONTENT_LENGTH'};
# Read the data
from standard input.
read (STDIN, $QueryString, $DataLen);
#
Use split to make an array of name-value pairs broken at
# the
ampersand character.
@NameValuePairs = split (/&/,
$QueryString);
أضف السطور السابقة الموضوع أمامها السهم إلى
الملف و احذف السطرين :
# Get the query string.
$QueryString =
$ENV{'QUERY_STRING'};
و احفظه بإسم quiz.pl في cgi-bin بالطبع
.
STDIN و POST :
لأن معلومات النموذج تأتي
من المدخل الأساسي بطريقة POST فيمكنك استعمال وظيفة read لتدخلها في برنامجك
. و للاختصار وظيفة read تأحذ هذا الشكل :
read (HANDLE, BUFFER,
LENGTH);
حيث HANDLE هو توجيه الملف كما عرفنا . و BUFFER هو
متغير عددي للإمساك بأي شيء يقرأه . و LENGTH هو عدد الرموز أو البايتات التي
ستقرأ في الذاكرة المؤقتة . و لكي تحصل على قيمة HANDLE فإن بيرل يجعل هذا
سهلاً ، ففي كل مرة تشغل فيها برنامج بيرل يعلن مسبقاً عن وجود مجموعة من
توجيهات الملف التي تسمح لبرنامجك بالتفاعل مع نظام التشغيل و فتح و إغلاق
الملفات ، و من بين هذه التوجيهات :
STDIN و هو طريق المدخل
الرئيسي .
STDOUT و هو طريق المخرج الرئيسي .
و كما ترى فإن
STDIN مفتوح لك بالفعل كل ما عليك هو أن تستخدمه . و أخيراً يجب عليك أن تخبر
read بعدد البايتات الموجودة ليقرأها ، و لحسن الحظ فإن محيط CGI يحتوي على
متغير به نفس المعلومات المطلوبة في read و هو المتغير CONTENT_LENGTH . و
نتيجة لكل هذه المساعدة من بيرل و سي جي آي يصبح لديك القليل لتفعله في تعديل
البرنامج ، عليك أن تحصل أولاً على طول المعلومات و هذا يتم بالسطر
:
$DataLen =
$ُENV{'CONTENT_LENGTH'};
ثم تستعمل هذا الطول في قراءة المعلومات من
المدخل الرئيسي في متغير محلي عددي (و هو BUFFER في الصيغة العامة أو
QueryString في برنامجنا) :
read (STDIN, $QueryString,
$DataLen);
الآن بعد أن فهمت عمل ما أضفت من سطور ، شغل المتصفح
(تأكد من تشغيل Sambar Server) و في صندوق العنوان اكتب
localhost/docs/quiz.htm ثم املأ النموذج بما ترغب و اضغط زر إرسل ، و سوف
تكون النتيجة في الغالب مشابهة لهذه :
لاحظ أن النموذج quiz.htm يعين قيمة عددية لكل زر راديو في كل فئة ،
مثلاً فئة فيلمك المفضل بها ستة أزرار راديو كل زر له رقم من صفر إلى خمسة و
بالتالي فالبرنامج يظهر لك القيمة العددية للزر الذي اخترته . يمكننا أن نعين
لكل زر قيمة إسمية (سلسلة) تصف الزر ، و لكن هذا يجعلهم أكثر صعوبة في
التعامل معهم ، إذاً ليس أمامنا خيار (و لا طماطم) سوف نكتب برنامجاً يعرض
القيم الإسمية للأزرار ، شغل محرر النص و اكتب الآتي :
#!perl/bin
# quiz.pl
# A little
perl program 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 "htmlara.pl"; # Full
Path.
$Title = "تفضيلاتك الشخصية";
$MaxData = 6;
#
Assign names to indexes to make them more descriptive.
($Sex,
$HowOld, $FaveFilm, $OldAdil, $LastName, $FirstName) = (0..5);
#
Set up a flag for the OldAdil checkbox.
$OldAdil = 1;
# Set
up a series of arrays to handle the form data.
@Gender = ("ذكر",
"أنثى", "غيرهما");
@Age = ("12-18", "19-25", "26-30","أكبر من 30",
"شيخ قبيلة");
@Film =
(
"Matrix",
"Gladiator",
"Mission
Impossible2",
"الكيت كات",
"الإرهاب و الكباب",
"ليس
فيهم"
);
# Get the length of the data.
$DataLen =
$ENV{'CONTENT_LENGTH'};
# Read the data from standard
input.
read (STDIN, $QueryString, $DataLen);
# Use split to
make an array of name-value pairs broken at
# the ampersand
character. then get the values.
@NameValuePairs = split (/&/,
$QueryString);
$n = 0;
foreach $NameValue
(@NameValuePairs)
{
($Name, $Value[$n]) = split (/=/,
$NameValue);
$n++;
}
# Set or clear $OldAdil flag
based on the number of pairs
# counted in $n. The checkbox value
won't be sent if it's
# not checked. Adjust indexes too.
if
($n != $MaxData)
{
$OldAdil =
0;
$FirstName--;
$LastName--;
}
# Put up an
HTML header, page title and a rule.
&HTML_Header
($Title);
print "<body>\n";
print
"<H1>$Title</H1>\n";
print "<HR>\n";
#
Print the information in a friendly manner.
print "<H3>اسمك
";
# See if anything has been entered in the name.
if
(($Value[$LastName] eq "") && ($Value[$FirstName] eq ""))
{
print "غير معروف\n";
}
else
{
print
"$Value[$FirstName] $Value[$LastName]\n";
}
print
"</H3>\n";
print "<H3>جنسك
$Gender[$Value[$Sex]]</H3>\n";
print "<H3>عمرك
$Age[$Value[$HowOld]]</H3>\n";
print "<H3>فيلمك المفضل
هو ";
print
"\"$Film[$Value[$FaveFilm]]\"</H3>\n";
print "<H3>أنت
";
if (!$OldAdil)
{
print "لا
";
}
print "ترى أن عادل إمام قد صار كبيراً على التمثيل
</H3>\n";
# End the HTML document.
&HTML_Footer;
# End quiz.pl
احفظه بإسم quiz.pl في فهرس cgi-bin ثم شغل
النموذج من المتصفح و املأه و اضغط على زر إرسل ، سترى شيئاً مثل هذا
:
هذا هو أكبر برنامج نكتبه حتى الآن ، و الآن إلى الشرح :
في أول
البرنامج استدعينا الملف htmlara.pl و هو نفس الملف html.pl ما عدا أن واصفة
<html> فيه تدعم العربية أي تجعل اتجاه الصفحة من اليمين إلى اليسار ،
و هذا مهم لكي يستطيع البرنامج أن يرسم صفحة ويب عربية ، كل ما عليك هو أن
تفتح الملف html.pl و تعدل الواصفة <html> في أوله إلى :
<html dir="rtl">
و احفظه بإسم htmlara.pl .
قد تكون لاحظت
أننا في هذا البرنامج قد أزلنا الأسطر التي تفك شفرة رموز URL ، و لهذا إذا
كتبت في النموذج في حقلي الإسم باللغة العربية ستظهر مشفرة في النتيجة . و
السبب في ذلك هو الاختصار ليس أكثر ، و لكن ينبغي عليك أن تضع هذه الشفرة في
كل برامجك القادمة .
أول سطر جديد في البرنامج يعكس جزءاً هاماً من
المعلومات التي تحتاجها ، و هو عدد الفئات التي تتوقع استقبالها . أي عدد
فئات أزرار الراديو التي تتوقعها :
$MaxData = 6;
فأنت تبحث عن الفئات التالية :
1- الجنس . 2-
العمر . 3- الفيلم المفضل .
4- رأيه في عادل إمام . 5- الإسم الأول .
6- الإسم الأخير .
و بالتالي فإن MaxData$ سوف يتم استعمالها مؤخراً
في البرنامج للتأكد من الرقم الفعلي للفئات المرسلة بسبب المراوغة في صندوق
الاختيار الخاص بعادل إمام . حيث إن صندوق الاختيار إما أن يكون محدد أو غير
محدد ، و في حالة عدم تحديده فإنه لا يرسل أي شيء على الإطلاق و بالتالي فإن
المجموعات سوف يختل ترتيبها .
بصورة عامة أنت تعرف بالفعل أن كل
الفئات سيتم وضعها في مجموعة بناء على الترتيب الذي تم إرسالهم به ، و يمكنك
جعل البرمجة لديك أسهل بتحديد أسماء متغيرات وصفية للفئات ، فهم سيتم إرسالهم
بنفس الترتيب الذي تمت به كتابتهم في نموذج هتمل . كل فئة من الفئات تحمل رقم
من صفر إلى خمسة ؛ الفئة الأولى هي الجنس و تأخذ الرقم صفر ، يليها العمر و
يأخذ الرقم واحد ، و هكذا حسب ترتيبهم في نموذج الهتمل الذي كتبناه . السطر
التالي يعين لكل رقم يدل على فئة إسم متغير وصفي :
($Sex, $HowOld, $FaveFilm, $OldAdil, $LastName,
$FirstName) = (0..5);
و لاحظ أننا وضعنا اختصار للأرقام بدلاً من
كتابة كل رقم أمام اسم المتغير الخاص به . هكذا يمكنك فهم لماذا يجب أن نتأكد
من الرقم الفعلي للفئات المرسلة ، لأن صندوق الاختيار إذا لم يتم تحديده لن
يرسل أي شيء و بالتالي فإن المتغير التالي عليه سيأخذ رقمه و تصبح النتيجة أن
يكتب البرنامج في النهاية مثلاً أن العمر = الكيت كات .
بعد ذلك وضعنا
قيمة المتغير OldAdil$ تساوي واحد ، فالطريقة الوحيدة لرؤية ما إذا كان صندوق
الاختيار قد تم اختياره أو لا هو اختبار وجوده و هذا هو ما فعلناه في السطر
:
$OldAdil = 1;
مــلــحــوظــة : العلم Flag في لغة البرمجة هو قيمة
إما صحيحة أي تساوي واحد و إما خاطئة أي تساوي صفر ، تعرف هذه القيم بإسم قيم
Boolean و هي على إسم عالم رياضيات بريطاني يسمى George Boole عاش في القرن
التاسع عشر و اخترع جبراً مبنياً على المنطق الرمزي .
الجزء التالي من
الشفرة سهل فهمه :
@Gender = ("ذكر", "أنثى", "غيرهما");
@Age
= ("12-18", "19-25", "26-30","أكبر من 30", "شيخ قبيلة");
@Film =
(
"Matrix",
"Gladiator",
"Mission
Impossible2",
"الكيت كات",
"الإرهاب و الكباب",
"ليس
فيهم"
);
فأنت تريد أن تطبع أوصاف القيم التي أدخلها
زائرك في النموذج لذلك فأنت تضاعف النموذج في مجموعات لكل فئة زر راديو
.
و لاحظ أن السلاسل في كل مجموعة مكتوبة بنفس ترتيبها عندما كتبت في
نموذج الهتمل ، هذا مهم لأن البرنامج سوف يستقبل قيم عددية من النموذج و يجب
أن تتطابق الأرقام مع فهارس المجموعة و إلا فسوف تطبع المجموعة الخطأ في
النهاية . (إذا كنت ترى عناصر المجموعة بأعلى غير مرتبة فذلك راجع إلى أخطاء
التنسيق ، و يجب عليك أنت أن تكتب العناصر بالترتيب الصحيح في برنامجك)
.
بعد ذلك يشحن البرنامج أزواج الإسم = القيمة Name = Value من
المعلومات المرسلة له و لكن هناك اختلاف بسيط :
@NameValuePairs = split (/&/, $QueryString);
$n = 0;
foreach $NameValue
(@NameValuePairs)
{
($Name, $Value[$n]) = split (/=/,
$NameValue);
$n++;
}
هنا أسسنا متغير جديد هو n$ أعددنا قيمته تساوي صفر
، و هو عداد بيس فقط لعد رقم الفئات المرسلة إلى البرنامج و لكن كفهرس في
مجموعة من كل القيم في أزواج Name = Value . أنت لا تحتاج للأسماء لأنك
بالفعل تعرفهم ، و لكنك تحتاج متغير زائف لكي يمسك مكان الجانب الأيسر من
الانقسام من NameValue$ . و بالتالي تكون Value[$n$] أول عنصر عددي من مجموعة
Value@ على أول مرور من خلال كتلة foreach .
السطر التالي عليها يضيف
n$ مع المشغل ++ لذلك فسوف تكون مساوية لواحد على المرور الثاني و 2 على
الثالث و هكذا ، الآن أنت لديك مجموعة مليئة بكل القيم التي تم إرسالها من
النموذج . و كذلك لديك تعداد للقيم في n$ و هذا التعداد هو كيفية تحديد ما
إذا كان صندوق الاختيار الخاص بعادل إمام قد تم تحديده أو لا .
الجزء
التالي يقول :
if ($n != $MaxData)
{
$OldAdil
=
0;
$FirstName--;
$LastName--;
}
إنه إذا كان n$ لا يساوي MaxData$ راجع الدرس الرابع
لتذكر مشغلات المقارنة فصندوق تحديد عادل إمام سوف يكون قيمته صفر أي أنه غير
محدد و بالتالي سينقص FirstName$ و LastName$ واحد في الأرقام المقابلة لهم
في النموذج حتى يشيرا إلى الفئة الملائمة لهم و لا يحدث خطأ ، و هذا بمشغل
التناقص -- .
و أخيراً ، يكتب البرنامج المعلومات المصاغة إلى صفحة
هتمل و يعرضها ، هذه شفرة قد قمنا بكتابتها من قبل ، و لكنها هنا مع
استثنائين : أولهما جملة if التي تطبع الإسمين الأول و الأخير
:
print "<H3>اسمك ";
# See if anything
has been entered in the name.
if (($Value[$LastName] eq "")
&& ($Value[$FirstName] eq ""))
{
print "غير
معروف\n";
}
else
{
print "$Value[$FirstName]
$Value[$LastName]\n";
}
جملة if تختبر عناصر FirstName$ و LastName$ في
مجموعة Value@ لكي ترى إذا كانوا خاليين (السلاسل الفارغة يشار إليها بعلامتي
اقتباس لا شيء بينهما "" و علامة المقارنة eq التي تعني يساوي راجع الدرس
الرابع و كل جملة موجودة بين قوسين ، و يربط بين الجملتين العلامة &&
التي تعني مشغل (و) (AND) المنطقي . و بالتالي يكون معنى الجملة : إذا كانت
الجملة الأولى صحيحة و الثانية صحيحة إذاً نفذ الشفرة التي في الكتلة
.
مــلــحــوظــة : يوجد في بيرل كذلك مشغل (أو) (OR) المنطقي و يمثله
العلامة || .
الجملة التالية else تقول أنه في حالة كذب جملة أو جمل
if بأعلى نفذ كتلة شفرتي . هناك تنوع else يمزج الجملتين الشرطيتين و يبدو
مثل هذا :
if (هذا صحيح)
{
افعل
هذا;
}
elseif (ذلك صحيح)
{
نفذ
ذلك;
}
else
{
نفذ شيئاً
آخر;
}
الجدير بالاهتمام في كتلة if-else أيضاً هو الطريقة
التي يتم بها طبع الأسماء :
print "$Value[$FirstName]
$Value[$LastName]\n";
و هذا بسبب الطريقة التي تم بها إعداد الفهارس
الوصفية في أول البرنامج فيمكنك الذهاب مثلاً إلى الإسم الأخير بكتابة
:
$Value[$LastName]
و لكن الأمر يصبح معقداً أكثر مع القيم الأخرى لأن
النموذج شحن أرقام للإشارة إلى أزرار الراديو ، و أنت تستعمل الأرقام لالتقاط
سلسلة من المجموعات التي صنعتها في بداية البرنامج . لذلك إذا كنت تريد
الإشارة إلى (أنثى) التي تحمل رقم واحد في الفئة (الجنس) يمكنك كتابة
:
$Gender [$Value
[$sex]]=$Gender[1]="أنثى"
لاحظ أن جملة print التي تطبع فيلمك المفضل بها
علامات اقتباس هاربة "\ لأننا نريد لعلامات الاقتباس أن تظهر حول اسم الفيلم
في صفحة هتمل .
أخر كتلة شفرة ننظر فيها هي :
print "<H3>أنت ";
if
(!$OldAdil)
{
print "لا ";
}
print "ترى أن
عادل إمام قد صار كبيراً على التمثيل </H3>\n";
تذكر أن قيمة OldAdil$ قد تم إعدادها أو إزالتها
اعتمادا على ما إذا كان صندوق اختيار عادل إمام قد أرسل قيمة للبرنامج أو لا
. علامة التعجب في بيرل ! هي مشغل (لا)(NOT) المنطقي . و هذه الجملة تقول أنه
إذا لم يكن صندوق اختيار عادل إمام محدداً اطبع كلمة (لا) قبل الجملة الأخيرة
أما إذا كان محدداً فإطبع الجملة الأخيرة وحدها .
اعلى
الصفحة