۱۳۸۸/۰۵/۰۹

نمايش پيغامي به كاربر در هنگام استفاده از MS Ajax


مطلب "نمايش يك پيغام به كاربر در ASP.Net" را احتمالا به خاطر داريد. اين روش در حالت postback كامل و يا در حالت page_load بدون مشكل كار مي‌كند. اما اگر در حال استفاده از آپديت پنل MS Ajax باشيم، ديگر كار نخواهد كرد چون تنها قسمتي از صفحه به روز رساني مي‌شود و يك postback كامل رخ نمي‌دهد تا از شيء صفحه جهت تزريق اسكريپت خود بتوانيم استفاده نمائيم. خوشبختانه طراحان MS Ajax به اين مورد هم توجه داشته‌اند و متد RegisterStartupScript را جزئي از كلاس ScriptManager قرار داده‌اند. براي مثال اگر نياز باشد در پايان عمليات يك متد كه از آپديت پنل كمك مي‌گيرد، يك alert نمايش داده شود مي‌توان از متد زير استفاده كرد:

void jsCall(string alert)
{
string script = @"alert('" + alert + "');";
ScriptManager.RegisterStartupScript(this, this.GetType(), "jsCall", script, true);
}

با توجه به اين نكته، مطلب "نمايش يك پيغام به كاربر در ASP.Net" را به صورت زير نيز مي‌توان با MS Ajax‌ سازگار كرد:

if (page != null)
{
ScriptManager sMgr = ScriptManager.GetCurrent(page);
if (sMgr != null)
{
ScriptManager.RegisterStartupScript(page, page.GetType(),
"script" + new Guid().ToString("N"),
scriptBlock, false);
}
else
//همان روش قبلي
...


۱۳۸۸/۰۵/۰۸

خواندني‌هاي 8 مرداد


اس كيوال سرور

امنيت

توسعه وب

دات نت فريم ورك

دبليو پي اف و سيلور لايت

دلفي

سي و مشتقات

لينوكس

متفرقه

محيط‌هاي مجتمع توسعه

ويندوز

۱۳۸۸/۰۵/۰۷

مقايسه حساس به حروف كوچك و بزرگ در SQL Server


چندين روش براي انجام مقايسه حساس به حروف كوچك و بزرگ (case sensitive) در SQL Server وجود دارد كه در ادامه آن‌ها را مرور خواهيم كرد:

ابتدا جدول موقتي زير را جهت آزمايشات بعدي در نظر بگيريد

CREATE TABLE #tblTest
(
f1 NVARCHAR(50)
)

INSERT INTO #tblTest (f1) VALUES('Test1')
INSERT INTO #tblTest (f1) VALUES('TEST1')

الف) استفاده از collation صحيح
عموما هنگام نصب اس كيوال سرور از collation غيرحساس به كوچكي و بزرگي حروف استفاده مي‌شود و اين مورد سبب مي‌شود كه پيش فرض ايجاد ديتابيس‌ها نيز به همين صورت باشد (هر چند كاملا قابل كنترل و تنظيم است). به صورت پويا مي‌توان اين collation را در كوئري‌ها نيز اعمال نمود. براي مثال:

SELECT f1 FROM #tblTest WHERE f1 COLLATE SQL_Latin1_General_CP1_CS_AS = 'Test1'
در اين مثال اگر از collation حساس به كوچكي و بزرگي حروف استفاده نمي‌شد، خروجي هر دو ركورد ثبت شده مي‌بود.

ب) استفاده از تابع BINARY_CHECKSUM اس كيوال سرور (نوعي الگوريتم ويژه، شبيه به امضاي ديجيتال و هش كردن اطلاعات است)

SELECT f1 FROM #tblTest WHERE BINARY_CHECKSUM(f1) = BINARY_CHECKSUM('Test1')
و يا استفاده از امكانات هش كردن اطلاعات در اس كيوال سرور: (امضاي ديجيتال دو رشته با هم مقايسه مي‌شوند)

SELECT f1 FROM #tblTest WHERE hashbytes('md5',f1) = hashbytes('md5',N'Test1')
ج) مقايسه در حالت بايناري

SELECT f1 FROM #tblTest WHERE convert(varbinary(50),f1) = convert(varbinary(50),N'Test1')

۱۳۸۸/۰۵/۰۶

فشرده سازي با فرمت 7z


جي‌ميل هر ايميلي را كه به همراه آن يك فايل اجرايي پيوست شده باشد برگشت مي‌زند. Zip‌ كردن آن هم فايده ندارد چون محتويات فايل‌هاي zip را هم بررسي مي‌كند! فقط به نظر فرمت rar و همچنين 7z را بررسي نمي‌كند (احتمالا با مجوز آن مشكل دارد).
قوي‌ترين برنامه سورس بازي كه اين فرمت را پشتيباني مي‌كند، برنامه 7zip است و خوشبختانه محصور كننده‌هايي نيز جهت كار با كتابخانه‌هاي اين برنامه براي دات نت فريم ورك موجود است. براي مثال:


مزيت استفاده از اين كتابخانه اين است كه اغلب فرمت‌هاي پر كاربرد را نيز پشتيباني مي‌كند (شامل zip ، gz ، rar و ...).
براي استفاده از آن به فايل‌هاي 7z.dll و SevenZipSharp.dll نياز خواهيد داشت. 7z.dll از برنامه 7zip گرفته شده و SevenZipSharp.dll هم محصور كننده دات نتي آن است.

مثالي در مورد فشرده سازي با فرمت 7z با كمك كتابخانه‌هاي نامبرده شده:

using SevenZip;
using System.Windows.Forms;
using System;

class C7Z
{
public static void Compress7Z(string filePath, string outPath)
{
SevenZipCompressor.SetLibraryPath(String.Format(@"{0}\7z.dll", Application.StartupPath));
SevenZipCompressor cmp = new SevenZipCompressor
{
ArchiveFormat = OutArchiveFormat.SevenZip,
CompressionMethod = CompressionMethod.Lzma,
CompressionMode = CompressionMode.Create,
CompressionLevel = CompressionLevel.High,
VolumeSize = 0
};
cmp.CompressFiles(outPath, filePath);
}

}

C7Z.Compress7Z(@"C:\test\test.txt", @"C:\test\test.7z");
مثال‌هاي بيشتري را با دريافت سورس SevenZipSharp مي‌توانيد مشاهده كنيد.

۱۳۸۸/۰۵/۰۵

تنظيمات امنيتي SMTP Server متعلق به IIS 6.0 جهت قرارگيري بر روي اينترنت


فرض كنيد يك سرور را بر روي اينترنت قرار داده‌ايد و از SMTP Server متعلق به IIS قصد داريد جهت ارسال ايميل توسط برنامه‌هاي خود استفاده نمائيد. در اين حالت مواردي را بايد رعايت نمود تا اين سرور تبديل به سرور رايگان ارسال spam توسط "دشمنان" نشود.



1- پورت پيش فرض را عوض كنيد
پورت پيش فرض اتصال به SMTP Server مساوي 25 است. از آنجائيكه به سادگي در برنامه‌هاي خود مي‌توان اين پورت را نيز تنظيم نمود، بهتر است به عنوان اولين قدم، اين پورت را تغيير داد. يك شماره پورت دلخواه خالي را يافته و بجاي 25 قرار دهيد. براي اين منظور مسير زير را طي كنيد:
بر روي Default SMTP Virtual Server در كنسول IIS كليك راست كرده و گزينه خواص را انتخاب كنيد. در برگه General روي دكمه Advanced كليك كرده و در صفحه باز شده سطر مربوط به پورت 25 را يافته، بر روي دكمه Edit كليك نموده و آن‌را به عددي ديگر تغيير دهيد.



2- دسترسي عموم را به سرور قطع كنيد!
متاسفانه تنظيمات پيش فرض SMTP Server متعلق به IIS در جهت قطع دسترسي "دشمنان" كاملا نادرست بوده و بر مبناي ايده حداقل دسترسي صورت نگرفته‌ است. اگر سرور را به اين حال رها كنيد فقط "دشمنان" را خوشحال كرده‌ايد.
براي قطع دسترسي دشمنان سه مرحله بايد صورت گيرد:
الف) در برگه Access مربوط به تنظيمات SMTP server ، روي دكمه relay كليك كرده، ابتدا تيك مربوط به Allow all computers which successfully authenticated to relay‌ را برداريد (اين مورد در يك شبكه داخلي حائز اهميت مي‌شود و ساير كامپيوترها را منع مي‌كند). سپس در قسمت بالاي صفحه گزينه only the list below را انتخاب كرده و IP آن‌را مساوي 127.0.0.1 وارد كنيد (يعني فقط اين كامپيوتر مجاز است كه از اين سرويس جهت ارسال ايميل استفاده كند؛ نه دشمنان خارجي).



ب) مورد الف را درباره‌ي قسمت مرتبط با دكمه connections نيز تكرار كنيد. (پيش فرض آن تمام عالم است!)



ج) در همين برگه‌ي Access بر روي دكمه Authentication كليك كرده و فقط تيك مربوط به integrated windows authentication را قرار دهيد. (هميشه تحت ويندوز اين روش authentication يكي از امن‌ترين‌ها است. همچنين در حالت قرارگيري سرور بر روي اينترنت سخت گيرانه‌ترين حالت ممكن را در اينجا انتخاب كرده‌ايم.)



خوب، با اين تنظيم قسمت (ج) ديگر برنامه‌ها با روش متداول قابل به ارسال ايميل نخواهند بود. يك يوزر معمولي local را به كامپيوتر افزوده (با حداقل دسترسي) و پسورد آن‌را در حالت never expires قرار دهيد. از اين يوزر ويندوزي جهت برقراري امكان اتصال به ميل سرور محلي در برنامه‌هاي خود استفاده خواهيم كرد (فرض بر اين است كه برنامه‌اي هم كه قرار است ايميل ارسال كند بر روي همان كامپيوتر سرور قرار دارد).

پس از اعمال اين تنظيمات بر روي دكمه apply كليك كنيد، تا تنظيمات اعمال شوند. يكبار نيز ميل سرور را استاپ و استارت كنيد.

3- تنظيمات ويژه برنامه‌ها براي ارسال ايميل:
در اين حالت برنامه‌هاي دات نت شما نياز به چهار تنظيم اضافه‌تر پيش از فراخواني تابع Send دارند:

MailMessage message = new MailMessage("from@site.com", strTo, subject, body)
{
IsBodyHtml = true,
BodyEncoding = Encoding.UTF8
};

SmtpClient client = new SmtpClient("127.0.0.1",portNumber);//portNumber is new
client.UseDefaultCredentials = false; //new
client.DeliveryMethod = SmtpDeliveryMethod.Network; //new
client.Credentials = new NetworkCredential("mail_user", "pass"); //new
client.Send(message);

همانطور كه ملاحظه مي‌كنيد بايد شماره پورت جديد را معرفي نمود، همچنين روش authentication و معرفي مشخصات يوزر ويندوزي كه اضافه كرديم را نيز نبايد فراموش كرد.

4- تمامي رخ‌دادهاي ميل سرور را ثبت كنيد.
براي اين منظور در برگه general ، تيك مربوط به enable logging را فعال كنيد. سپس بر روي دكمه خواص كنار آن كليك كرده و در صفحه باز شده به برگه extended properties مراجعه نموده و تمامي موارد را تيك بزنيد. به ازاي هر يك روز فعاليت سرور، يك فايل متني در مسير C:\WINDOWS\System32\LogFiles تشكيل خواهد شد.


سؤال چگونه تشخيص دهم كه ميل سرور من هك شده است يا خير؟!
اگر موارد فوق را رعايت نكنيد، در قسمت current sessions كنسول IIS مي‌توانيد "دشمنان" را مشاهده كنيد! همچنين مصرف CPU پروسه inetinfo.exe عملكرد سرور را مختل كرده، بعلاوه در مسير C:\Inetpub\mailroot\Queue احتمالا چند هزار ايميل درصف قرار گرفته شده براي ارسال را مي‌توانيد مشاهده كنيد! (همينطور در مسير C:\Inetpub\mailroot\Badmail نيز اين تعرض قابل مشاهده است)
اگر اين موارد را مشاهده كرديد، ابتدا سرور را استاپ كنيد، سپس محتويات پوشه‌هاي ياد شده را تخليه كرده و از مرحله يك فوق شروع به اعمال تنظيمات نمائيد.


۱۳۸۸/۰۵/۰۲

خواندني‌هاي 2 مرداد


اس كيوال سرور

الگوهاي طراحي برنامه نويسي شيءگرا

امنيت

توسعه وب

دات نت فريم ورك

دبليو اف

سي و مشتقات

كتاب‌هاي رايگان

لينوكس

متفرقه

محيط‌هاي مجتمع توسعه

مسايل انساني، اجتماعي و مديريتي برنامه نويسي

ويندوز

۱۳۸۸/۰۵/۰۱

عبارات باقاعده‌اي در مورد كار با تگ‌ها


حذف تمامي تگ‌هاي يك عبارت HTML
اين تابع و عبارت باقاعده به كار رفته در آن هنگام جستجو بر روي يك فايل html كه حاوي انبوهي از تگ‌ها است مي‌تواند مفيد باشد و يا جهت حذف هر نوع فرمت اعمالي به يك متن.

private static readonly Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);
/// <summary>
/// حذف تمامي تگ‌هاي موجود
/// </summary>
/// <param name="html">ورودي اچ تي ام ال</param>
/// <returns></returns>
public static string CleanTags(string html)
{
return _htmlRegex.Replace(html, string.Empty);
}

حذف يك تگ ويژه بدون حذف محتويات آن
فرض كنيد مي‌خواهيد تمام تگ‌هاي script بكار رفته در يك محتواي html را حذف كنيد.

private static readonly Regex _contentRegex = new Regex(@"<\/?script[^>]*?>", RegexOptions.Compiled | RegexOptions.IgnoreCase);

/// <summary>
/// تنها حذف يك تگ ويژه
/// </summary>
/// <param name="html">ورودي اچ تي ام ال</param>
/// <returns></returns>
public static string CleanScriptTags(string html)
{
return _contentRegex.Replace(html, string.Empty);
}

حذف يك تگ خاص به همراه محتويات آن تگ
فرض كنيد مي‌خواهيم در محتواي html دريافتي اثري از تگ‌ها و كدهاي جاوا اسكريپتي يافت نشود.

private static readonly Regex _safeStrRegex = new Regex(@"<script[^>]*?>[\s\S]*?<\/script>",
RegexOptions.Compiled | RegexOptions.IgnoreCase);

/// <summary>
/// حذف يك تگ ويژه به همراه محتويات آن
/// </summary>
/// <param name="html">ورودي اچ تي ام ال</param>
/// <returns></returns>
public static string CleanScriptsTagsAndContents(string html)
{
return _safeStrRegex.Replace(html, "");
}

و اگر فرض كنيم كه متدهاي فوق در كلاسي به نام CRegExHelper قرار گرفته‌اند، كلاس آزمون واحد آن به صورت زير مي‌تواند باشد:

using NUnit.Framework;

namespace testWinForms87
{
[TestFixture]
public class CTestRegExHelper
{
#region Methods (3)

// Public Methods (3)

[Test]
public void TestCleanScriptsTagsAndContents()
{
Assert.AreEqual(
CRegExHelper.CleanScriptsTagsAndContents("data1 <script> ... </script> data2"),
"data1 data2");
}

[Test]
public void TestCleanScriptTags()
{
Assert.AreEqual(
CRegExHelper.CleanScriptTags("<b>data1</b> <script> ... </script> data2"),
"<b>data1</b> ... data2");
}

[Test]
public void TestCleanTags()
{
Assert.AreEqual(
CRegExHelper.CleanTags("<b>data</b>"),
"data");
}

#endregion Methods
}

}




۱۳۸۸/۰۴/۳۰

افزونه CodeRush 9.2 و ايجاد مشكل براي IDE


نگارش جديد افزونه‌هاي DevExpress اين بار واقعا سنگ تمام گذاشته‌اند و با قابليت‌هاي آناليز كد افزونه‌ي ReSharper قابل مقايسه بوده و يا حتي در بعضي از موارد هم بهتر از آن‌ها هستند:



براي مثال مطابق شكل فوق تنها كافي است يك شيء از نوع disposable داشته باشيد كه در كد شما به صورت صريح dispose نشده باشد. بلافاصله آن‌را تشخيص داده و راه علاج را نيز توصيه مي‌كند.

اما پس از نصب آن، ديگر يك سري از پروژه‌هاي جديد در IDE قابل ايجاد شدن نيستند (حداقل براي من به اين صورت بود). پيغام خطايي هم كه از طرف VS.Net صادر مي‌شود به صورت زير است:

The project type is not supported by this installation?

پس از كمي جستجو مشخص شد كه روش رفع اين مشكل به صورت زير است:

devenv /setup
regsvr32.exe "%vs90comntools%\..\IDE\projectaggregator.dll"
devenv /resetskippkgs

سه سطر فوق را در خط فرمان صادر كرده و مدتي صبر كنيد تا عمليات به پايان رسد. پس از آن مشكل برطرف خواهد شد.

۱۳۸۸/۰۴/۲۹

خواندني‌هاي 29 تير


اس كيوال سرور

امنيت

توسعه وب

دات نت فريم ورك

سي و مشتقات

شيرپوينت

لينوكس

ماي اس كيوال

متفرقه

محيط‌هاي مجتمع توسعه

مرورگرها

وب سرورها

ويندوز

۱۳۸۸/۰۴/۲۸

بازسازي msdb تخريب شده


حاصل قطع برق و يا يك ري استارت دستي ناصحيح را در نظر بگيريد:



Database 'msdb' cannot be opened. It has been marked SUSPECT by recovery. See the SQL Server errorlog for more information. (Microsoft SQL Server, Error: 926)

Msdb از نوع ديتابيس‌هاي سيستمي است و نمي‌شود مطابق روال متداول ديتابيس‌هاي SUSPECT شده آن‌را بازيابي كرد. اين روش متداول به صورت زير است:

ALTER DATABASE DBName SET EMERGENCY
DBCC checkdb('DBname')
ALTER DATABASE DBName SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DBCC CheckDB ('DBName', REPAIR_ALLOW_DATA_LOSS)
ALTER DATABASE DBName SET MULTI_USER

در ابتداي كار ديتابيس در حالت اورژانسي قرار مي‌گيرد. بعد وضعيت و ميزان تخريب نمايش داده شده، سپس تك كاربره مي‌شود. در ادامه به اس كيوال سرور اجازه داده مي‌شود كه ديتابيس را با هر وضعي (حتي به قيمت از دست رفتن تعدادي ركورد) ترميم كند و در آخر ديتابيس مجددا به حالت چند كاربره بازگشت داده مي‌شود.
اين روشي است كه سال قبل با قطعي‌هاي مكرر برق زياد كاربرد داشت.

اما ديتابيس سيستمي msdb را نمي‌شود در حالت اورژانسي قرار داد؛ بنابراين بايد به دنبال راه چاره‌ي ديگري بود. پس از مدتي جستجو در وبلاگ‌هاي msdn ، راه حل زير يافت شد و كاملا عملي است (تست شده!) :

روش زير در مورد اس كيوال سرور 2008 ، 2005 و حتي 2000 نيز قابل استفاده است.
ابتدا خونسردي خودتان را حفظ كنيد! الان فقط ديگر با management studio نمي‌توانيد ديتابيس‌ها را مرور كنيد و همچنين تمام job هاي تعريف شده شما نابود شده‌اند! اما سرور به كار عادي خودش مي‌تواند ادامه دهد. سپس :
الف) تمام سرويس‌هاي مربوط به اس كيوال سرور را stop كنيد. به كنسول سرويس‌ها مراجعه كرده و هر آنچه كه در نام آن sql را مشاهده مي‌كنيد، stop كنيد.
ب) با استفاده از خط فرمان، ابتدا به مسير زير وارد شويد:
cd "C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Binn\"

و سپس دستور زير را اجرا نمائيد:
start sqlservr.exe -c -m -T3608

به اين ترتيب اس كيوال سرور در يك حالت حداقل كه بتوان ديتابيس msdb تخريب شده را detach كرد راه اندازي مي‌شود. (پرچم 3608 مجوز detach كردن اين ديتابيس را مي‌دهد)
ج) management studio را اجرا كنيد. زمانيكه پنجره كانكت ظاهر مي‌شود آن‌را كنسل كرده و در نوار ابزار بالاي صفحه روي دكمه new query كيك كنيد (چون حالت راه اندازي سرور در حالت تك كاربره است نمي‌خواهيم اتصال ديگري برقرار شود و در كار اخلال كند). با كليك بر روي new query پنجره connect to server ظاهر مي‌شود. در همين پنجره بر روي دكمه options كليك كرده در برگه connection properties در قسمت connect to database نام master را وارد نمود و اكنون بر روي دكمه connect كليك نمائيد.
ج) سپس دستور زير را وارد كنيد تا ديتابيس msdb را بتوان detach كرد.
Use master;
sp_detach_db 'msdb'

مراحلي كه عنوان شد مهم است. اگر به اين صورت عمل نكنيد با پيغام خطاي زير مواجه خواهيد شد:
Cannot detach an opened database when the server is in minimally configured mode

اگر به اين خطا برخورديد، يكبار ديگر از صفر شروع كنيد. تمام سرويس‌هاي مرتبط با sql را استاپ كنيد (حتي در صورت نياز كارت شبكه سرور را نيز غيرفعال كنيد). و از مرحله الف مجددا شروع نمائيد تا حتما حالت تك كاربره‌ي اتصال برقرار شود. (همچنين پنجره‌ي كوئري جديدي را نيز باز نكنيد چون در اين حالت فقط و فقط يك اتصال مجاز است)

تا اينجا موفق شديم كه ديتابيس msdb را detach كنيم. اكنون به پوشه ديتابيس‌ها مراجعه كرده و mdf و ldf اين ديتابيس تخريب شده را rename كنيد (به هر اسمي كه مايل بوديد).
د) اكنون نوبت بازسازي مجدد اين ديتابيس است.
محتويات فايل instmsdb.sql را كه در مسير C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\install قرار دارد، در پنجره‌ي كوئري تك كاربره‌اي كه در مرحله قبل بازكرده‌ايم، copy/paste كرده و دكمه F5 را فشار دهيد. پس از مدتي ديتابيس msdb باز سازي شده و مشكل برطرف مي‌شود.
ه) اكنون سرور را stop و start كنيد يا كلا كامپيوتر سرور را restart‌ كنيد تا تمامي سرويس‌هاي stop شده راه اندازي مجدد شوند.


۱۳۸۸/۰۴/۲۷

دريافت اطلاعات از سايت‌هاي غير استاندارد


اساسا از آنجائيكه ما در يك دنياي كامل زندگي نمي‌كنم و بقولي همه چيزمان بايد با همه چيزمان جور دربيايد، ممكن است هنگام استفاده از يك httpWebRequest به خطاي زير برخورد كرده و عمليات دريافت اطلاعات متوقف شود:

The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF

و يا حالتي ديگر:

The underlying connection was closed: The server committed an HTTP protocol violation.

بعضي از وب سروها ممكن است پاسخ ارسالي خود را دقيقا مطابق سطر به سطر RFC هاي مربوطه ارائه ندهند و كلاس httpWebRequest دات نت هم تعارفي با آن‌ها نداشته و به دلايل امنيتي پردازش پاسخ دريافتي را نيمه كاره رها مي‌كند.
براي مثال content-length دقيقا بايد به همين شكل ارسال شود و اگر به صورت content length (با يك فاصله در ميان كلمات ارسال گردد) به عنوان يك HTTP response split attack در نظر گرفته شده و خطاهاي HTTP protocol violation حاصل مي‌شوند.

اما مي‌توان آگاهانه دات نت فريم ورك را وادار كرد كه از اين مساله چشم پوشي كند و اين نوع سايت‌ها را نيز بررسي و دريافت نمايد. براي اين منظور در فايل app.config برنامه ويندوزي خود و يا web.config يك برنامه تحت وب، چند سطر زير را اضافه كنيد:

<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing="true" />
</settings>
</system.net>
</configuration>

۱۳۸۸/۰۴/۲۵

BloggerToCHM 1.3


نگارش جديد برنامه BloggerToCHM را از اينجا مي‌توانيد دريافت كنيد.
تغييرات حاصل شده:
  • پشتيباني بهتر از تغييرات open search API كه هر از چندگاهي توسط گوگل اعمال مي‌شود.
  • رفع مشكل تخريب اعداد فارسي در فايل توليدي نهايي
  • اضافه شدن چند گزينه جهت كنترل بر روي نمايش قسمت about در فايل نهايي حاصل و همچنين درج نظرات
  • و ...

۱۳۸۸/۰۴/۲۲

فشرده سازي خروجي يك وب سرويس


جهت بهينه سازي روش ارائه شده در مقاله "بارگذاري يك يوزركنترل با استفاده از جي‌كوئري" ، مي‌توان مبحث فشرده سازي را نيز به آن افزود.
براي اين منظور نياز است تا بتوان response حاصل را كاملا كنترل كرد و اين مورد از طريق يك http module به خوبي قابل انجام است. مبحث http compression و پياده سازي آن‌را احتمالا بارها در سايت‌هاي مختلف نيز ديده‌ايد:

using System;
using System.IO;
using System.IO.Compression;
using System.Globalization;
using System.Web;


public class JsonCompressionModule : IHttpModule
{
public JsonCompressionModule()
{
}

public void Dispose()
{
}

public void Init(HttpApplication app)
{
app.PreRequestHandlerExecute += new EventHandler(Compress);
}

private void Compress(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
HttpResponse response = app.Response;

if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))
{
if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))
{
string acceptEncoding = request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);

if (acceptEncoding.Contains("gzip"))
{
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "gzip");
}
else if (acceptEncoding.Contains("deflate"))
{
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
response.AddHeader("Content-encoding", "deflate");
}
}
}
}
}
}
در اين ماژول تنها درخواست‌هايي از نوع application/json بررسي خواهند شد. هر چند اين فشرده سازي را بر روي خروجي هر نوع WebMethod ايي نيز مي‌توان اعمال كرد. در اين حالت، سطر بررسي json را حذف كرده و آن‌را به صورت زير تغيير دهيد:

if ( !request.Url.PathAndQuery.ToLower().Contains( ".asmx" ) )
return;
مرورگر IE6 و پايين‌تر نيز از اين فشرده سازي معاف شده‌اند (چون يا پشتيباني كاملي را ارائه نمي‌دهند يا بايد منتظر كرش مرورگر بود).

جهت اعمال اين ماژول به برنامه ASP.Net خود، كافي است سطر زير را به قسمت httpModules وب كانفيگ افزود:

<httpModules>
<add name="JsonCompressionModule" type="JsonCompressionModule"/>
</httpModules>
روش آزمايش ماژول تهيه شده:

متاسفانه افزونه‌ي فايرباگ فايرفاكس اندازه‌ي نهايي response را نمايش مي‌دهد و در گزارش آن حتي خبري از Content-encoding اضافه شده نيز نخواهد بود. بنابراين براي بررسي اين روش مناسب نيست.
ابزار ديگري كه اساسا براي اين نوع آزمايشات طراحي شد‌ه است، برنامه معروف فيدلر مي‌باشد (كه توسط مدير پروژه تيم IE برنامه نويسي شده است).
براي استفاده از فيدلر جهت ديباگ درخواست‌هاي local بايد يك نكته‌ي كوچك را رعايت كرد:
http://localhost.:25413/

همانطور كه در URL فوق مشاهده مي‌كنيد يك نقطه پس از localhost اضافه شده است تا خروجي محلي مربوطه قابل بررسي شود.



مطابق تصوير فوق، هم content-encoding اضافه شده مشخص است و هم حجم پاسخ دريافتي از 40 كيلوبايت (بر اساس يك تست معمولي روي صفحه‌اي مشخص) به نزديك يك كيلوبايت و اندي كاهش يافته است.


۱۳۸۸/۰۴/۲۱

تهيه بك آپ‌هاي خودكار از SQL Server Express


SQL Server express edition نگارش مجاني و ساده شده‌ي اس كيوال سرور است. اين نگارش مجاني فاقد SQL Server agent براي زمان بندي انجام امور تكراري، براي مثال تهيه بك آپ‌هاي خودكار است. اين مورد در كل ايرادي محسوب نمي‌شود زيرا مي‌توان اين عمليات را با استفاده از سيستم استاندارد scheduled tasks ويندوز نيز پياده سازي كرد.
برنامه خط فرمان سورس بازي به نام ExpressMaint موجود است كه مي‌تواند از ديتابيس‌هاي اس كيوال سرور اكسپرس (و غير اكسپرس) بك آپ تهيه كند. فقط كافي است اين برنامه را به عنوان يك scheduled task ويندوز معرفي كنيم تا در زمان‌هاي تعيين شده در مكان‌هايي مشخص، بك آپ تهيه كند. همچنين اين برنامه فايل‌هاي بك آپ تهيه شده را نيز تعيين اعتبار مي‌كند.
با پارامترهاي خط فرمان آن در اين‌جا مي‌توانيد آشنا شويد. خلاصه كاربردي آن را به صورت چند دستور در ادامه مرور خواهيم كرد.

الف) يك فايل bat را با محتواي زير درست كنيد :

C:\backup\expressmaint.exe -S (local)\sqlexpress -D ALL_USER -T DB -R C:\backup -RU WEEKS -RV 2 -B C:\backup -BU DAYS -BV 2 -V -C
توضيحات: در اين فايل bat ، مسير فايل اجرايي برنامه حتما بايد دقيقا ذكر شود و گرنه scheduled task ويندوز درست كار نخواهد كرد. همچنين instance اس كيوال سرور اكسپرس در اينجا (local)\sqlexpress فرض شده است. اين دستور از تمامي ديتابيس‌هاي غيرسيستمي در مسير C:\backup بك آپ مي‌گيرد (به ازاي هر ديتابيس يك پوشه مجزا درست خواهد كرد و هر فايل را بر اساس تاريخ و ساعت مشخص مي‌سازد). همچنين لاگ عمليات را نيز در همان پوشه تهيه مي‌كند (نتيجه اعتبار سنجي صورت گرفته بر روي بك آپ‌هاي تهيه شده در اين فايل‌ها ثبت مي‌شود). مطابق پارامترهاي بكار گرفته شده، بك آپ‌هاي قديمي‌تر از دو روز به صورت خودكار حذف شده و لاگ فايل‌ها به مدت 2 هفته نگهداري مي‌شوند.

ب) براي اجراي زمان بندي شده‌ي اين فايل bat تهيه شده، دستورات زير را در خط فرمان اجرا كنيد (فرض بر اين است كه فايل bat تهيه شده در مسير مشخص شده C:\backup\backup.bat قرار دارد) :

AT 23:30 /EVERY:m,t,w,th,f,s,su C:\backup\backup.bat
AT 11:30 /EVERY:m,t,w,th,f,s,su C:\backup\backup.bat
به اين صورت ويندوز هر روز، دوبار در طول روز از كليه ديتابيس‌ها به صورت خودكار بك آپ تهيه مي‌كند.

روشي كه در اين‌جا ذكر شد منحصر به نگارش express نيست و با كليه نگارش‌هاي SQL Server سازگار است.


۱۳۸۸/۰۴/۲۰

رمزگشايي عنوان يك ايميل فارسي دريافت شده


گوگل اجازه‌ي فعال كردن POP3 را روي اكانت‌هاي GMail مي‌دهد. فرض كنيد با استفاده از يكي از كلاينت‌هاي POP3 دات نت مي‌خواهيم ايميل‌ها را با برنامه نويسي دريافت كنيم (و مثلا از Outlook استفاده نكنيم). اكنون به نظر شما عنوان دريافت شده زير چه معنايي دارد؟
=?UTF-8?B?QW5hbHl0aWNzIHZhaGlkbmFzaXJpLmJsb2dzcG90LmNvbSAyMDA4MTIyNiAo2KLZhdin?= =?UTF-8?B?2LEg2LPYp9mK2Kop?=

براي درك اتفاق رخ داده بايد به RFC ‌هاي مربوطه مراجعه كرد (RFC-2822 و RFC-2047). مطابق استانداردهاي ذكر شده، هدر ارسالي يك ايميل همواره بايد از حروف اسكي تشكيل شود. حال اگر عنوان ايميل كه جزئي از هدر را تشكيل مي‌دهد از حروف غير اسكي تشكيل شد، حتما بايد يك لايه encoding روي آن‌ها صورت گيرد. دو حالت تعريف شده در اين‌جا مطابق استاندارد ميسر است:
الف) Quoted Printable : در اين حالت عنوان با =?utf-8?Q شروع مي‌شود.
ب) Base64 : در اين روش عنوان با =?utf-8?B شروع خواهد شد.

روش متداول، روش ب است كه نسبت به روش الف فشرده‌تر مي‌باشد. در اين حالت براي درك معناي قسمت‌هاي مختلف رشته دريافت شده بايد به الگوي زير مراجعه كرد:
=?charset?encoding?EncodedText?=
در اين‌جا charset بيانگر نحوه encoding متن اصلي است كه بر روي آن الگوريتم base64 اعمال شده.
در رشته طولاني فوق كه در ابتداي مقاله به آن اشاره شده، عنوان به دو قسمت تجزيه شده. يا به عبارتي دوبار الگوي فوق در آن تكرار شده است كه بايد EncodedText هاي آن‌ها را يافت و سپس آن‌ها را با توجه به charset مربوطه از حالت base64 به يك رشته معمولي تبديل نمود.

//using System.Text;
public static string Base64ToString(string charset, string encodedString)
{
//تبديل بيس 64 به آرايه‌اي از بايت‌ها
byte[] buffer = Convert.FromBase64String(encodedString);
//تبديل آرايه‌اي از بايت‌ها به رشته با توجه به انكدينگ مربوطه
return Encoding.GetEncoding(charset).GetString(buffer);
}
اكنون عنوان صحيح ايميل فوق به صورت زير قابل دريافت خواهد بود:

string subject = Base64ToString("utf-8", "QW5hbHl0aWNzIHZhaGlkbmFzaXJpLmJsb2dzcG90LmNvbSAyMDA4MTIyNiAo2KLZhdin2LEg2LPYp9mK2Kop");

۱۳۸۸/۰۴/۱۹

خواندني‌هاي 19 تير



امنيت

توسعه وب

دات نت فريم ورك

دبليو سي اف

دبليو پي اف و سيلور لايت

متفرقه

محيط‌هاي مجتمع توسعه

مرورگرها

مسايل انساني، اجتماعي و مديريتي برنامه نويسي

ويندوز

پي اچ پي

ويديوي رايگان امنيت در SharePoint


دمويي نيم ساعته در مورد مباحث مختلف امنيت و سطوح دسترسي در SharePoint



پس از دريافت پسوند فايل را به mp4 تغيير دهيد.

۱۳۸۸/۰۴/۱۷

OPML هاي جديد


چهار سري فايل OPML به روز رساني شده در مورد بهترين وبلاگ‌هاي برنامه نويسي، طراحي، social media و همچنين وبلاگ‌هاي IT‌ ايراني را از آدرس زير مي‌توانيد دريافت نمائيد:


لينك OPML وبلاگ‌هاي IT ايراني را هم كه در كنار صفحه مشاهده مي‌كنيد آخر هر هفته به روز مي‌شود (به همراه خلاصه وبلاگ).


۱۳۸۸/۰۴/۱۶

خواندني‌هاي 16 تير


اس كيوال سرور

توسعه وب

دات نت فريم ورك

دبليو پي اف و سيلور لايت

سي و مشتقات

شيرپوينت

كتاب‌هاي رايگان

ماي اس كيوال

متفرقه

وب سرورها

پي اچ پي

۱۳۸۸/۰۴/۱۵

بارگذاري يك يوزركنترل با استفاده از جي‌كوئري


مزيت استفاده از يوزر كنترل‌ها، ماژولار كردن برنامه است. براي مثال اگر صفحه جاري شما قرار است از چهار قسمت اخبار، منوي پويا ، سخن روز و آمار كاربران تشكيل شود، مي‌توان هر كدام را توسط يك يوزر كنترل پياده سازي كرده و سپس صفحه اصلي را از كنار هم قرار دادن اين يوزر كنترل‌ها تهيه نمود.
با اين توضيحات اكنون مي‌خواهيم يك يوزكنترل ASP.Net را توسط jQuery Ajax بارگذاري كرده و نمايش دهيم. حداقل دو مورد كاربرد را مي‌توان براي آن متصور شد:
الف) در اولين باري كه يك صفحه در حال بارگذاري است، قسمت‌هاي مختلف آن‌را بتوان از يوزر كنترل‌هاي مختلف خواند و تا زمان بارگذاري كامل هر كدام، يك عبارت لطفا منتظر بمانيد را نمايش داد. نمونه‌ي آن‌را شايد در بعضي از CMS هاي جديد ديده باشيد. صفحه به سرعت بارگذاري مي‌شود. در حاليكه مشغول مرور صفحه جاري هستيد، قسمت‌هاي مختلف صفحه پديدار مي‌شوند.
ب) بارگذاري يك قسمت دلخواه صفحه بر اساس درخواست كاربر. مثلا كليك بر روي يك دكمه و امثال آن.

روش كلي كار:
1) تهيه يك متد وب سرويس كه يوزر كنترل را بر روي سرور اجرا كرده و حاصل را تبديل به يك رشته كند.
2) استفاده از متد Ajax جي‌كوئري براي فراخواني اين متد وب سرويس و افزودن رشته دريافت شده به صفحه.
بديهي است زمانيكه متد Ajax فراخواني مي‌شود مي‌توان عبارت يا تصوير منتظر بمانيد را نمايش داد و پس از پايان كار اين متد، عبارت (يا تصوير) را مخفي نمود.

پياده سازي:
قسمت تبديل يك يوزر كنترل به رشته را قبلا در مقاله "تهيه قالب براي ايميل‌هاي ارسالي يك برنامه ASP.Net" مشاهده كرده‌ايد. در اين‌جا براي استفاده از اين متد در يك وب سرويس نياز به كمي تغيير وجود داشت (KeyValuePair ها درست سريالايز نمي‌شوند) كه نتيجه نهايي به صورت زير است. يك فايل Ajax.asmx را به برنامه اضافه كرده و سپس در صفحه Ajax.asmx.cs كد آن به صورت زير مي‌تواند باشد:

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using System.Web.UI;
using System.Web.UI.HtmlControls;

namespace AjaxTest
{
public class KeyVal
{
public string Key { set; get; }
public object Value { set; get; }
}

/// <summary>
/// Summary description for Ajax
/// </summary>
[ScriptService]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Ajax : WebService
{
/// <summary>
/// Removes Form tags using Regular Expression
/// </summary>
private static string cleanHtml(string html)
{
return Regex.Replace(html, @"<[/]?(form)[^>]*?>", string.Empty, RegexOptions.IgnoreCase);
}

/// <summary>
/// تبديل يك يوزر كنترل به معادل اچ تي ام ال آن
/// </summary>
/// <param name="path">مسير يوزر كنترل</param>
/// <param name="properties">ليست خواص به همراه مقادير مورد نظر</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"><c>NotImplementedException</c>.</exception>
[WebMethod(EnableSession = true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string RenderUserControl(string path,
List<KeyVal> properties)
{
Page pageHolder = new Page();

UserControl viewControl =
(UserControl)pageHolder.LoadControl(path);

viewControl.EnableViewState = false;

Type viewControlType = viewControl.GetType();

if (properties != null)
foreach (var pair in properties)
{
if (pair.Key != null)
{
PropertyInfo property =
viewControlType.GetProperty(pair.Key);

if (property != null)
{
if (pair.Value != null) property.SetValue(viewControl, pair.Value, null);
}
else
{
throw new NotImplementedException(string.Format(
"UserControl: {0} does not have a public {1} property.",
path, pair.Key));
}
}
}

//Form control is mandatory on page control to process User Controls
HtmlForm form = new HtmlForm();

//Add user control to the form
form.Controls.Add(viewControl);

//Add form to the page
pageHolder.Controls.Add(form);

//Write the control Html to text writer
StringWriter textWriter = new StringWriter();

//execute page on server
HttpContext.Current.Server.Execute(pageHolder, textWriter, false);

// Clean up code and return html
return cleanHtml(textWriter.ToString());
}
}
}
تا اين‌جا متد وب سرويسي را داريم كه مي‌تواند مسير يك يوزر كنترل را به همراه خواص عمومي آن‌را دريافت كرده و سپس يوزر كنترل را رندر نموده و حاصل را به صورت HTML به شما تحويل دهد. با استفاده از reflection خواص عمومي يوزر كنترل يافت شده و مقادير لازم به آن‌ها پاس مي‌شوند.

چند نكته:
الف) وب كانفيگ برنامه ASP.Net شما اگر با VS 2008 ايجاد شده باشد مداخل لازم را براي استفاده از اين وب سرويس توسط jQuery Ajax دارد در غير اينصورت موفق به استفاده از آن نخواهيد شد.
ب) هنگام بازگرداندن اين اطلاعات با فرمت json = ResponseFormat.Json جهت استفاده در jQuery Ajax ، گاهي از اوقات بسته به حجم بازگردانده شده ممكن است خطايي حاصل شده و عمليات متوقف شد. اين طول پيش فرض را (maxJsonLength) در وب كانفيگ به صورت زير تنظيم كنيد تا مشكل حل شود:

<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="10000000"></jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>

براي پياده سازي قسمت Ajax آن براي اينكه كار كمي تميزتر و با قابليت استفاده مجدد شود يك پلاگين تهيه شده (فايلي با نام jquery.advloaduc.js) كه سورس آن به صورت زير است:

$.fn.advloaduc = function(options) {
var defaults = {
webServiceName: 'Ajax.asmx', //نام فايل وب سرويس ما
renderUCMethod: 'RenderUserControl', //متد وب سرويس
ucMethodJsonParams: '{path:\'\'}',//پارامترهايي كه قرار است پاس شوند
completeHandler: null //پس از پايان كار وب سرويس اين متد جاوا اسكريپتي فراخواني مي‌شود
};
var options = $.extend(defaults, options);

return this.each(function() {
var obj = $(this);
obj.prepend("<div align='center'> لطفا اندكي تامل بفرمائيد... <img src=\"images/loading.gif\"/></div>");

$.ajax({
type: "POST",
url: options.webServiceName + "/" + options.renderUCMethod,
data: options.ucMethodJsonParams,
contentType: "application/json; charset=utf-8",
dataType: "json",
success:
function(msg) {
obj.html(msg.d);

// if specified make callback and pass element
if (options.completeHandler)
options.completeHandler(this);
},
error:
function(XMLHttpRequest, textStatus, errorThrown) {
obj.html("امكان اتصال به سرور در اين لحظه مقدور نيست. لطفا مجددا سعي كنيد.");
}
});
});
};
براي اينكه با كليات اين روش آشنا شويد مي‌توان به مقاله "بررسي وجود نام كاربر با استفاده از jQuery Ajax در ASP.Net" مراجعه نمود كه از ذكر مجدد آن‌ها خودداري مي‌شود. همچنين در مورد نوشتن يك پلاگين جي‌كوئري در مقاله "افزونه جملات قصار jQuery" توضيحاتي داده شده است.
عمده كاري كه در اين پلاگين صورت مي‌گيرد فراخواني متد Ajax جي‌كوئري است. سپس به متد وب سرويس ما (كه در اينجا نام آن به صورت پارامتر نيز قابل دريافت است)، پارامترهاي لازم پاس شده و سپس نتيجه حاصل به يك شيء در صفحه اضافه مي‌شود.
completeHandler آن اختياري است و پس از پايان كار متد اجكس فراخواني مي‌شود. در صورتيكه به آن نيازي نداشتيد يا مقدار آن را null قرار دهيد يا اصلا آن‌را ذكر نكنيد.

مثالي در مورد استفاده از اين وب سرويس و همچنين پلاگين جي‌كوئري نوشته شده:

الف) يوزر كنترل ساده زير را به پروژه اضافه كنيد:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="part1.ascx.cs" Inherits="TestJQueryAjax.part1" %>
<asp:Label runat="server" ID="lblData" ></asp:Label>
بديهي است يك يوزر كنترل مي‌تواند به اندازه يك صفحه كامل پيچيده باشد به همراه انواع و اقسام ارتباطات با ديتابيس و غيره.

سپس كد آن‌را به صورت زير تغيير دهيد:

using System;
using System.Threading;

namespace TestJQueryAjax
{
public partial class part1 : System.Web.UI.UserControl
{
public string Text1 { set; get; }
public string Text2 { set; get; }

protected void Page_Load(object sender, EventArgs e)
{
Thread.Sleep(3000);
if (!string.IsNullOrEmpty(Text1) && !string.IsNullOrEmpty(Text2))
lblData.Text = Text1 + "<br/>" + Text2;
}
}
}
اين يوزر كنترل دو خاصيت عمومي دارد كه توسط وب سرويس مقدار دهي خواهد شد و نهايتا حاصل نهايي را در يك ليبل در دو سطر نمايش مي‌دهد.
عمدا يك sleep سه ثانيه‌اي در اينجا در نظر گرفته شده تا اثر آن‌را بهتر بتوان مشاهده كرد.

ب) اكنون كد مربوط به صفحه‌اي كه قرار است اين يوزر كنترل را به صورت غيرهمزمان بارگذاري كند به صورت زير خواهد بود (مهم‌ترين قسمت آن نحوه تشكيل پارامترها و مقدار دهي خواص يوزر كنترل است):

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="TestJQueryAjax._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>

<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/jquery.advloaduc.js" type="text/javascript"></script>
<script src="js/json2.js" type="text/javascript"></script>

<script type="text/javascript">
function showAlert() {
alert('finished!');
}

//تشكيل پارامترهاي متد وب سرويس جهت ارسال به آن
var fileName = 'part1.ascx';
var props = [{ 'Key': 'Text1', 'Value': 'سطر يك' }, { 'Key': 'Text2', 'Value': 'سطر 2'}];
var jsonText = JSON.stringify({ path: fileName, properties: props });

$(document).ready(function() {
$("#loadMyUc").advloaduc({
webServiceName: 'Ajax.asmx',
renderUCMethod: 'RenderUserControl',
ucMethodJsonParams: jsonText,
completeHandler: showAlert
});
});

</script>

</head>
<body>
<form id="form1" runat="server">
<div id="loadMyUc">
</div>
</form>
</body>

</html>
نكته:
براي ارسال صحيح و امن اطلاعات json به سرور، از اسكريپت استاندارد json2.js استفاده شد.

ابزار ديباگ:
بهترين ابزار براي ديباگ اين نوع اسكريپت‌ها استفاده از افزونه فايرباگ فايرفاكس است. براي مثال مطابق تصوير زير، يوزر كنترلي فراخواني شده است كه در سرور وجود ندارد:


دريافت مثال فوق


۱۳۸۸/۰۴/۱۴

پيدا كردن MAC Address از روي IP


دستگاه كارتخوان تحت شبكه‌اي را تصور كنيد كه تا ديروز در شبكه ديده مي‌شد اما امروز ناپديد شده! ديگر نمي‌شود با آن ارتباط برقرار كرد و توسط برنامه نوشته شده آن‌را تخليه كرد. به صورت پيش فرض يك IP ثابت به اين دستگاه‌ها انتساب داده مي‌شود مثلا 192.168.1.100 . حال اگر در شبكه اين IP رزرو نشود ممكن است DHCP اين IP را به كامپيوتر ديگري بدهد يا روتري به اشتباه از آن استفاده كند. الان چطور بايد تشخيص داد كه اين IP توسط چه وسيله‌اي در حال استفاده است؟
براي بدست آوردن MAC Address يك ديوايس در شبكه از دستور خط فرمان ARP مي‌توان استفاده كرد. براي مثال:

arp -a

و يا :
arp -a findstr 192.168.1.100


اگر در اين ليست‌ها MAC Address آي پي مورد نظر شما يافت نشد، ابتدا آن IP را ping كنيد و بعد دستورات فوق را استفاده نمائيد. علت هم اين است كه دستورات فوق تنها ARP table ايي را بر اساس ارتباطات ايستگاه كاري فعلي با شبكه نمايش مي‌دهند و اگر كامپيوتر فعلي هيچ ارتباطي با IP مورد نظر نداشته باشد، خروجي خاصي را نمايش نخواهد داد.

حال اگر با برنامه نويسي بخواهيم اين‌كار را انجام دهيم با استفاده از تابع API زير نيز مي‌توان به همين نتيجه رسيد:

[System.Runtime.InteropServices.DllImport("Iphlpapi.dll", EntryPoint = "SendARP")]
internal extern static Int32 SendArp(Int32 destIpAddress, Int32 srcIpAddress, byte[] macAddress, ref Int32 macAddressLength);

public static System.Net.NetworkInformation.PhysicalAddress GetMacFromIP(System.Net.IPAddress IP)
{
if (IP.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
throw new ArgumentException("supports just IPv4 addresses");

Int32 addrInt = IpToInt(IP);
Int32 srcAddrInt = 0;
byte[] mac = new byte[6]; // 48 bit

int length = mac.Length;
int reply = SendArp(addrInt, srcAddrInt, mac, ref length);

byte[] emptyMac = new byte[12];

if (reply != 0)
{
//No MAC Address found for the IP Address
return new System.Net.NetworkInformation.PhysicalAddress(emptyMac);
}
return new System.Net.NetworkInformation.PhysicalAddress(mac);
}

private static Int32 IpToInt(System.Net.IPAddress IP)
{
byte[] bytes = IP.GetAddressBytes();
return BitConverter.ToInt32(bytes, 0);
}
مك آدرسي كه در حال استفاده از IP ما بود:
00:0F:8F:F1:EE:40

مك آدرس واقعي دستگاه كارتخوان:
00.64.00.00.5E.7A

اين تداخل رخ داده، باعث شده بود كه ارتباط با دستگاه كارتخوان قطع شود. همانطور كه مي‌دانيد سه بايت اول هر مك آدرس مي‌تواند بيانگر شركت سازنده‌اي باشد. 00:0F:8F مربوط به روترهاي سيسكو است.

۱۳۸۸/۰۴/۱۳

اسكريپت‌هاي خود را يكي كنيد


به ScriptManager ارائه شده در دات نت فريم ورك 3 و نيم، سرويس پك يك، امكان تركيب و يكي كردن اسكريپت‌هاي يك سايت نيز اضافه شده است. به مثال زير دقت بفرمائيد:

<asp:ScriptManager runat="server" ID="scMan1">
<CompositeScript>
<Scripts>
<asp:ScriptReference Path="~/flash_detect.js" />
<asp:ScriptReference Path="~/jquery.min.js" />
</Scripts>
</CompositeScript>
</asp:ScriptManager>

به صورت خودكار تمامي ScriptReference هاي قرار گرفته درون تگ CompositeScript ، يكي شده و توسط يك ScriptResource به صفحه اضافه خواهند شد. براي مثال:

<script src="/ScriptResource.axd?d=cAKulKR-axYxbFwMRvm-IlAnHOZjn3-BvtfYzmKItFijWImCOZdjuDVGIFvqZLFX0" type="text/javascript"></script>

مزايا:
  • - كم شدن رفت و برگشت‌ها به سرور. به اين صورت مرورگر تنها يكبار درخواست دريافت اسكريپت فوق را به سرور ارسال مي‌كند و نه چندين بار به ازاي هر يك از اسكريپت‌هاي سايت.
  • - كش شدن خودكار اسكريپت‌ حاصل. (هدرهاي لازم اضافه مي‌شوند)
  • - اگر مرورگر HTTP compression را پشتيباني كند، نتيجه حاصل GZip شده ارائه مي‌گردد.

و نهايتا استفاده از اين گزينه به بالا رفتن سرعت بارگذاري سايت، كمك شاياني را خواهد نمود.

ماخذ


۱۳۸۸/۰۴/۱۲

خواندني‌هاي 12 تير


اس كيوال سرور

امنيت

توسعه وب

دات نت فريم ورك

دبليو سي اف

دبليو پي اف و سيلور لايت

سايت‌هاي ايراني

شيرپوينت

لينوكس

متفرقه

محيط‌هاي مجتمع توسعه

مرورگرها

مسايل انساني، اجتماعي و مديريتي برنامه نويسي

پي اچ پي

۱۳۸۸/۰۴/۱۱

سايت‌هاي خبري ايراني و RSS هاي بي‌خاصيت آن‌ها!


در طي اين چند وقت اخير هر قدر به سايت‌هاي خبري داخل كشور مراجعه كردم بيشتر نا اميد شدم. آيا واقعا اين بزرگواران فكر مي‌كنند مردم فرصت اين را دارند كه روزانه به چند صد سايت خبري سر بزنند؟ اين سايت‌ها يا RSS فيد ندارند و يا اين مشكلات را به همراه دارند:
  • استاندارد نبودن تاريخ فيدها. (عزيزان برنامه نويس اين تاريخ شمسي نيست و نبايد باشد! RSS يك فرمت استاندارد است.)
  • استاندارد نبودن محتواي XML توليد شده (قابل parse نيست!)
  • بعضي از آن‌ها RSS فيد دارند اما بايد چند دقيقه در سايت جستجو كنيد تا يك لينك را بتوانيد در اين زمينه پيدا كنيد!
  • از همه بدتر اينكه خروجي RSS آن‌ها يا چند لينك است بدون توضيح يا چند لينك است بعلاوه يك سطر توضيح. (هدف يك مشترك RSS اين است كه ديگر به سايت شما مراجعه نكند و مشروح مطالب را از طريق فيد دنبال كند. بنابراين يك لينك كافي نيست. يك سطر توضيح هم كم لطفي است. لطفا كل متن خبر را نيز ارائه دهيد.)
  • تعداد در نظر گرفته شده ناكافي مداخل مربوطه. مثلا امروز 20 خبر در سايت درج شده اما فيد RSS آن فقط 10 خبر آخر را نمايش مي‌دهد. اين فيد هم تقريبا بدون استفاده است چون حداقل يك روز كامل را پوشش نمي‌دهد.

۱۳۸۸/۰۴/۱۰

برفراز ابرها


دموي جالبي است در مورد پردازش ابري، مزايا و معايب آن و روش‌هاي موجود