امروز یه اتفاق خیلی ساده، یه درس بزرگ بهم داد. داشتم یه برنامه ساده CRUD مینوشتم، یعنی یه برنامه ای که یه سری فیلد رو توی دیتابیس بنویسه، ویرایش داشته باشه و حذف کنه و در نهایت نشون بده.
این برنامه فقط برای نمایش برای یه نفر بود که میخواست یه چیزی یاد بگیره :دی خیلی ساده.
مساله لینک حذف بود، این لینک :‌


http://localhost/admin.php?del=10

در حقیقت این میومد و ردیف شماره ۱۰ رو حذف میکرد. البته توی admin.php بررسی میشد که آیا کاربر اجازه دسترسی داره یا نه. اگه اجازه حذف داشت اونوقت حذف رو انجام میداد. به نظر همه چی درست بود، ولی یه اتفاق باعث شد بفهمم یه جای کار میلنگه.
این لینک رو اتفاقی کپی کردم توی کلیپ برد. خودمم همزمان میخواستم یه جایی تو یه پیغام شخصی فروم، یه عکس بگذارم. منتها اشتباها این لینک کپی شد به جای لینک عکس اصلی. از اونجایی که دقت منم در حد تیم ملیه :)‌ عکس رو با بدون اینکه آدرسش رو چک کنم گذاشتم توی پیغام، دکمه پیشنمایش رو زدم و …

باقیش معلومه. فیلد ۱۰ حذف شد، و من حتی متوجه نشده بودم تا یه کم بعد رفتم دوباره سراغ برنامه.
خوب این یعنی که با اینکه من امنیت رو کاملا حفظ کرده بودم توی فایل admin.php ولی این امنیت خیلی راحت به هم ریخت با وادار شدن من برای دیدن یه عکس. خوب اگه اینکار رو یه نفر دیگه انجام میداد و یه پیغام حاوی لینک حذف برای من میفرستاد که مثلا به صورت عکس جاسازی شده بود،‌ خیلی راحت به مقصودش میرسید. من اجازه حذف دارم،‌ و فقط کافیه اون لینک یه بار توسط من ویزیت بشه، به هر صورتی.

راه چاره چیه؟؟ اینکه از متد GET استفاده نکنیم.یا اینکه تو صفحه دوم هم یه سوال بپرسیم و بعد از طریق متد پست حذف نهایی رو توی مرحله دوم انجام بدیم، یه کمی به نظر من اعصاب خورد کنه.
البته من یه پیشنهاد هم دارم، که فکر میکنم بد نباشه. یه کلمه رندوم ایجاد بشه تو هر جلسه برای هر کاربر، مثلا به اسم $salt . از هر جلسه به جلسه دیگه متفاوت باشه. به جای لینک بالا، از این لینک استفاده بشه (یا چیزی شبیه اون):


http://localhost/admin.php?del=10&salt=$slat

وقت حذف علاوه بر بررسی سطح دسترسی کاربر این “نمک” هم بررسی بشه :)‌ اگه اونم با متغییری که تو جلسه ذخیره شده برابر بود کاری که باید انجام بشه،‌انجام بشه.
اینطوری، کسی نمیتونه لینک رو درست کنه. (مگه اینکه یه جوری جلسه مدیر رو بدزده، که خوب در اون صورت دسترسی خود مدیر رو داره و دیگه لازم نیست یه همچین کارهایی رو انجام بده، خودش دسترسی داره و میتونه هر کاری میخواد بکنه!!)

پ.ن : به این روش میگن CSRF یا Cross-Site Request Forgery که جالب اینه که خودم هم میدونستم ولی هیچوقت دقت نکرده بودم یعنی همیشه طور دیگه ای بهش نگاه میکردم، اینکه مثلا یه سایت خطرناک رو به خورد کاربر بدن نه سایتی که اصلا خطری نداره و اتفاقا کاربر اجازه دسترسی بهش رو داره و از دسترسی کاربر سواستفاده بشه. این روش هم من دوباره کشف کردم، قبل از من بازم کشف شده بوده :D و من فقط دوباره چرخ رو اختراع کردم!!
بیشتر درباره این قضیه که بگردید دوباره منابع بهتری رو پیدا میکنید و راه حلهای دقیقتر و بهتری.

چک باکس در html

مرداد ۲۰م, ۱۳۸۹

فرمهای HTML ساختار ساده ای دارند. تشکیل شده اند از یه سری المان ساده (معمولا input ) که وقتی کاربر دکمه ارسال (یه عنصر input با نوع submit ) رو میزنه فرستاده میشن به سمت سرور، و البته این که به کجا فرستاده بشه یا اینکه چطور فرستاده بشه توی خصایص فرم مشخص میشه. (خصیصه action برای اینکه فرم به کجا فرستاده بشه و خصیصه method برای اینکه مشخص کنید فرم چطور باید ارسال بشه)
این وسط، وقتی فرم ارسال میشه، کلیه عناصری که اسم دارن (یعنی همه المانهای فرمی که خصیصه name براشون تنظیم شده ) به سمت سرور ارسال میشن، ولی این وسط یه استثنا هست، و اون هم عنصر checkbox.
این عنصر اگه تیک زده بشه مقدار خودشو میفرسته و اگه تیک زده نشه مقدارش فرستاده نمیشه. معمولا مشکلی پیش نمیاد، طرف سرور کافیه بررسی کنید که آیا این اسم تو آرایه _POST یا _GET (بسته به متدی که فرم ارسال میشه) هست یا نه. اگه بود، مقدارش هر چی باشه یعنی چک خورده، اگه نبود یعنی چک نخورده.
ولی اگه نخواید از این روش استفاده کنید چی؟ یعنی اگه بخواید مثلا وقتی چک نخورد، مقداری فرستاده بشه (مثلا 0 ) و اگه چک خورد مقداری ارسال بشه (مثلا ۱ ) .
یه چیزی دیدم تو فرمهای Zend Framework که این مشکل رو برطرف میکرد. برای اینکار کافیه یه عنصر از نوع hidden بالاتر از عنصر checkbox بگذارید، دقیقا به نام همون عنصر checkbox فقط مقدارش رو بگذارید همون مقداری که میخواید وقتی تیک نخورده ارسال بشه (مثل صفر تو مثال ما)‌ بعد عنصر chekbox هم بگذارید و مقدار حالت تیک خورده رو توش بگذارید (تو این مثال یک) خوب اگه تیک نخوره، فرم که ارسال میشه، checkbox اصلا فرستاده نمیشه، ولی عنصر hidden که هست :) در مقابل وقتی چک خورده باشه، عنصر hidden چون قبل از عنصر checkbox هست، مقدارش با مقدار checkbox رونویسی میشه. کد باید اینطور باشه :

<form action="/some/address" method="post">
<input type="hidden" name="mycheckbox" value="0" />
<input type="checkbox" name="mycheckbox" value="1" />
</form>

برای سادگی کل قسمتهای زاید فرم، حذف شده ولی شما کل فرمتون رو بگذارید، فقط یادتون باشه که عنصر hidden باید قبل از عنصر chekbox باشه ، اسمشون هم یکی باشه.

بازم یادداشت شخصی

مرداد ۱۵م, ۱۳۸۹

از اونجایی که بارها گفتم این یه وبلاگ شخصیه که گاهی درباره برنامه نویسی هم توش مینویسم، اینجا اعلام میکنم این یک پست کاملا شخصی است و درباره برنامه نویسی نیست، فقط نظرات شخصی خودم.
اسم گذاری
قبلا میگفتن هر چی بده میگن آقا،‌ آقا گرگه،‌آقا دزده، آقا روباهه… و هر چی خوبه مییشه خانم، خورشید خانم،‌مهتاب خانم …اما جدیدا طور دیگه‌ای شده گویا. من کلا آدمی هستم از تلوزیون فراری، منتها دیشب یه جایی گرفتار شدم که یه سریال میدیدن و صاحبخانه وقتی فهمید که من اصلا این سریال رو ندیدم واسه اینکه من این اطلاعات مهم رو از دست ندم!! تمام داستان رو واسم خلاصه گفت!! یه چیزیش جالب بود : همه آدم خوبا (و اونهایی که داشتن منحرف میشدن و آدم بدا گیرشون انداخته بودن)اسماشون عربی بود- محسن، سعید، (اگه اشتباه نکنم حاج ناصر یا یه همچین چیزی) فامیلیشونم عربی بود، کریمی.
آدم بدا، ولی ، همه اسماشون ایرانی اصیل یا دست کم غیر عربی بود، ساسان، سامان، مهران، بیتا! حتی فامیلیشون : کیان.
اسمها تو همین مایه ها بودن ولی من دقیقا نمیدونم همینها بودن یا شاید من پس و پیش کرده باشم بعضی حروف رو، ولی ایرانی بودن و عربی بودن رو اشتباه نمیکنم.
نوستالژی یا عقب ماندگی؟
فرداش، تلوزیون روشن بود که بیتا (دخترم)‌ ببینه. دیدم آهنگی که پخش میشه آشناست، رفتم و دیدم همون پینوکیویی که من ۲۰ سال پیش (شایدم بیشتر!! ) میدیدم گذاشتن واسه بچه من. داستان مساله نیست، پینوکیو داستانیه که مطمئنم یه روز خودم برای دخترم تعریف میکنم، مساله همون نسخه پینوکیوست. با کیفیت کم، همون خطوط سفید عمودی یا افقی گاه و بیگاه و….. حالم بد شد!!! نه اینکه من خاطره نداشته باشم از این چیزها ولی خداییش اگه قراره دخترم هم همونها رو ببینه که من دیدم، اونم تو این عصر!! تف به این پیشرفت. به خدا درجا زدن از پسرفت بدتره گاهی…
کتاب
عصر دیروز، یه کتاب خوندم از دن براون، در حقیقت از همون شخصیت معروفش رابرت لنگدان که با بازی تام هنکس روی پرده سینما هم اومد. قسمت سومش رو خوندم، اولی فرشتگان و شیاطین بود که داستان روون و خوبی داشت. دومیش کد داوینچی بود که حقیقتا داستان قشنگی بود و خیلی خوب هم نوشته شده و به نظر من بهترین این سری هم بود. سومی، سمبل گمشده‌ (یا همون نماد گمشده) بود که حوصله ام رو سر برد. خوشش اومده انگار اینقدر داستان رو الکی بپیچونه و پرش کنه از معما و … آخرش که دیگه داشتم فقط میخوندم که تموم شه! به هر حال، اینم یه کتابه و هر کتابی ارزش یه بار خوندن داره، خصوصا اگه قبلا دو جلد قبلی رو خونده باشی (تاکیدم روی خوندنه، نه دیدن فیلم).

Mysql Menu قسمت سوم

مرداد ۱۲م, ۱۳۸۹

چند وقت پیش در باره منو و طریقه ایجاد آن با mysql نوشتم. منظورم بیشتر روش دومی بود که معرفی کردم. خودم تا همین روزها نیاز نشده بود که از این منو استفاده کنم، تا امروز برای کاری ار همان پست استفاده کردم. (این وبلاگ بیشتر از هر کسی گویا به درد خودم میخورد) میخواستم از همان کوئری ها استفاده کنم و یک ساختار تشکیل شده از ul و li های تو در تو درست کنم. اول سعی کردم اطلاعات را داخل آرایه بریزم که بعد به صورت html دربیاورم که متوجه شدم دارم لقمه دور سر میچرخانم.
با توجه به اینکه ساختار منو (لطفا پست MySQL , Menu قسمت دوم رو حتما بخونید) دقیقا شبیه ساحتار تو در توی html هست میشه از این خاصیت استفاده کرد :)‌ یعنی اونجا همه منو های یه سمت چپ داشتن یه سمت راست، تو html هم هر تگی یه سمت چپ داره یه سمت راست. من میخوام یه ساختار منوی ساده با ul و li به وجود بیارم طوری که :

  • عنصر دور تا دور فقط یه ul داره.
  • عناصری که زیر مجموعه ندارن دورشون li میفته
  • عناصری که زیر مجموعه دارن هم li میخوان هم ul .
  • اگه آیتمی هیچ زیر منو نداشت اونوقت متن اون آیتم هم نشون داده بشه (شما اینو خودتون میتونید گسترش بدید، یا برای همه منوها آیتم رو نشون بدید، من ترجیح دادم ساده‌تر کار کنم.)

نتیجه خیلی سادست. فقط باید حالات مختلف رو بنویسم.ساختار دیتابیس اینه (مثل مثال قبلی ، فقط فیلد name به صورت unique در اومده برای اینکه توی کد باید به یه چیزی تکیه کرد ;) )

CREATE TABLE IF NOT EXISTS `adv_menu` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(60) NOT NULL,
  `data` varchar(255) NOT NULL,
  `lside` int(11) NOT NULL,
  `rside` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM;

اینبار میخوام از PDO استفاده کنم برای اتصال به mysql . ایده خیلی سادست. فقط در نظر بگیرید که همونطور که قبلا گفتم (تو پست قبلی در این مورد)‌ هر منو یه چپ داره یه راست.
خوب چی میشه اگه سمت چپ رو شروع تگ در نظر بگیریم و سمت راست رو پایان تگ؟ چی میشه اگه یه آرایه ایجاد کنیم به تعداد دو برابر آیتمها، با ایندکس ۱ تا دوبرابر آیتمها، بعد تو آرایه ایندکس سمت چپ تگ شروع html رو بذاریم (مثلا یه li یا یه ul بعد یه li یا هر چیز دیگه ای) و در ایندکس سمت راست هم دقیقا پایان همون تگ سمت راست رو (مثلا اینبار /li )، فقط کافیه بدونیم که مثلا آیتم اگه زیر مجموعه نداشت فقط li میخواد (که این فقط در صورتیه که سمت چپی یکی کمتر از سمت راستی باشه) اگه منوی دور تا دوره فقط یه ul میخواد (که خوب این هم سمت چپش همیشه ۱ میشه)‌ و در غیر این صورت ul و li با هم.
خوب این خیلی ساده ایتمهای توی دیتابیس رو تبدیل میکنه به یه ساختار html و کافیه که اینبار فقط این آرایه رو به هم بچسبونیم و در خروجی نشون بدیم.
کد زیر کل این کارها رو به ساده ترین وجهی انجام میده، ولی باز هم جای کار داره، خیلی زیاد هم جای کار داره.
خواندن ادامه این مطلب »

اسکریپت رو اگه نصب کردید دوباره آپدیت کنید، چون sf یه تغییراتی تو لینک دانلود داده بود که حالا آپدیت شد
چند وقتی هست که SourceForge در یک اقدام “ناجوانمردانه” :D دانلود رو برای چند تا کشور به خصوص محدود کرده. البته این امکان هست که مدیر پروژه این محدودیت رو غیر فعال کنه ولی در صورتی که اینکار انجام نشده باشه مشکل پابرجاست.
این اسکریپتی که نوشتم (با فایرفاکس و Greasemonkey کار میکنه) به شما امکان میده بدون نیاز به هیچ وب سرویس یا برنامه ای با خود فایرفاکس یا هر دانلود منجری که روی فایرفاکس نصبه فایلها رو دانلود کنید. این اسکریپت مستقیما فایل رو از همون Mirror که توی SF استفاده میکنید دانلود میکنه.
برای اینکار به این چند تا گزینه احتیاجه :
اول فایرفاکس!!!
بعد از اون باید یک addon رو نصب کنید. این Addon اسمش Greasemonkey هست و به شما امکان اجرای userscripts رو میده.
بعد از نصب این addon حالا وقتشه که گام آخر رو انجام بدید. روی این لینک کلیک کنید
بعد از کلیک اگر Greasemonkey درست نصب باشه یه دیالوگ میاد و میپرسه که میخواید این اسکریپت نصب بشه؟ بزنید Install و تمام.
حالا هر فایل رو میخوایید میتونید از SourceForge بگیرید. خیلی ساده از صفحه پروژه دکمه دانلود رو بزنید اینبار دیگه مشکلی پیش نمیاد، دقیقا مثل قبل که ایران تحریم نبود میرید برای دانلود.
اگه میخواید توضیحات بیشتر این اسکریپت رو بخونید یا اینکه خدای ناکرده خدای ناکرده در بارش نظری بدید!!! به این آدرس رجوع کنید. اونجا هم دکمه Install هست که البته مثل لینک بالایی عمل میکنه و فرقی نداره.

فقط اینکه هنوز مشکل استفاده از GIT یا SVN و یا … هنوز وجود داره متاسفانه و تنها راهش اینه که مدیر پروژه دست به کار بشه و این مساله رو حل کنه. این هم حل نمیشه مگه اینکه ما خودمون از مدیر پروژه ها درخواست کنیم. برای پروژه Ubuntuzilla من درخواست دادم و مدیر پروژه محدودیت رو برداشت. بعید میدونم هیچکدوم از برنامه نویسهایی که تو SF فعالیت میکنن با این قضیه مشکلی داشته باشن.