اخر عشرة مواضيع بالمنتدى
80برنامج لجميع انواع الموبيلbeshoy بواسطة: beshoy sa3ed | نكت قبيحه جدا جدا ممنوع دخول البنات بواسطة: m7mod | الدكـاتـره والشنـط الـجـلـد بواسطة: m7mod | جميع أهداف الألمانى توماس موللر الذى حصل على لقب الهداف فى كأس العالم 2010 بواسطة: m7mod | تعلم كيف تتغلب علي قلة الثقة بالنفس بواسطة: mba degree | تعلم مهارات الاتصال الفعال بواسطة: mba degree | مهارات الاتصال الفعال بواسطة: mba degree | كيف تكون شخص منظم و تترك انطباع جيد عند الاخرين بواسطة: mba degree | كيف تنمي مهارة الابداع في شخصيتك بواسطة: mba degree | مهارات ااقناع بواسطة: mba degree
موضوع مغلق 
 
تقييم الموضوع:
  • 0 اصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
الدرس 13 ADO.Net
11-06-2009, 03:17 AM (اخر تعديل لهذه المشاركة : 02-01-2010 12:34 PM بواسطة مصطفى الشريف.)
مشاركات: #1
Rainbow الدرس 13 ADO.Net
السلام عليكم ورحمه الله وبركاته
بسم الله الرحمن الرحيم و الصلاه والسلام على اتم المرسلين والله اكبر ولله الحمد اللهم يسر ولا تعسر



بعد ما تعلمنا كيفيه الاتصال بقاعده البيانات MSQL و Access
سنتعرف الان على كيفيه التعامل مع قاعده البيانات مثلاً تنفيذ استعلام SQL

الفصيله التي تقوم بتنفيذ امر ضد قاعده البيانات هي


SqlCommand لقواعد بيانات SQL
OleDbCommand لقواعد بيانات Access


حيث يتطلب تنفيذ امر ضد قاعده بيانات توفير
اتصال مفتوح Connection ,,,,,ونص الامر (استعلام SQL) منCommandText
لأستخدام هذه الفصيله قم بتعريف متغير من نوع الفصيله داخل الفصيله لكن خارج اي اجراء

PHP كود:
Dim OLEDB_CMD As New OleDbCommand
او 
    Dim SQL_CMD 
As New SqlCommand 
ثم بعد فتح الاتصال
قم بتمرير الاتصال و نص الاستعلام للفصيله كالتالي

PHP كود:
OLEDB_CMD.Connection Connection1
OLEDB_CMD
.CommandText "SQL command" 

لتطبيق الكود
افتح مشروع جديد او افتح المشروع الذي كنت اعددته بالدرس السابق



PHP كود:
Imports System.Data.OleDb
Public Class Form1
    Dim OLEDB_Connection1 
As New OleDbConnection
    Dim OLEDB_CMD 
As New OleDbCommand
    Dim row 
As Integer

    
Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgsHandles MyBase.Load
        
'اتصال بقاعده بيانات اكسس
        Try
            OLEDB_Connection1.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = " & Application.StartupPath & "\Employees.mdb"
            OLEDB_Connection1.Open()

        Catch ex As Exception
            MsgBox("حدث خطأ اثناء فتح قاعده البيانات" & vbCrLf & ex.Message)
            Exit Sub
        End Try

        '
تنفيذ الامر
        OLEDB_CMD
.Connection OLEDB_Connection1
        OLEDB_CMD
.CommandText "INSERT INTO EmployeeData  " _
        
" (EmployeeName,  EmployeeAge,  EmployeeSalary ,EmployeeNationality)" _
        
" VALUES( 'Mohamed',  22, 22000, 'مصري' ) "
        
row OLEDB_CMD.ExecuteNonQuery()
        If 
row 0 Then
            MsgBox
("تم تنفيذ الامر")
        Else
            
MsgBox("لم يتم تنفيذ الامر")
        
End If
        
غلق الاتصال
        OLEDB_Connection1
.Close()
    
End Sub
End 
Class 

لو نظرنا في كود تنفيذ الامر بعد تحديد الاتصال المطلوب للكائن OLEDB_CMD نقوم بتعين جمله استعلام يقوم باضافه سجل جديد لقاعده بيانات موجوده مع البرنامج ثم نقوم
باستدعاء الاسلوب OLEDB_CMD.ExecuteNonQuery() الذي يقوم بتنفيذ الاستعلام



الان لو فتحت قاعده البيانات ستجد سجل جديد مضاف لقاعده البيانات...


2-طرق تنفيذ الامر
هناك 4 طرق لتنفيذ الاستعلام على قاعده البيانات كالتالي
1-ExecuteNonQuery :تقوم بتنفيذ استعلام دون توقع عوده نص من نتيجه الاستعلام لكن نتوقع عوده عدد السجلات التي تأثرت(تستعمل عند استعلامات الاضافه و الحذف والتعديل).
2-ExecuteReader تقوم بتنفيذ استعلام مع توقع عوده نص من نتيجه الاستعلام (تستعمل عند استعلامات الاختيار) .
3- ExecuteScalar تقوم بتنفيذ استعلام مع توقع عوده سجل واحد من نتيجه الاستعلام (تستعمل عند استعلامات الاختيار).

سنقوم الان بتعديل المثال السابق بحيث يتم تنفيذ استعلام مختلف بعض الشئ

كود:
SELECT  COUNT(*)  FROM  EmployeeData  WHERE  EmployeeName = 'Mohamed'

SELECT Count استعلام يرجع عدد السجلات التي تنطبق عليها الشرط WHERE EmployeeName = 'Mohamed

لو عدلنا الاستعلام ليصبح كالتالي


PHP كود:
"SELECT  COUNT(*) FROM EmployeeData  " _
        
"WHERE EmployeeName ='" Name1 "'" 

فان نتيجه الاستعلام ستكون كافه الحقول من الجدول EmployeeData عندما الحقل EmployeeName
يساوي المتغير Name1.

الان سنحاول تنفيذ الاستعلام من البرنامج بحيث يدخل المستخدم الاسم في حقل نص فيتم التحقق من اسم الموظف ان كان موجود بالجدول EmployeeData.

اضف لمشروع جديد زر امر و مربع ادخال نص..واستبدل الكود الموجود بالتالي


PHP كود:
Imports System.Data.OleDb
Public Class Form1
    Dim OLEDB_Connection1 
As New OleDbConnection
    Dim OLEDB_CMD 
As New OleDbCommand
    Dim row 
As Integer
    
Private Sub Button1_Click(ByVal sender As System.ObjectByVal e As System.EventArgsHandles Button1.Click
        
'اتصال بقاعده بيانات اكسس
        Try
            OLEDB_Connection1.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = " & Application.StartupPath & "\Employees.mdb"
            OLEDB_Connection1.Open()

        Catch ex As Exception
            MsgBox("حدث خطأ اثناء فتح قاعده البيانات" & vbCrLf & ex.Message)
            Exit Sub
        End Try
        '
تنفيذ الامر
        OLEDB_CMD
.Connection OLEDB_Connection1
        OLEDB_CMD
.CommandText "SELECT  COUNT(*) FROM EmployeeData  " _
        
"WHERE EmployeeName ='" TextBox1.Text "'"
        
row OLEDB_CMD.ExecuteScalar
        
If row 0 Then
            MsgBox
("تم التحقق من الموظف")
        Else
            
MsgBox("لم يتم العصور على الموظف")
        
End If
        
غلق الاتصال
        OLEDB_Connection1
.Close()
    
End Sub
End 
Class 

حيث استخدمنا الاسلوب ExecuteScalar لمعرفه نتيجه الاستعلام..

Security Issue: SQL Injection Attacks حقن الاستعلامات


ظهرت منذ فتره ثغره امنيه في معظم التطبيقات التي تقوم بأستعمال قواعد بيانات تدعم استعلامات SQL
مثل قواعد اكسس و sql server
تقوم تلك الثغره باستغلال ما يعرف بال Patched query's ويقصد بها الاستعلامات المركبه بحيث يتم تنفيذ اكثر من استعلام مع وضع فاصل بين كل استعلام العلامه التاليه ;
كذلك التعليقات على الستعلامات حيث يتم تجاهل اي نص بعد العلامه --
يعني مثلاً لو انت تريد تصميم برنامج يتحقق من صلاحيه مستخدم ما للوصول لبرنامج معين

انت ستستعمل الكود التالي

PHP كود:
OLEDB_CMD.CommandText "SELECT  COUNT(*) FROM EmployeeData  " _
        
"WHERE EmployeeName ='" TextBox1.Text "'" &" And EmployeePassword  =  '" Textbox2.Text "'")
        
row OLEDB_CMD.ExecuteScalar

        
If row 0 Then
            MsgBox
("تم التحقق من الموظف")
        Else
            
MsgBox("لم يتم العصور على الموظف")
        
End If 

لكن المتسلل او الHacker بعد ما يعرف اصدار البرنامج اللي سيادتك مركبه على الخادم ويتحقق من انه فعلاً يحتوي على الثغره المذكوره.
لن يكتب اي كلمه سر على الاطلاق سيكتب النص التالي في صندوق ادخال اسم المستخدم

كود:
xxx’  ;  DROP  TABLE  [EmployeeData]  --

دعنا نتفحص هذا الكود لو اختبرت القيمه OLEDB_CMD.CommandText
بعد ادخال النص و الضغط على زر التنفيذ ستجد انه يساوي التالي تماماً
كود:
SELECT  COUNT(*)  FROM  EmployeeData
WHERE  EmployeeName  =  ’xxx’  ;
DROP  TABLE  [EmployeeData]  --’  AND  EmployeePassowrd  =  ”

ذلك الاستعلام يحتوي على جملتين SQL وتعليق حيث
1- جمله SELECT

كود:
SELECT  COUNT(*)  FROM  Customers
WHERE  EmployeeName  =  ’xxx


حيث سيتم ارجاع عدد السجلات التي توافق EmployeeName = ’xxx’

2- جمله DROP TABLE []

كود:
[b]DROP  TABLE  [EmployeeData][/b]

حيث سيتم مسح الجدول EmployeeData تماماً

لاحظ تم الربط بين الاستعلامين ب العلامه ;

3-
كود:
--’  AND  EmployeePassowrd  =  ”

طبعاً هذا باقي الاستعلام الاصلي الذي تم سبقه بالعلامه -- ليتم تعريفه كتعليق ولن يلفت له على الاطلاق..

لو عايز تهزر مع حد بس مش عاوز تضيع قاعده البيانات اللي هو عامله استعمل الكود التالي

كود:
xxx’  ;  SHUTDOWN  WITH  NOWAIT  --

ليتم ايقاف الخادم على الفور
AngryAngryAngry

الحل لمثل تلك الثغرات يكون من خلال احد الطرق الاَتيه

اولاً البحث عن اي علامات غريبه في المدخلات من خلال دوال البحث (راجع درس الدوال) مثل العلامه ' او ال Double Dash --
واذا صادف وجود اي منها قم بحذفها او امتنع عن تنفيذ باقي الاستعلام.

الطريقه الثانيه التعامل مع الاستعلامات من خلال الاوامر ذات العوامل :-



2-الاوامر ذات العوامل Command Parameters:-


في الكود السابق بتاع التحقق من المستخدم انت استخدمت البيانات اللي موجوده في التكستات مباشره لتكمله جمله الاستعلام وهذا كما قلنا يعرضك لكثير من المشاكل الامنيه وغيرها...
ما سنضيفه الان هو القدره على ربط قيم معينه متغيره بجمله الاستعلام الموجهه لقاعده البيانات
يعني الاستعلام بتعنا بيحاول يعثر على قيمه تساوي اسم الموظف EmployeeName و كلمه السر EmployeePasword
فبدلاً من دمج اسم الموظف و كلمه السر في جمله الاستعلام نقوم بتعريف قيمه متغيره في جمله الاستعلام .

يعني جمله الاستعلام بدل ما تكون هكذا


كود:
"SELECT  COUNT(*) FROM EmployeeData  " & _
        "WHERE EmployeeName ='" & TextBox1.Text & "'" &" And EmployeePassword  =  '" & Textbox2.Text & "'"

تكون هكذا
كود:
"SELECT  COUNT(*) FROM EmployeeData " & _
        "WHERE EmployeeName = @EmployeeName" _
        & " And EmployeePassword  = @EmployeePassword"

لاحظ اننا سبقنا اسم القيمه المتغيره او ال parameter بالعلامه @ متبوعه بأسم ال parameter.
لاحظ انك لو بتستعمل Access لابد انك تستخدم العلامه ? بدلاً من @

الان انتهى التعامل مع نص الاستعلام نفسه و بدأ التعامل مع ال
SqlCommand

التي بدورها ستقوم باستبدال القيم المتغيره او ال parameter بالنص الموافق له:_
ابدأ مشروع جديد و ادخل الكود التالي في حدث الضغط على زر ما واضف 2 Textbox
PHP كود:
Dim connection1 As SqlConnection = New SqlConnection("Data Source=.\sqlexpress;Initial Catalog=Employees;Integrated Security=True")
        
Dim Result As Integer

        Dim commandStr 
As String _
        
"SELECT  COUNT(*) FROM Level1_Employees " _
        
"WHERE EmployeeName = @EmployeeName" _
        
" And EmployeePassword  = @EmployeePassword"

        
Dim sqlCommand1 As New SqlCommand(commandStrconnection1)
        
sqlCommand1.Parameters.Add("@EmployeeName"SqlDbType.NVarChar)
        
sqlCommand1.Parameters.Add("@EmployeePassword"SqlDbType.NVarChar)


        Try
            
connection1.Open()

            
sqlCommand1.Parameters("@EmployeeName").Value TextBox1.Text
            sqlCommand1
.Parameters("@EmployeePassword").Value TextBox2.Text

            Result 
CInt(sqlCommand1.ExecuteScalar)

            If 
Result 0 Then
                MsgBox
("Welcome : " TextBox1.Text)
            Else
                
MsgBox("User or password not Found"MsgBoxStyle.Critical)
            
End If

        Catch 
ex As Exception
            MsgBox
("Failed" vbCrLf ex.Message)
        
End Try 


في الكود التالي
كود:
sqlCommand1.Parameters.Add("@EmployeeName", SqlDbType.NVarChar)

لاحظ اننا استخدمنا الاسلوب Add الخاص بالمجموعه sqlCommand1.Parameters
التي يمكن التفكير بها كمصفوفه تحوي كل المعاملات او ال Parameters الخاصه بجمله الامر sqlCommand1.
حيث اننا حددنا اولاً اسم المعامل ثم نوعه.. ويمكن تحديد طوله ايضاَ.

ثم في الكود التالي نبدأ بتحديد قيمه المعامل انها تساوي قيمه الموجوده بصندزق النص:


كود:
sqlCommand1.Parameters("@EmployeeName").Value = TextBox1.Text

لو حاولت انك تحقن اي استعلام داخل الجمله الرأيسيه ستفشل.

مميزات القيم المتغيره او ال Parameters بالاستعلامات :-

1-التأكد من ان انواع البيانات تم تحديدها وفقاً لأنواع ال ADO
2-تمكنك من استخدام الاسلوب Prepare الذي سيسرع منعمليه تنفيذ الاستعلامات.
3-تمكنك من التعامل مع الاجرائات المخزنه او ال Stored procedures.




اعداد الاستعلامات The Prepare Method

عندما تتوقع تنفيذ جمله استعلام اكثر من مره فيجب عليك اعدادها بالاسلوب Prepare هكذا ستزيد من سرعه برنامجك بنسبه 50% حيث انك لن ترسل جمله الاستعلام كل مره لكنك فقط ستغير المعاملات او ال Parameters .لكن لاحظ انك لو غيرت نص الستعلام سيكون عليك اعاده الاعداد مره اخرى

الصيغه العامه لجمله الاعداد سهله جداً

كود:
command.Prepare()
حيث command هو كائن Sql Command
ويمكن تنفيذها في اي وقت بعد اضافه المعاملات او ال Parameters للكائن Sql Command

فقط ستقوم بتمرير جمله الاستعلام في اول مره بعد تغيير جمله الاستعلام..لكن لاحظ انك لو غيرت نص الستعلام سيكون عليك اعاده الاعداد مره اخرى

يعد الكود التالي كود مناسب لاضافه سجل جديد بالجدول


PHP كود:
Dim connection1 As SqlConnection = New SqlConnection("Data Source=.\sqlexpress;Initial Catalog=Employees;Integrated Security=True")
        
Dim Result As Integer

        Dim commandStr 
As String _
        
"insert into Level1_Employees " _
        
"( " _
        
"   EmployeeName, " _
        
"   EmployeePassword " _
        
") " _
        
"values(@EmployeeName, @EmployeePassword)"

        
Dim sqlCommand1 As New SqlCommand(commandStrconnection1)
        
sqlCommand1.Parameters.Add("@EmployeeName"SqlDbType.NVarChar)
        
sqlCommand1.Parameters.Add("@EmployeePassword"SqlDbType.NVarChar)


        Try
            
connection1.Open()

            
sqlCommand1.Parameters("@EmployeeName").Value TextBox1.Text
            sqlCommand1
.Parameters("@EmployeePassword").Value TextBox2.Text

            sqlCommand1
.ExecuteNonQuery()


        Catch 
ex As Exception
            MsgBox
("Failed" vbCrLf ex.Message)
        
End Try 

لكن تخيل انك تريد اضافه 100 سجل جديد بنفس الطريقه
ان اعاده ارسال جمل الاستعلام اكثر من مره للخادم هو الحل ليس بالفعال..
لكن يفضل استخدام جمل الاعداد كالتالي



PHP كود:
Try

            
connection1.Open()
            
sqlCommand1.Parameters("@EmployeeName").Value TextBox1.Text
            sqlCommand1
.Parameters("@EmployeePassword").Value TextBox2.Text
            sqlCommand1
.Prepare()
            
sqlCommand1.ExecuteNonQuery()


        Catch 
ex As Exception
            MsgBox
("Failed" vbCrLf ex.Message)
        
End Try 


الأجرائات المخزنه Stored Procedure T-SQL


تكلمنا من قبل خلال مقدمه قواعد بيانات SQL Server عن الاجرائات المخزنه وبينا اهميتها و تعاملنا مع احد الامثله لأجراء بسيط وكان التنفيذ على قاعده بيانات .

اليوم سنتعامل مع الاجرائات المخزنه من خلال الكود...
اخر مواضيعى


01100001-00101101-01101100-00101101-01101100-00101101-01100001-00101101-01101000
عرض جميع مشاركات هذا العضو
11-13-2009, 06:45 PM
مشاركات: #2
RE: الدرس 13 ADO.Net
السلام عليكم

سنتعلم اليوم كيفيه تنفيذ الاستعلامات التي تعود بقيمه طويله(جداول كامله) من خلال الاسلوب

ExecuteReader الخاص بالكائن OleDbCommand

لعرض ناتج الاستعلام والتعامل معه يجب عليك تعريف متغير من نوع الفصيله DataReader وهو يعتبر مخزن بيانات المسترجعه من الاستعلام

حيث تستطيع تلك الفصيله احتواء جداول تحتوي على صور او بيانات معقده

الكود التالي يقوم بتنفيذ استعلام يعود بجدول كامل من قاعده البيانات:


PHP كود:
    ' ----- Connect to the database.
    Dim connectionString As String = _
       "Data Source=MySystem\SQLEXPRESS;" & _
       "Initial Catalog=MyDatabase;Integrated Security=true"
    Dim theDatabase As New SqlClient.SqlConnection(connectionString)
    theDatabase.Open()

    ' 
----- Prepare the SQL statement for the reader.
    
Dim sqlStatement As New SqlClient.SqlCommand_
       
"SELECT * FROM Table1 WHERE Column2 = 25"_
       theDatabase
)
    
Dim dataResults As SqlClient.SqlDataReader _
       sqlStatement
.ExecuteReader()

     ----- 
Clean up.
    
sqlStatement Nothing
    theDatabase
.Close()
    
theDatabase.Dispose() 

لاحظ ان الكود مخصص لقاعده بيانات MSQL اسمها MyDatabase
و يمكن تعديل الكود ليعمل على قاعده بيانات Access

الان اذا اردت قرائه البيانات من ال dataResults بافتراض ان الاستعلام عاد بنتيجه قم بقرائه البيانات من خلال استدعاء الاسلوب Read() الخاص بالكائن dataResults كالتالي


PHP كود:
    Do While dataResults.Read()
       
MsgBox("Column1 = " CStr(dataResults("Column2")))
    
Loop
    dataResults
.Close() 

الكود السابق يقوم بعمل تكرار طالما الاسلوب dataResults.Read يرجع قيمه
حيث يتم عرض رساله تحوي محتوى السجل لاحظ ايضاً اننا استخدمنا الاسلوب CStr() لتحويل محتوى السجل من object وهو النوع الافتراضي الذي تعود به الاسلوب dataResults.Read لنحول القيمه الى نص..

لمزيد من المعلومات عن تحويل انواع البيانات ارجع للدرس الخاص بذلك

لاحظ انه يمكن الوصول لمحتوى السجل من خلال الطرق التاليه

كود:
    dataResults("Column2")
    dataResults(1)

من خلال اسم العمود او من خلال ترتيب العمود الاندكس
ممكن التأكد من ان الاستعلام يحتوي على نتائج من خلال الكود التالي


PHP كود:
If (dataResults.HasRows FalseThen MsgBox("No data."


الجدير بالذكر ان الفصيله DataReader لا يمكن ربطها بأدوات التحكم المختلفه صندوق نص و صندوق الصور بشكل مباشر..ذلك لان الفصيله DataReader تعمل بطريقه "forward-only" ذلك يعني ان السجل الذي تم عرضه مره من خلال الاسلوب read يتم حذفه ولا يمكن الرجوع اليه الا من خلال اعاده تنفيذ الاستعلام.

لحل هذه المشكله ممكن استخدام فصيله اخرى و هي DataSet

عرض جميع مشاركات هذا العضو
موضوع مغلق 


المواضيع المحتمل ان تكون متشابهة.
الموضوع: الكاتب الردود: المشاهدات: اخر رد
Rainbow الدرس 22 Win32 API DataType مصطفى الشريف 5 553 06-30-2010 06:18 PM
اخر رد: مصطفى الشريف
Rainbow الدرس 21 Win32 API نظره للغه البرمجه C مصطفى الشريف 0 95 06-29-2010 05:32 PM
اخر رد: مصطفى الشريف
Rainbow الدرس 20 مقدمه Win32 API and .Net مصطفى الشريف 2 657 04-21-2010 03:38 AM
اخر رد: مصطفى الشريف
Rainbow الدرس 18 توزيع البرامج مصطفى الشريف 0 566 03-06-2010 12:41 AM
اخر رد: مصطفى الشريف
Rainbow الدرس 17 Crystal Report مصطفى الشريف 2 1,164 03-03-2010 05:29 PM
اخر رد: مصطفى الشريف
Rainbow الدرس 16 Crystal Report مصطفى الشريف 2 944 02-27-2010 03:42 PM
اخر رد: مصطفى الشريف
  الدرس 15 التعامل مع البيانات بشكل مرئي مصطفى الشريف 1 1,203 02-05-2010 04:27 AM
اخر رد: مصطفى الشريف
  الدرس 14 ADO.Net مصطفى الشريف 1 1,182 11-27-2009 09:00 PM
اخر رد: مصطفى الشريف
Rainbow الدرس 12 ADO.Net مصطفى الشريف 1 1,411 10-25-2009 12:50 AM
اخر رد: مصطفى الشريف
Rainbow الدرس العاشر التعامل مع النماذج مصطفى الشريف 0 1,135 10-03-2009 10:36 PM
اخر رد: مصطفى الشريف
Rainbow الدرس التاسع الفصائل مصطفى الشريف 2 842 09-28-2009 04:48 PM
اخر رد: مصطفى الشريف
Rainbow الدرس الثامن الدوال و الاجرائات2 مصطفى الشريف 2 1,425 09-07-2009 10:52 PM
اخر رد: مصطفى الشريف
Rainbow الدرس السابع تحويل انواع البيانات مصطفى الشريف 0 694 08-07-2009 03:37 AM
اخر رد: مصطفى الشريف
Rainbow الدرس السادس توجيه الكود مصطفى الشريف 0 640 08-03-2009 04:20 PM
اخر رد: مصطفى الشريف
Rainbow الدرس الخامس المتغيرات والثوابت وانواع البيانات2 مصطفى الشريف 0 1,035 07-18-2009 01:08 AM
اخر رد: مصطفى الشريف

التنقل السريع:

إتصل بناشباب دمنهورالعودة للأعلىالعودة للمحتوىالأرشيفخلاصات RSS
Bookmark and Share Free counter and web stats Powered by  MyPagerank.Net