اذهب إلى المحتوى

علاقة جافاسكريبت بتطور الإنترنت والمتصفحات


أسامة دمراني
اقتباس

يُعَدّ توفير فضاء مشترك للمعلومات نتواصل فيه من خلال مشاركة هذه المعلومات حلمًا بُنيت عليه الشبكة العنكبوتية، كما تُعَدّ عمومية هذه الشبكة لازمةً وضروريةً، إذ يستطيع الرابط الفائق hypertext link الإشارة إلى أي شيء سواءً كان شخصيًا أو محليًا أو عالميًا، مسودةً كان أو نسخةً منقحةً.

ـــ تِم بِرنَرز لي Tim Berners-Lee، الشبكة العنكبوتية العالمية: تاريخ شخصي قصير للغاية.

Picture of a telephone switchboard.jpg

سنتحدث في المقالات الباقية من هذه السلسلة عن متصفحات الويب، فبدونها لم تكن جافاسكربت لتكون أصلًا، وإذا وُجدت لسبب ما فلم يكن أحد ليلتفت إليها.

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

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

الشبكات والإنترنت

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

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

يستخدِم الحاسوب هذه الشبكة ليرسل بِتَّات من البيانات إلى حاسوب آخر، ويجب على كلا الحاسوبين معرفة ماذا يفترض لهذه البِتَّات أن تكون وماذا تمثل من أجل تحقيق تواصل فعال، ويتوقف معنى أي تسلسل من البتات على نوع الشيء المراد التعبير عنه وعلى آلية الترميز encoding mechanism المستخدَمة.

يصف بروتوكول الشبكة network protocol أسلوبًا من التواصل عبر أي شبكة، فهناك بروتوكولات لإرسال البريد الإلكتروني وجلبه ومشاركة الملفات، وحتى التحكم في الحواسيب التي قد تكون مصابةً ببرمجيات خبيثة، فيُستخدَم بروتوكول نقل النصوص الفائقة HTTP مثلًا -وهو اختصار لـ Hypertext Transfer Protocol- لجلب الموارد المسمّاة وكتل المعلومات مثل صفحات الويب أو الصور، كما يشترط على الجزء الذي سينشئ الطلب البدء بسطر يشبه السطر التالي مسميًا المورد وإصدار البروتوكول الذي يريد استخدامه:

GET /index.html HTTP/1.1

هناك قواعد كثيرة تحكم الطريقة التي يمكن للطالب requester فيها إدخال بيانات أو معلومات في الطلب، والطريقة التي يحزِّم الطرف الآخر بها الموارد المطلوبة، وهو مستقبِل الطلب الذي يعيد هذه الموارد إلى طالبها..

تُبنى أغلب البروتوكولات على بروتوكولات أخرى، حيث يتعامل بروتوكول HTTP مع الشبكة كما لو كانت أداة يضع فيها البِتّات ويتوقع منها الوصول إلى الوجهة الصحيحة بالترتيب المتوقع لها، لكن الواقع المشاهَد يقول عكس ذلك كما رأينا في مقال البرمجة غير المتزامنة في جافاسكريبت. ويعالِج بروتوكول التحكم في النقل TCP -اختصارًا لـ Transmission Control Protocol- هذه المشكلة بما أن كل الحواسيب المتصلة بالإنترنت تفهمه، وقد بُنيت أغلب عمليات التواصل في الإنترنت عليه أصلًا.

فكرة عمل بروتوكول TCP هي أنّ الحاسوب يجب أن يكون في وضع انتظار أو استماع للحواسيب الأخرى حتى تكلمه أو تراسله، كما يجب أن يكون لكل مستمِع رقمًا يسمى منفَذًا port ويرتبط به من أجل أن تستطيع استماع عمليات تواصل مختلفة في الوقت نفسه على آلة واحدة، كما تحدد أغلب البروتوكولات المنفَذ الذي يجب استخدامه افتراضيًا، فحين نريد إرسال بريد إلكتروني باستخدام بروتوكول SMTP مثلًا، فيجب أن تستمع الآلة التي نرسله من خلالها إلى المنفَذ 25، ثم سينشئ حاسوب آخر حينئذ اتصالًا من خلال التوصيل بالآلة الهدف مستخدمًا رقم المنفَذ الصحيح، فإذا استطاع الوصول إلى الآلة الهدف وكانت تستمع لهذا المنفَذ، فسنقول أنّ الاتصال تحقق بنجاح، كما يُسمى الحاسوب المستمع هنا بالخادم server والحاسوب المتصَل به بالعميل client.

يعمل مثل ذلك الاتصال على أساس خط أنابيب ثنائي الاتجاه يمكن للبِتّات أن تتدفق فيه من كلا الاتجاهين، مما يعني استطاعة كلا الحاسوبين إرسال البيانات واستلامها عبره، وبمجرد أن تُنقل البِتّات بنجاح، فسيمكن للآلة التي على الطرف الآخر قراءتها مرةً أخرى، وهذا النموذج مريح جدًا، بل يمكن القول أنّ TCP هو النموذج المجرَّد للشبكة.

الشبكة العنكبوتية العالمية The Web

تُعَدّ الشبكة العنكبوتية العالمية -أو الويب- مجموعةً من البروتوكولات والصيغ التي تسمح لنا بزيارة صفحات الويب داخل متصفح ما، وتشير كلمة الشبكة العنكبوتية فيها إلى حقيقة إشارة هذه الصفحات إلى بعضها بعضًا وارتباطها ببعضها، وبالتالي تكوّن شبكةً عملاقةً يستطيع المستخدِم التنقل خلالها بحُرية، كما يجدر بنا الإشارة هنا إلى أنّ هذه الشبكة ليست هي كل الإنترنت، فالأخير أوسع وأشمل.

لكي تكون جزءًا من هذه الشبكة، لا تحتاج إلا إلى توصيل آلة بالإنترنت وتجعلها تستمع إلى المنفَذ 80 ببروتوكول HTTP كي تستطيع الحواسيب الأخرى طلب مستندات وملفات منها، ويُسمى كل مستند على الشبكة بمحدِّد موقع الموارد الموحَّد Uniform Resource Locator -أو URL اختصارًا-، حيث يكون أشبه بما يلي:

  http://eloquentjavascript.net/13_browser.html
 |      |                      |               |
 protocol       server               path

يخبرنا أول جزء أنّ هذا الرابط يستخدم بروتوكول HTTP على خلاف بروتوكول HTTP المشفَّر مثلًا التي سيكون هكذا: https://‎، ثم يعرِّف الجزءُ الذي يليه الخادمَ الذي نطلب منه المستند، ولدينا في النهاية مسار من سلسلة نصية يعرِّف المستند المحدَّد أو المورد الذي نريد.

تحصل الآلات المتصلة بالإنترنت على عنوان IP يكون رقمًا يمكن استخدامه لإرسال رسائل إلى هذه الآلة، حيث يبدو هكذا:

149.210.142.219 أو 2001:4860:4860‎::‎8888

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

إذا كتبتَ محدِّد المواقع ذاك في شريط عنوان المتصفح، فسيحاول المتصفح جلب المستند الذي في ذلك الرابط وعرضه، فيبدأ بالنظر في العنوان الذي يشير إليه eloquentjavascript.net، ثم يستخدِم بروتوكول HTTP ليحقق اتصالًا بالخادم الذي في ذلك العنوان ويطلب المورِد ‎/13_browser.html، وإذا تم ذلك كله فسيرسل الخادم حينئذ مستندًا يعرضه لك المتصفح على الشاشة.

HTML

تُهيأ صفحات الويب التي تراها أمامك على الشاشة بتنسيق يتكون من تراكيب محددة، واللغة التي نكتب بها تلك التراكيب اسمها HTML أو Hypertext Markup Language وتعني لغة ترميز النصوص الفائقة، ويحتوي المستند العادي المكتوب بهذه اللغة على نصوص ووسوم tags، وتحدد التركيب البنائي لتلك النصوص كما تصف الأنواع المختلفة لها سواءً كانت روابط أو فقرات أو عناوين، وتبدو هذه اللغة هكذا:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My home page</title>
  </head>
  <body>
    <h1>My home page</h1>
    <p>Hello, I am Marijn and this is my home page.</p>
    <p>I also wrote a book! Read it
      <a href="http://eloquentjavascript.net">here</a>.</p>
  </body>
</html>

توفِّر الوسوم معلومات عن بنية المستند وتحاط بقوسين محددين هما رمزا "أصغر من" و"أكبر من" في الرياضيات كما ترى في المثال أعلاه؛ أما بقية النص فيكون نصًا عاديًا، كما يبدأ المستند بوسم ‎<!doctype html>‎ الذي يخبر المتصفح أن يفسر الصفحة وفق لغة HTML الحديثة وليس الإصدارات القديمة المختلفة منها والتي تكون عادةً قبل HTML5.

تمتلك مستندات HTML في الغالب ترويسةً head ومتن body، كما تحتوي الترويسة على معلومات عن المستند؛ أما المتن فيحتوي على النصوص التي في المستند نفسه، وفي هذه الحالة تقول الترويسة أنّ عنوان هذه المستند هو "My home page" وأنها تستخدِم ترميز UTF-8 الذي هو أسلوب نتبعه لترميز نصوص اليونيكود على أساس بيانات ثنائية.

يحتوي متن المستند على ترويسة واحدة، وهي <h1> التي تعني الترويسة الأولى، و<h2> حتى <h6> لتشير إلى ترويسات فرعية، كما يحتوي على فقرتين اثنتين محدَّدتين بوسم <p>.

تأتي الوسوم في أشكال كثيرة، فيبدأ العنصر مثل المتن أو الفقرة أو الرابط بوسم افتتاحي مثل <p>وينتهي بوسم غالق مثل ‎</p>‎، وقد تكون بعض الوسوم الافتتاحية فيها معلومات أكثر مثل وسم <a> في صورة أزواج من name="value"‎، وتسمى هذه المعلومات بالسمات attributes، وفي حالتنا فإن وجهة الرابط توضَّح بالآتي: 
 

href="http://eloquentjavascript.net"

 وتشير href هنا إلى مرجع لنص فائق hypertext reference.

قد لا تغلف بعض الوسوم أيّ شيء ولا تحتاج إلى إغلاقها، ويُعَدّ وسم البيانات الوصفية metadata الذي يأتي بصورة الآتية مثالًأ على ذلك:

 ‎<meta charset="utf-8">

إذا أردنا كتابة أقواس محددة <> داخل نص مستند لتظهر كما هي من غير تفسيرها على أنها محددات وسوم، فيجب كتابتها بصيغة خاصة بها، بحيث يُكتب القوس الابتدائي ‎<‎ الذي يمثل علامة "أقل من" في الرياضيات على الصورة ‎&lt;‎، وكذلك القوس الغالق ‎>‎ الذي يمثل علامة أكبر من في الرياضيات على الصورة ‎&gt;‎. وهكذا، نكتب محرف آمبرساند & ثم اسم المحرف أو رمزه ثم فاصلة منقوطة ;، وتُعرف هذه الصيغة باسم الوحدة entity، حيث تُستبدَل بالمحرف الذي تعبِّر عنه، وذلك مشابه للطريقة التي تُستخدَم بها الشرطة المائلة العكسية في سلاسل جافاسكربت النصية.

بما أنّ هذه الآلية تعطي معنى خاصًا لمحارف &، فإنها بذاتها تحتاج إلى تهريب بأن تُكتب ‎&amp;‎ لتظهر بصورتها إذا احتجنا إلى إظهارها في النص، وبالمثل لما بين قيم السمات المغلفة بعلامات تنصيص مزدوجة، إذ يمكن استخدام ‎&quot;‎ لإدخال محرف علامة التنصيص ليظهر بصورته.

تُحلَّل HTML بأسلوب يتسامح كثيرًا مع الأخطاء، فإذا كان أحد الوسوم مفقودًا من موضع ما أو نسينا كتابته، فسيكتبه المتصفح ليعالج الخلل، وقد اعتُمِد الأسلوب الذي يحدث به ذلك بحيث تستطيع الاعتماد على جميع المتصفحات الحديثة التي تفعل الشيء نفسه لمعالجة أخطاء الكتابة.

انظر المستند التالي الذي سيعامَل على أنه المستند الذي كتبناه في المثال أعلاه رغم أخطاء الصياغة والبناء التي فيه:

<!doctype html>

<meta charset=utf-8>
<title>My home page</title>

<h1>My home page</h1>
<p>Hello, I am Marijn and this is my home page.
<p>I also wrote a book! Read it
  <a href=http://eloquentjavascript.net>here</a>.

عرف المتصفح قد أنّ وسوم <html> و<head> و<body> ليست موجودة، وعرف أنّ الوسمين <meta> و<title> ينتميان إلى الترويسة، والوسم <h1> تعني أنّ متن المستند بدايته من هنا.

كما لم يعد هناك حاجة إلى إغلاق الفقرات بصورة صريحة بما أنّ بدء فقرة جديدة أو إنهاء المستند سيغلقها ضمنيًا، ولعلك لاحظت إن كنت منتبهًا إلى أن علامات التنصيص التي حول قيم السمات ليست موجودة أيضًا.

سنهمِل في هذه السلسلة وسوم <html> و<head> و<body> من الأمثلة للاختصار ولإبقاء الأمثلة بسيطة، لكن سنغلق الوسوم ونضيف علامات التنصيص حول السمات، كما قد نهمِل تصريح doctype وcharset، لكن لا يعني هذا أننا نشجعك على ذلك، فقد تجد المتصفح يتصرف بغرابة ويفعل أشياءً سخيفةً إذا أهملتها، لذلك نريدك أن تتصرف كما لو كانت البيانات الوصفية الخاصة بهما موجودة في الأمثلة حتى لو لم تكن ظاهرة فعلًا في النص أمامك.

HTML وجافاسكربت

ما يهمنا في HTML فيما يتعلق بهذه السلسلة هو وسم <script>، إذ يسمح لنا بإدخال شيفرة جافاسكربت داخل المستند.

<h1>Testing alert</h1>
<script>alert("hello!");</script>

ستعمل مثل تلك الشيفرة عندما يرى المتصفح وسم <script> أثناء قراءة HTML، وستُظهر الصفحة نافذة منبثقة حين تُفتح، كما تُشبه دالة alert في المثال أعلاه prompt إلا أنها تخرج نافذة منبثقة تعرض رسالةً ما دون طلب إدخال أي بيانات.

يمثِّل المثال السابق برنامجًا صغير الحجم؛ أما إدخال برامج كبيرة مباشرةً في HTML فهو غير عملي، وبدلًا من ذلك يمكن تزويد وسم <script> بسِمة src لجلب ملف سكربت خارجي من رابط URL ما، وهو ملف نصي يحتوي على برنامج جافاسكربت.

انظر المثال التالي حيث يحتوي ملف code/hello.js على البرنامج السابق نفسه alert("hello!")‎.

<h1>Testing alert</h1>
<script src="code/hello.js"></script>

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

يجب إغلاق وسم <script> دومًا بوسمه الغالق ‎‏‎<‏‏‏‎/‎script‎‏‏‎‎‏‎‏‏‏>‎ حتى لو كان يشير إلى ملف سكربت لا يحتوي أي شيفرة، فإذا نسيت ذلك، فسستُفسَّر بقية الصفحة على أنها جزء من السكربت.

تستطيع تحميل وحدات ES -التي وردت في مقال الوحدات Modules في جافاسكريبت- في المتصفح بتزويد وسم script بسِمة type="Module"‎، كما يمكن أن تعتمد مثل هذه الوحدات على وحدات أخرى باستخدام روابط متعلقة بها على أساس أسماء وحدات في تصريحات import.

كذلك يمكن لبعض السمات أن تحتوي على برنامج جافاسكربت، فالوسم <button> الذي في المثال التالي والذي سيُظهر زرًا به سمة onclick، كما ستعمل قيمة السمة في كل مرة نضغط على الزر فيها.

<button onclick="alert('Boom!');">لا تضغط هنا</button>

لاحظ أننا اضطررنا لاستخدام علامات تنصيص مفردة للسلسلة النصية التي في سمة onclick لأن العلامات المزدوجة كانت مستخدِمة سلفًا للسمة ككل، لكن كان بإمكاني أن أستخدم ;quot‏&‎ كذلك.

داخل صندوق الاختبارات sandbox

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

ويسمى هذا العزل لتلك البرامج بصندوق الرمل أو صندوق الاختبار Sandbox، وإن كانت الترجمة الحرفية له هي صندوق الرمل إلا أنّ وظيفته هي عزل البرمجيات التي لا نثق فيها إلى حين البَت في أمرها أو تنتفي الحاجة إليها، وتعمل هذه البرامج كما تشاء داخل هذا الصندوق دون أذى للحاسوب نفسه أو لبياناتك، فلو كان هذا الصندوق قفصًا حديديًا سميك الجدران، فستكون البرامج حينها هي الكائنات التي تعبث فيه كما تشاء دون أن تؤذي من هو خارج القفص، ودون أن تستطيع هي نفسها الخروج.

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

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

التوافقية وحروب المتصفحات

كان المتصفح المسيطر على الساحة في بدايات الويب يسمى موزايك Mosaic، ثم انتقل السوق إلى متصفح نِت سكيب Netscape الذي ما لبث أن أفرغ الساحة قهرًا لمتصفح إنترنت إكسبلورر Internet Explorer الشهير الخاص بمايكروسوفت.

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

ظهر بعد ذلك متصفح موزيلا فاير فوكس Mozilla Firefox، وهو فرع لا يهدف للربح من نِت سكيب ليبارز إنترنت إكسبلورر في السوق في أواخر عام 2002، وقد سيطر على حصة كبيرة من السوق لعدم اهتمام مايكروسوفت بمتابعة التطوير وزهدها في مجال المتصفحات حينها، ثم خرجت جوجل بمتصفح خاص بها هو جوجل كروم Chrome، وكذلك شركة آبل بمتصفح سفاري Safari الذي اكتسب شهرةً بسبب أنه يأتي مع أجهزتها تلقائيًا، وبالتالي صار لدينا أربعة متصفحات رئيسية على الساحة بدلًا من واحد فقط.

اتجهت هذه الهيئات الأربعة نحو وضع معايير موحَّدة وأساليب هندسية أفضل لتصميم هذه المتصفحات، لتعطينا متصفحات لا تعاني كثيرًا من الزلات البرمجية ولا مشاكل التوافقية، وقد رأت مايكروسوفت مؤخرًا أنّ حصتها في هذا السوق قد تهاوت كثيرًا، فتبنّت هذا الرأي في النهاية في متصفح إيدج Edge الخاص بها واستبدلت به متصفحها القديم.

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

ترجمة -بتصرف- للفصل الثالث عشر من كتاب Elequent Javascript لصاحبه Marijn Haverbeke.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...