تعليم لغة بيرل Perl و سي جي آي CGI

 

 

الدرس الثالث

 

 

 

هذا الدرس صعب إلى حد ما ، فتح مخك معي جيداً و ركز في القراءة .

بمجرد أن ابتكرنا برنامج بيرل ، فإن الطريقة الوحيدة التي يتفاعل بها مع وثيقة هتمل HTML هي الاتباع التام للقواعد و الآليات التي صممت لجعل الشبكة العالمية World Wide Web تعمل . من هذه الآليات سي جي آي CGI .

فهم متغيرات المحيط :

المحيط أو Environment هو مساحة من الذاكرة ترتبط فيها أسماء المتغيرات مع قيم السلسلة المقابلة لها . مثلاً ، إذا حاولت أن تشغل برنامج عن طريق أمر (تشغيل) Run من قائمة (إبدأ) Start و ليكن مثلاً برنامج Telnet فإن نظام التشغيل سوف يبحث في المحيط المحدد له ، و هو بالنسبة له مجموعة من المسارات و الفهارس التي يبحث فيها ليجد البرنامج و بمجرد أن يجده فإنه يشغله لك ، أما إذا لم يجده فإنه يعطيك رسالة خطأ .

إذا وضعت متغير في المحيط مرتبط بسلسلة معينة فإنه يمكنك استبدال أيهما بالآخر في أي وقت و من أي برنامج ينفذ إلى المحيط . باختصار ، فإن المحيط هو مساحة من الذاكرة فيها متغيرات ذات قيم معينة لا يشترط أن تكون أنت صانع هذه المتغيرات بل قد تكون هذه المتغيرات وضعها نظام التشغيل أو الخادم أو أي برنامج عامل على النظام في نفس الوقت .

يمكننا أن نوضح المحيط بمثال عملي كالتالي افتح نافذة الدوس Dos و اكتب السطر الآتي /

set FOOBAR="The most powerful thing in the world"

هذا السطر أسس متغير في المحيط هو FOOBAR ثم أعطى له سلسلة حرفية مقابلة له هي "The most powerful thing in the world" ، و هكذا فإن المتغير FOOBAR و مقابله موجودان في الذاكرة و يمكننا أن نستدعيهما بالأمر echo مع وضع اسم المتغير بين علامتي المتغير الخاصتين بالويندوز و هما %FOOBAR% ، هكذا يفهم الويندوز أننا نريد أن نستعرض أحد المتغيرات الموجودة في المحيط و يعرض لنا مقابله المتمثل في السلسلة الحرفية .

       حسناً فهمنا الآن معنى المحيط ، بالنسبة لبيرل فإنه يصل إلى المحيط عن طريق وضعه في مجموعة مترابطة خاصة تسمى ENV% .

           المجموعة المترابطة تشبه المجموعة العادية التي رمزها @ فيما عدا أن كل عضو أو عنصر في القائمة مرتبط بقيمة معينة و بالتالي فإن العنصر يتكون من جزئين : المتغير و قيمته ، و تكون العلامة المميزة للمجموعات المترابطة هي علامة النسبة المئوية % .

و يمكننا أن نستدعي المتغير FOOBAR الذي أسسناه في المحيط عن طريق بيرل بالطريقة التالية :

$FooBar=$ENV {'FOOBAR'};

أما إذا كنت تريد أن تضع متغير في المحيط فيمكنك ذلك بالطريقة التالية:

$ENV {'FOOBAR'}="The most powerful thing in the World";

حسناً ، لماذا إذن وضعنا علامة الدولار $ أمام ENV ؟ ألم نتفق على أن علامة المجموعات المترابطة ( و منها المحيط لأن بيرل يضعه في مجموعة مترابطة ) هي % ؟ حسناً تذكر أننا في الحالتين قد استدعينا أو أسسنا عنصراً واحداً فقط في مجموعة و بالتالي يعتبره بيرل قيمة عددية و يجب أن يكون مسبوقاً هو و اسم المجموعة بعلامة عددية و هي علامة الدولار $ .

إعداد متغيرات المحيط Environment :

يمكنك إعداد متغيرات المحيط بأي برنامج و هذه المتغيرات متاحة في المحيط لأي تطبيقات فرعية أخرى طالما أن البرنامج أو التطبيق الذي وضعهم يعمل ، و عندما ينتهي البرنامج تنتهي المتغيرات التي وضعها في المحيط .

و هكذا فإن المتغيرات التي يضعها الخادم في المحيط تكون متاحة لبرنامج بيرل عبر السي جي آي .

متغيرات محيط CGI :

عندما يعمل الخادم فهو يملأ مجوعة من المتغيرات المحيطية التي تصف بعض خصائصه ، و عندما يتصل زائر لموقعك بالخادم الذي يقع عليه موقعك فإن الخادم يعبيء متغيرات محيطية أخرى عن الاتصال الذي تم ، مثلاً من أين ، متى ، نوع المتصفح .. إلخ . في الجدول التالي مجموعة من متغيرات سي جي آي الشائعة التي يضعها الخادم في المحيط :

المتغير

الوصف

AUTH_TYPE

طريقة توثيق الوصول

CONTENT_LENGTH

الحجم بالبايت لأي معلومة تصل

CONTENT_TYPE

نوع أي معلومة تصل

GATWAY_INTERFACE

نسخة CGI التي تعمل على الخادم

HTTP_ACCEPT

أنواع MIME التي قبلها العميل

HTTP_REFERER

عنوان URL للعميل

HTTP_USER_AGENT

نوع المتصفح الخاص بالعميل

PATH_INFO

معلومات المسار الإضافية لتطبيق CGI

PATH_TRANSLATED

PATH_INFO مترجمة إلى مسار ملف

QUERY_STRING

معلومات عنوان URL المشفرة المرسلة من نموذج HTML بوساطة أمر GET .

  REMOTE_ADDR

عنوان آي بي IP للعميل 

REMOTE_HOST

اسم المجال للعميل

REMOTE_IDENT

معلومات عن الهوية الخاصة بالعميل

REMOTE_USER

تعريف المستخدم الذي يرسله العميل

REQUEST_METHOD

طريقة العميل في الطلب ( مثل HTML أو POST أو GET )

SCRIPT_NAME

عنوان URL الخاص بتطبيق CGI

SERVER_NAME

اسم الخادم

SERVER_PORT

قناة اتصال TCP/IP التي تم طلب الاتصال منها (عادةً 80 ل HTTP )

SERVER_PROTOCOL

اسم البروتوكول الذي يستخدمه الخادم المستعمل في الطلب

SERVER_SOFTWARE

اسم البرنامج أو التطبيق الذي يستخدمه الخادم

بعض مفاهيم بيرل الجديدة :

في عملية تصميم برنامج بيرل لطباعة متغيرات سي جي آي المحيطية لصفحة ويب سنتعلم تفاصيل مجموعات بير المترابطة و استخدام أداتين جديدتين :

كما ذكرنا ، فإن المجموعة المترابطة تشبه كثيراً المجموعة العددية فيما عدا أن هناك قيمتين في مكان كل فهرس بدلاً من قيمة واحدة ، تعرف القيمة الأولى باسم Key أو المفتاح ، و يستخدمها بيرل في الفهرس الداخلي للمجموعة ، و هذا الفهرس الداخلي يتم تركيبه عن طريق فرم المفاتيح .

فرم المفاتيح هو باختصار ترجمة قيمة المفتاح Key إلى مفتاح عددي يشير إلى القيمة مما يجعل عملية البحث تتم بسرعة و كفاءة . و كما علمنا أن بيرل يقدم علامة جديدة للدلالة على المجموعات المترابطة هي علامة النسبة المئوية % .

كتابة برنامج العرض :

البرنامج الذي سنكتبه الآن سوف يأخذ كلاً من متغيرات المحيط التي ذكرناها في الجدول ، بالإضافة إلى وصف قصير لها ، في مجموعة مترابطة تسمى EnvVarlist% . ثم يعد صفحة هتمل HTML و يطبع الأسماء و القيم الخاصة بكل المتغيرات حتى ينتهي من المجموعة كلها .

المجموعة المترابطة EnvVarlist% سوف تكون طويلة إلى حد ما ، لذلك سوف نعدها بطريقة تجعلها أكثر قابلية للقراءة مثل السطر التالي :

%EnvVarlist=

(

'AUTH_TYPE', 'Server\'s Authentication method is: ',

لاحظ أن الأقواس على السطر التالي و أنها تترك مسافة قبلها في بداية السطر ، و هذه المسافات غير ضرورية .

ملاحظة : إذا أردت يمكنك كتابة برنامج بيرل بأكمله على سطر واحد طالما أن كل جملة برنامج مفصولة عن الأخرى بشكل مناسب عن طريق الفاصلة المنقوطة ; و الأقواس المفتوحة و المغلقة . و لكن مع ذلك ، البرنامج الجيد هو البرنامج الأكثر قابلية للقراءة . هذا مهم بالنسبة للآخرين الذين قد سضطرون لاستعمال شفرتك ، و هو أيضاً مهم لك ، حيث ستكون قادراً على تتبع ما تفعله بصورة أفضل إذا كانت الشفرة موضحة بشكل جيد . و القواعد العامة لتوضيح الشفرة تتضمن أنه يجب عليك ترك مسافات في بداية السطر قبل كتل الشفرة ، و ألا تمتد أسطر الشفرة أكثر من الهامش الأيمن لمحرر النص الخاص بك . ترك المسافات في بداية السطر قبل كتل الشفرة يجعل مكان كل تكتل من الشفرة يبرز بوضوح . أما الأسطر الطويلة فتتطلب منك أن تعرض حتى حافة الشاشة و تأخذ خطوة إضافية لتتمكن من قراءتهم .

سوف نضع عناصر السلسلة للمجموعة في علامات اقتباس مفردة هذه المرة للتناسق بين المفاتيح و المعلومات . و هذا سوف يسبب مشكلة ، حيث أن الفاصلة العليا في كلمة Server's سوف تنهي السلسلة لأن البرنامج سوف يعتبرها علامة الاقتباس الثانية التي تنهي السلسلة . للخروج من هذا المأزق هربنا ببساطة من الفاصلة العليا في كلمة Server's بوضع رمز الهروب \ قبلها (هل تذكره ؟) ، إنه يعطي معنى خاص للحرف الذي يليه .

هل أنت مستعد لكتابة البرنامج ؟ اكتب السطور التالية في محرر النص و احفظها بإسم cgienv.pl :

#!c:/perl/bin

# cgienv.pl

# A Perl program to list some of the common CGI environment variables.

require "html.pl"; # call in HTML header and ender

# Fill an associative array with the variable names

# and short descriptions.

%EnvVarlist =

(

'AUTH_TYPE', 'Server\'s authentication method is: ',

'CONTENT_LENGTH', 'Lenght of any attached information: ',

'CONTENT_TYPE', 'Type of any attached information: ',

'GATEWAY_INTERFACE', 'CGI version on server is: ',

'HTTP_ACCEPT', 'Client will accept these MIME types: ',

'HTTP_REFERER', 'Referrer\'s URL is: ',

'HTTP_USER_AGENT', 'Client\'s browser is: ',

'PATH_INFO', 'Extra PATH information is: ',

'PATH_TRANSLATED', 'PATH translation is: ',

'QUERY_STRING', 'Query string sent by client is: ',

'REMOTE_ADDR', 'Client\'s IP address is: ',

'REMOTE_HOST', 'Client\'s domain name is: ',

'REMOTE_IDENT', 'Identity data sent by client is: ',

'REMOTE_USER', 'User ID sent by client is: ',

'REQUEST_METHOD', 'Client\'s request method is: ',

'SCRIPT_NAME', 'URL of the CGI application is: ',

'SERVER_NAME', 'Server\'s computer name is: ',

'SERVER_PORT', 'Connection made at this port: ',

'SERVER_PROTOCOL', 'Server is using this protocol: ',

'SERVER_SOFTWARE', 'Server is running this software: '

);

# Start up an HTML document , then run the variables out to

# it with their descriptions.

&HTML_Header ("Common CGI environment variables");

print "<body>", "\n";

print "<H1>Some of the common CGI environment variables</H1>", "\n";

print "<H3><I>Note: Some variables have no value.";

print "These will be blank.</I></H3>", "\n";

print "<HR>", "\n"; # Draw a rule.

while (($EnvironVar, $Desc) = each (%EnvVarlist))

{

print $EnvironVar, ": ", $Desc, $ENV{$EnvironVar}, "<BR>", "\n";

}

# Ship the HTML ender. We're done.

&HTML_Footer;

# End cgienv.pl

هل لاحظت أننا استدعينا بوظيفة require ملف جديد اسمه html.pl ؟ لا تقلق ، هذا الملف هو مجرد تدعيم أو تجميع للملفين اللذين صنعناهما و أسميناهما بإسم htmlend.pl و htmlhead.pl ، و يمكنك صنع هذا الملف بكتابة السطور التالية في ملف و حفظه بإسم html.pl :

# html.pl

# Contains header and ender subroutines for setting

# up HTML document from Perl.

 

# Set up a standard HTML header section with the page title passed

# on the command line.

sub HTML_Header

{

print "content-type: text/html"; #put up standard HTTP opening line.

print "<html>", "\n\n"; # Specify HTML document .

print "<head>", "\n\n"; # Specify header section.

print "<title>", "@_", "<title>", "\n\n"; # put up the title line.

print "<head>", "\n\n"; # End header section.

} # End HTML_Header.pl.

# Set up a standard HTML footer section. At this point,

# it simply ends the body and html sections.

sub HTML_Footer

{

print "\n", "</body>", "\n\n";

print "</html>", "\n\n";

} # End HTML_Footer.

1;

تذكر أن الكسل و عدم الصبر هما من صفات المبرمج الجيد . فوضع كلاً من هاتين الوظيفتين الفرعيتين في ملف واحد يقلل سطراً كاملاً من الكتابة ، و كذلك يسهل عليك تصحيح الأخطاء .

الآن إلى البرنامج الأول cgienv.pl لقد أنشأنا مجموعة مترابطة تسمى EnvVarlist و وضعنا فيها رموز بعض متغيرات سي جي أي المحيطية الشائعة كعناصر لها و فصلنا بين كل عنصر و الآخر بفاصلة ، و تركنا مسافة قبل وضع علامة الاقتباس الأخيرة من كل عنصر و ذلك حتى لا يتشابك مع الكلمات التي سوف تأتي بعده عندما نطبعه في صفحة HTML .

تذكر أن العنصر الواحد يتكون من جزئين : المتغير و قيمته . و العنصر الأخير في المجموعة لم نضع بعده فاصلة ، و ذلك لأنه آخر عنصر في المجموعة و لا يوجد عنصر بعده .

وظيفة each و كتلة شفرة while :

while تنفذ الجملة التي بين الأقواس حتى تصبح غير صحيحة فتتوقف . هذه الجملة بين الأقواس تنقسم إلى قسمين يفصل بينهما علامة = و each :

while (($EnvironVar, $Desc) = each (%EnvVarlist))

و العبارة كلها تعني أن يضع قيمة المفتاح الأول أو العنصر الأول من المجموعة المترابطة EnvVarlist% في المجموعتين EnvironVar$ و Desc$ حيث أن العنصر الواحد في المجموعة المترابطة يتكون من جزئين كما عرفنا . ثم يزيد أو يضيف واحد لينتج بذلك قيمة المفتاح أو العنصر الثاني و يضعه في المجموعتان المذكورتان و هكذا إلى أن يصل إلى نهاية المجموعة و لا يجد عناصر أخرى فإن each تنتج قيمة NULL التي تعني الصفر إلى كل من المجموعتان EnvironVar$ و Desc$ مما يجعل جملة while غير صحيحة و ينتهي الدوران .

الدوران Loop الذي تنشؤه while لا يقتصر على الجملة التي تليها فقط ، بل تنشيء دوران آخر لطباعة عناصر المجموعتين EnvironVar$ و Desc$ في :

{

print $EnvironVar, ": ", $Desc, $ENV{$EnvironVar}, "<BR>", "\n";

}

حيث يطبع البرنامج عنصري المجموعتين مفصولين بعلامة : ، ثم يطبع بعدهما قيمة المتغير الموجود كعنصر في المجموعة EnvironVar$ الموجودة في المحيط و رمزه ENV% ، و لكننا بما أننا سنطبع قيمة مجموعة واحدة التي بدورها تمثل متغير واحد في المحيط الذي يضعه بيرل في مجموعة مترابطة تسمى ENV% فإننا سنستبدل علامة مجموعة المحيط المترابطة % بعلامة الكمية العددية $ لأننا سنأخذ عنصر واحد من عناصرها .

لاحظ بعناية عدد الأقواس في جملة while فالأقواس المفتوحة يجب أن تلائم الأقواس المغلقة ، و يجب أن تتأكد من هذا و إلا فإن المترجم سيشتكي بمرارة .

إدارة المثال :

الآن شغل المتصفح و تأكد من أن Sambar Server فعال و شغل الملف cgienv.pl كالمعتاد :

ستجد أن بعض المتغيرات فارغة لم يكتب أمامها قيمة ، و يجب أن تتذكر أن العديد من القيم المعروضة على صفحة الويب خاصة بالخادم الذي تم تشغيل البرنامج عليه ، و من المحتمل جداً ان ترى معلومات مختلفة عندك .

في هذا البرنامج بالرغم من أننا قد أدخلنا أعضاء المجموعة EnvVarlist% بالترتيب الأبجدي ، إلا أنهم لم يظهروا بهذا الترتيب عند تشغيل البرنامج ، و هذا نتيجة لعملية فرم المفاتيح التي تحدثنا عنها في وقت سابق . أيضاً لأن each و while لا يرتبان العناصر بل يأخذان المجموعة من أعلى لأسفل في الوقت الذي تكون فيه عناصر المجموعة قد تغير ترتيبها نتيجة لعملية فرم المفاتيح .

هناك وظيفة أخرى تؤدي نفس عمل each و while و لكنها ترتب العناصر في نفس الوقت و تصنفهم ، هذه الوظيفة هي sort ، و هي تعمل مع أداتين أخرتين هما :

غير كتلة شفرة while في cgienv.pl إلى هذا :

foreach $EnvironVar (sort (keys (%EnvVarlist)))

{

print $EnvironVar, ": ", $ENV{$EnvironVar}, "<BR>", "\n";

}

جملة foreach مثل جملة while تصنع دوران loop لتستخلص في كل مرة عنصراً واحداً فقط من المجموعة الموجودة بين الأقواس ، فيما عدا أنها لا تأخذ عنصر المجموعة المترابطة EnvVarlist مباشرة بل تأخذ قيمة المفتاح التي وضعتها وظيفة key في مجموعة عادية ، و في نفس الوقت فإنها لا تأخذها من أعلى لأسفل مثل each و while بل تأخذها حسب الترتيب الأبجدي نظراً لأنها تستعمل وظيفة sort .

لاحظ أننا استبعدنا جزء Desc$ من المثال لأنها قد تمثل مشكلة تتراوح بين عادية و متوسطة ، و نحن نريد أن نحافظ على الأشياء بسيطة لك .

و إذا شغلت الملف cgienv.pl بعد التعديل سوف ترى شكل مشابه لهذا :

حسناً ، العناصر الآن مرتبة حسب الترتيب الأبجدي .

 

 

 

استفسار ؟ راسلني

 

الدرس الرابع