PDA

View Full Version : حرفه ای: کلاسی برای باز کردن صفحات وب با PHP درون سرور



amir001
دوشنبه 25 بهمن 1389, 15:58 عصر
با سلام

من یک کلاس نوشته ام برای باز کردن یک URL درون سرور.

من خودم از این مورد زیاد استفاده میکنم و فکر میکنم استفاده زیادی هم برای بقیه داشته باشه.

متد اصلی این کلاس یک URL را میگیرد و آن را باز میکند.

تنها کاری که نیاز هست انجام دهیم این هست که آدرس URL را به تابع اصلی آن بدهیم تا سایت را باز کند و در صورتی که بخواهیم دیتایی را به آن URL ارسال کنیم باید آن را به عنوان آرگومان دوم به تابع بدهیم.

مزیت های این کلاس:
کار با کوکی ها (در صورتی که در پاسخ URL کوکی باشد آنرا ذخیره کرده و به همراه درخواست های بعدی ارسال میکند.)
امکان اضافه و کم کردن کوکی ها.
امکان اضافه کردن Referere به هدرها.
امکان اضافه کردن هدر های سفارشی
پشتیبانی از gzip در ورودی دیتا. (با این امکان حجم داده های دریافتی تا چند برابر کمتر میشوند ، در صورتی که سرور مورد نظر ما از آن پشتیبانی کند.)
پشتیبانی از SSL برای کار با پروتکل Https

در صورت وجود Location در هدر دریافتی به صورت اتوماتیک به لینک جدید میرود (این قسمت هم تکمیل شده)

و مهمترین ویژگی اون فکر میکنم سادگی کار با اون هست.

یک نمونه:


<?php
include_once("browser.class.php");

$ff = new Browser();
$ff->Open("http://www.google.com/");

echo $ff->Response['body'];

?>
ممنون میشم دوستان نظرشون را بفرمایند و در کامل کردن اون به من کمک کنند.
هر نکته ای که فکر میکنید باعث بهینه شدن برنامه و کم شدن کدها و ساده تر شدن الگوریتم ها میشه بفرمایید تا اصلاح کنم.
اگر فکر میکنید توابع دیگری هم نیاز هست بفرمایید تا به آن اضافه کنیم.
خطاهای موجود در اون را گزارش بفرمایید تا اصلاح شوند.

(با کم و زیاد شدن کد و ویرایش آن فایل جدید جایگزین همین فایل درون پست اول می شود.)


فایل پیوست به رو رسانی شد.

amir001
دوشنبه 25 بهمن 1389, 16:02 عصر
راهنمای توابع موجود :



function Debug($flag)
این تابع در صورتی که ورودی آن true باشد باعث میشود که در مراحل بعدی عملیات مرحله به مرحله در خروجی نمایش داده شود. برای عملیات دیباگ کردن میباشد.



function Open( $url , $data = null)
این تابع ، تابع اصلی کلاس میباشد که یک URL را میگیرد و آن را باز میکند. در صورتی بخواهیم مقادیری را به سرور ارسال کنیم آن را در آرگومان دوم تابع قرار میدهیم و اطلاعات به صورت POST ارسال میشوند.
بعد از اجرای این تابع نتایج باز کردن URL در یک آرایه عضو کلاس قرار میگیرد.


$this->Response['header'];
$this->Response['body'];




function GetAllData()
این تابع یک خروجی از متغیر های موجود در کلاس و مقادیر آنها میدهد. (استفاده در هنگام خطایابی)


function AddHeader($name , $val)
این تابع برای اضافه کردن یک هدر میباشد. نام و مقدار را میگیرد و به هدرها اضافه میکند.

نمونه:

$ff->AddHeader("X-Sender" , "PHP-Browser");



function GetCookie()
مقدار فعلی کوکی ها را باز میگرداند.


function AddCookie($name,$val)
برای اضافه کردن یک کوکی


function SetReferer($ref)
اضافه کردن آدرس منبع به هدرها

لیست توابع داخلی کلاس:


private function CheckLocation()
هدر پاسخ را بررسی میکند اگر حاوی Location باشد ، صفحه را Redirect میکند.


private function addressParser($url)
این تابع برای پارس کردن آدرس ورودی و جدا کردن بخش های مختلف آن میباشد.



private function OpenPage($hed)
مرحله ی نهایی باز کردن صفحه را انجام میدهد. هدرها توسط توابع دیگر داده میشوند و این تابع هدرها را درون سرور مورد نظر مینویسد و پاسخ را دریافت میکند.



private function Get()
عمل ساخت هدرها برای عمل GET را انجام میدهد.


private function Post()
عمل ساخت هدر ها و اضافه کردن دیتا برای عمل POST را انجام میدهد.



private function SetCookie($text)
اضافه کردن یک کوکی . تابع داخلی که رشته موجود در هدر پاسخ را گرفته و کوکی ها را از آن بیرون کشیده و به رشته کوکی ها اضافه میکند و یا آنها را به روز میکند.(جایگزین)



private function translateCookie()
آرایه ی کوکی های موجود را به یک رشته برای ارسال تبدیل میکند.


private function errorLog($text)
خطاها را لاگ مکند.



private function Log($text)
این تابع عملیات لاگ کردن مراحل را انجام میدهد. در صورتی متغیر $debug مقدار true داشته باشد مراحل را در خروجی نمایش میدهد.

$ M 3 H R D A D $
جمعه 29 بهمن 1389, 19:24 عصر
چرا ادامه ندادید این آموزش و ؟ یک مثال برای لوگین بزنید

Mr.Moghadam
یک شنبه 01 اسفند 1389, 16:27 عصر
سلام
کلاس خیلی خوبیه ولی برای من عکسها و کلا قالب آدرس مورد نظر باز نمیشه و همه چیز به هم ریخته است این مشکل رو چجوری میشه حل کرد؟

amir001
یک شنبه 01 اسفند 1389, 16:47 عصر
این کد سورس آدرسی را که بهش دادید خروجی میده.
شما اون را چاپ میکنید. بقیه عکس ها و فایل های سی اس اس و... را مرورگر تون باز میکنه. در صورتی که آدرس عکس ها و ... فیلتر باشند یا مشکل مشابهی داشته باشند نمیتونند باز بشن و نمایش داده نمیشن.

اگر میخواهید با این کلاس عکس ها و ... را باز کنید باید آدرس آنها را در سورس سایت با یک آدرس جدید جایگزین کنید و سپس اونها را توسط همین کلاس باز کنید و نمایش بدید.

Yousha
یک شنبه 01 اسفند 1389, 17:36 عصر
بجای نوشتن چند بار کلمه private public protected و... یک با بنویس و بقیه رو جلوش قرار بده.
صحیح private $xx, $yy, $dd یا public $ff, $rr, $gg
نادرست private $ss; private $tt; private $gg...

مهمتر از همه کلاس شما Constructor نداره. یک تابع با نام کلاس Browser یا با نام __construct درست کنید و فراخوانی/initation اولیه رو رو داخلش قرار بده.

{} دستورات شرطی رو هم کامل بزار(اصولی نیست).

بجای " از ' برای رشته های معمولی استفاده کن(حتماً حتماً). سرعت پردازش رو خیلی افزایش میده. این " برای رشته هایی هست که متغیر داخلشه.

نام توابع و متغیر هایی که private هستند رو با _ شروع کنید(اصول برنامه نویسی هستش). private _myFunction ------- private $_myVar

Tab ها و فضاهای اضافی رو هم پاک کن.

از رفرنس & هم حتماً استفاده کن.

یک تابع __destruct هم در آخر کلاس قرار بده و تمام متغیر هارو داخلش بزار.
مثل


public function __destruct()
{
unset($this->_Str_Path, $this->_File, $this->_Ary_Variable);
}


کلاسهای client/sniffer در اینترنت زیاد هست. چند تاشونو بگیرید و از نقاط قوتش الگو بگیرید(منظورم کپی نیست).
موفق باشی

amir001
سه شنبه 03 اسفند 1389, 14:59 عصر
سلام دوست عزیز
اول از همه به خاطر لطفی که فرمودین تشکر میکنم.
نکات خوبی را بیان کردید که جالب بودند.

اما جسارتا بعضی از اونها را قبول ندارم.


بجای نوشتن چند بار کلمه private public protected و... یک با بنویس و بقیه رو جلوش قرار بده.
{} دستورات شرطی رو هم کامل بزار(اصولی نیست).


Tab ها و فضاهای اضافی رو هم پاک کن.

از رفرنس & هم حتماً استفاده کن.

ی

استفاده از یک کلمه private برای چندین متغیر کلاس فکر میکنم کار درستی نیست.
همونطور که میدونید توی سی نوشته میشه private: و تمام عناصر بعد از اون خصوصی میشه که در زبانی مثل سی شارپ این امکان وجود نداره و باید برای هر متغیر یا متد جدا قید بشه (مایکروسافت به خاطر دلایل خوبی این امکان را برداشته).

نوشتن تابع سازنده در کلاس الزامی نیست و در صورتی که بخواهیم برای کلاسها ورودی بگیریم و یا حافظه بگیریم استفاده میشه.

در مورد تخریب کننده رعایت میکنم و متغیر ها را از بین میبرم. کار درستی هست.

نوشتن {} برای دستورات شرطی ، یک دستوری الزامی نبوده و هنوز هم نیست. و به خاطر تو رفتگی هایی که ایجاد میشه خوانا هستند. اما در کل میدونم که نوشتنشون بهتره.

در مورد فضای خالی اصلا قبول ندارم. یکی از اصول اصلی برنامه نویسی ایجاد تو رفتگی هست که همین TAB ها هستند و باعث خوانا شدن برنامه میشه.

در مورد & در php زیاد نمیدونم. میشه توضیح بدید که چیکار میکنه؟

sattaryekta
سه شنبه 03 اسفند 1389, 22:01 عصر
کار بسیار بسیار عالی بود. :تشویق:
من قبلا برای ساخت یک موتور جستجوی وب سایت های ایرانی یک همچین چیزی طراحی کردم ولی با یک سایت مشکل داشت که متأسفانه این کلاس هم همون مشکل را داره. لطفا این را تست کنید:

$ff->Open("http://aftab.ir/");یا کد زیر:


$ff->Open("http://www.aftab.ir/");که منجر به این خطا شد:


Notice: Undefined variable: Res in browser.class.php on line 199

amir001
سه شنبه 03 اسفند 1389, 23:56 عصر
تست کردم و به درستی جواب داد.

کلاسی که نوشتم خودش کوکی ها را ذخیره میکنه . مشکلی که فعلا هست اینه که تغییر آدرس سایت را از طریق هدرهای دریافتی پشتیبانی نمیکنه که فعلا باید به صورت دستی این کار را انجام داد تا اینکه اون قسمت را بنویسم.

برای همین اگر متد دیباگ اون را با ورودی true مقدار دهی کنید مراحل را میبینید.

برای باز کردن صفحه اول آفتاب یک بار به شما کوکی ارسال میکنه و بعد شما را به یک صفحه دیگر ارجاع میده و بعد دوباره به صفحه اصلی بر میگردونه.

برای همین این سه خط را پشت سر هم بنویسید تا بتونید صفحه اصلی سایت را ببینید.


$ff->Open("http://www.aftab.ir/");
$ff->Open("http://www.aftab.ir/include/chkc.php?url=/");
$ff->Open("http://www.aftab.ir/");که اینطوری میشه:


<?php
include_once("browser.class.php");

$ff = new Browser();
$ff->Debug(true);
$ff->AddHeader("Accept-Encoding","gzip");

$ff->Open("http://www.aftab.ir/");
$ff->Open("http://www.aftab.ir/include/chkc.php?url=/");
$ff->Open("http://www.aftab.ir/");

?>

sattaryekta
چهارشنبه 04 اسفند 1389, 15:01 عصر
فعلا باید به صورت دستی این کار را انجام داد تا اینکه اون قسمت را بنویسم
خیلی ممنون. کلاس مفیدیست.

Yousha
یک شنبه 08 اسفند 1389, 13:09 عصر
استفاده از یک کلمه private برای چندین متغیر کلاس فکر میکنم کار درستی نیست.
همونطور که میدونید توی سی نوشته میشه private: و تمام عناصر بعد از اون خصوصی میشه که در زبانی مثل سی شارپ این امکان وجود نداره و باید برای هر متغیر یا متد جدا قید بشه (مایکروسافت به خاطر دلایل خوبی این امکان را برداشته).
#C کجا PHP کجا؟ هیچ ربطی به هم ندارند.


نوشتن تابع سازنده در کلاس الزامی نیست و در صورتی که بخواهیم برای کلاسها ورودی بگیریم و یا حافظه بگیریم استفاده میشه.
کپسوله سازی که نمی کنید؟ میکنید؟
چه بخواید و چه نخواید اصول شی نویسی اینه.


در مورد فضای خالی اصلا قبول ندارم. یکی از اصول اصلی برنامه نویسی ایجاد تو رفتگی هست که همین TAB ها هستند و باعث خوانا شدن برنامه میشه.
100%. من اینو نگفتم. گفتم Tab های اضافی. مثلاً بین دستورات.


if x
y
اینجا
if x
y
...



در مورد & در php زیاد نمیدونم. میشه توضیح بدید که چیکار میکنه؟
این علامت رفرنس هستش. و تقریباً کار Pointer در Cرو انجام میده. بجای کپی یک مقدار، اصلش رو استفاده می کنه. PHP manual رو مطالعه کنید.

amir001
جمعه 20 اسفند 1389, 21:33 عصر
#C کجا PHP کجا؟ هیچ ربطی به هم ندارند.


من سی شارپ را به عنوان زبانی مثال زدم که اصول مهندسی نرم افزار و کاهش خطا درونش بسیار رعایت شده.

به خاطر نظرات مفیدتون تشکر میکنم.

در ادامه تغییرات...

رضا قربانی
جمعه 20 اسفند 1389, 22:40 عصر
تغییر جدیدی اعمال کردید ؟ اگه آپدیت کردید خبر کنید

با تشکر

amir001
شنبه 21 اسفند 1389, 18:10 عصر
فایل پیوست به روز رسانی شد:
پیروی کردن از Location برای تغییر مسیر تکمیل شد.
اضافه شدن $ResponseHeader به متغیر های کلاس برای نگهداری مقادیر هدر دریافتی به صورت آرایه انجمنی. همچنین اضافه شدن یک متد برای تبدیل هدر های بازگشتی به آرایه ی انجمنی.

نمونه:
Array
(
[status] => HTTP/1.0 200 OK
[0] => HTTP/1.0 200 OK
[date] => Sat, 12 Mar 2011 14:55:24 GMT
[expires] => Sat, 12 Mar 2011 14:55:24 GMT
[cache-control] => private, max-age=0
[content-type] => text/html; charset=UTF-8
[content-encoding] => gzip
[content-length] => 6065
)



دوستان لطف کنند اگر باگ مشاهده کردند بفرماییند تا اصلاحش کنم.
به خصوص در تغییر Location که تازه اضافه شده.

sattaryekta
یک شنبه 22 اسفند 1389, 12:27 عصر
کلاسی که نوشتم خودش کوکی ها را ذخیره میکنه . مشکلی که فعلا هست اینه که تغییر آدرس سایت را از طریق هدرهای دریافتی پشتیبانی نمیکنه که فعلا باید به صورت دستی این کار را انجام داد تا اینکه اون قسمت را بنویسم.
یعنی این مشکل حل شد؟

رضا قربانی
یک شنبه 22 اسفند 1389, 13:47 عصر
ببینم این فایل ها رو از سایت خودت کپی کردی دیگه (یعنی فایل های خودت رو پاک کردی و این قسمتش رو واسه ما گذاشتید :لبخند::متفکر: ؟ RSS گذاشتی تا خبرا رو از سایت بگیره ؟ )

amir001
یک شنبه 22 اسفند 1389, 14:32 عصر
یعنی این مشکل حل شد؟

بله مشکل حل شد. در صورتی که صفحه ای را درخواست بدید و اون با Location شما را به صفحه جدید انتقال بده، درون برنامه Location شناسایی میشه و دنبال میشه.


ببینم این فایل ها رو از سایت خودت کپی کردی دیگه (یعنی فایل های خودت رو پاک کردی و این قسمتش رو واسه ما گذاشتید :لبخند::متفکر: ؟ RSS گذاشتی تا خبرا رو از سایت بگیره ؟ )

متوجه منظورتون نشدم. :لبخندساده:

رضا قربانی
یک شنبه 22 اسفند 1389, 14:58 عصر
منظورم اینه که این سه فایلی که گذاشتید واسه آپلود ، قسمتی از سایت شما بوده .

یه کم بیشتر در مورد این چیزی که نوشتید توضیح می دید و بگید که چه عملی رو انجام می ده و همراه با تستش و خلاصه فرض کنید ما هیچی از این مبحث حالیمون نیست :لبخند:

amir001
یک شنبه 22 اسفند 1389, 15:42 عصر
منظورم اینه که این سه فایلی که گذاشتید واسه آپلود ، قسمتی از سایت شما بوده .

یه کم بیشتر در مورد این چیزی که نوشتید توضیح می دید و بگید که چه عملی رو انجام می ده و همراه با تستش و خلاصه فرض کنید ما هیچی از این مبحث حالیمون نیست :لبخند:

اسم سایتم را فقط برای نمونه آوردم، توی مثال هاش ذکر کردم.

ببینید فرض کنید میخواهید سمت سرور و با یک برنامه PHP محتویات یک صفحه اینترنتی را بگیرید. برای این کار باید سوکت پروگرامینگ بلد باشید و همچنین با پروتکل HTTP هم آشنا باشد. با استفاده از این کلاس دیگه نیازی به موارد بالا ندارید.
فرض کنید من میخوام فید آخرین اخبار ایسنا را بگیرم و اخبار اون را بریزم درون دیتا بیس سایت خودم. به این شکل عمل میکنم که یک شئ از اون کلاس میسازم و با فراخوانی کردن متد اون و دادن آدرس صفحه فید ایسنا، به راحتی محتویات اون را میگیرم.

ببینید:


<?php
include_once("browser.class.php");
$ff = new Browser();
$xmlData = $ff->Open("http://www.isna.ir/isna/xml/");
?>


این یک نمونه بود.
فرض کنید میخوام از سمت سرور یک عکس را از یک سایت بگیرم و اون را روی سرور خودم ذخیره کنم.


<?php
include_once("browser.class.php");
$ff = new Browser();
$imageData = $ff->Open("http://dblog.ir/wp-content/uploads/2011/02/r17pzqqfnf61hb7azqz1.jpg");

$fp = fopen("image.jpg",'a');
fwrite($fp,$imageData,strlen($imageData));
fclose($fp);

?>


فرض کنید میخوام یک سایت را باز کنم و یکسری اطلاعات را در حالت پست به اون ارسال کنم.
برای مثال من کلمه SEARCH_TEXT را میخوام در سایت تابناک جست جو کنم.
ابتا اطلاعاتی که باید به سایت ارسال بشه را درون یک متعیر قرار دادم و بعد اون را به صفحه جستجوی تابناک ارسال کردم.


<?php
include_once("browser.class.php");
$ff = new Browser();
$PostData = "query=SEARCH_TEXT&submitbutt=%D8%AC%D8%B3%D8%AA%D8%AC%D9%88&from=1384%2F01%2F01&to=1389%2F12%2F22&service_id=-1&sec_id=-1&rpp=10&_asearch_submit=yes"
$searchRes = $ff->Open("http://www.tabnak.ir/fa/search",$PostData);
?>

ابوذر محمودی
سه شنبه 02 فروردین 1390, 10:32 صبح
ببخشید،واسه سایت هایی که نیاز به لاگین داره چطور عمل کنیم؟مثلا میخوایم یه فایل ضمیمه از انجمن برنامه نویس دانلود کنیم،میشه توضیح بدین؟

shahriyar3
یک شنبه 29 بهمن 1391, 15:35 عصر
اسم توابع و نحوه عملکرد برنامه خیلی شبیه یکی از extention های php هست!!
ولی به نظر میاد که وقت گذاشتی تکمیل کردیش شاید هم واقعا خودت نوشته باشیش ولی در هر صورت
توی سایت phpclasses.org ثبت کن به نام خودت. امضا تو هم به اول کلاس اضافه کن , حیفه همچین کلاسی بدون کپی رایت استفاده بشه :چشمک:

amir001
شنبه 05 اسفند 1391, 13:46 عصر
اگر برنامه نویسی حرفه ای کار کرده باشید باید بدونید که هیچ جایی نام کلاس و نام توابع و یا حتی نام متغیر ها را ملاک کپی بودن کد قرار نمیدن، چون برنامه نویس باید از نامهای مرتبط استفاده کنه تا خوانایی کد بالاتر بره، مثلا در همه ی زبان های برنامه نویسی نام توایع سوکت مثل هم هستن.

اگر همچین کلاسی سراغ دارید اینجا بذاریدش همه استفاده میکنیم.

Unique
شنبه 05 اسفند 1391, 14:31 عصر
از کلاس خوبی که گذاشتین بسیار تشکر میکنم، یکی از مشکلات curl زمانی که روی سرور های shared کار میکنیم و safe mode هست و (با یه تغییر دیگه که یادم نیست) مشکل location توی header هست که واقعا اذیت میکنه. امیدوارم دوستان قدر کسانی که اینجا نتیجه زحمات شبانه روزیشون را میگذارند بدونند.

mohammadhosin
جمعه 25 اسفند 1391, 23:56 عصر
سلام به همه دوستان
من تازه کارم ولی تو این زمینه زیاد کد امتحان کردم ( حتی این کد اخیر رو )
همهشون رو میزارم اینجا



<?php
echo copy("http://www.test.com","test.html");
?>
سایت رو روی سرور کپی میکنه و میتونید مستقیم باز کنید



<?
$URL= $_POST['url'];
echo file_get_contents("$URL");
?>

ساده ترین کدی که سایت بدون کپی کردن باز میکنه براتون



<?php
#usage:
$mhm= $_POST['url'];
$r = new HTTPRequest("$mhm");
echo $r->DownloadToString();

class HTTPRequest
{
var $_fp; // HTTP socket
var $_url; // full URL
var $_host; // HTTP host
var $_protocol; // protocol (HTTP/HTTPS)
var $_uri; // request URI
var $_port; // port

// scan url
function _scan_url()
{
$req = $this->_url;

$pos = strpos($req, '://');
$this->_protocol = strtolower(substr($req, 0, $pos));

$req = substr($req, $pos+3);
$pos = strpos($req, '/');
if($pos === false)
$pos = strlen($req);
$host = substr($req, 0, $pos);

if(strpos($host, ':') !== false)
{
list($this->_host, $this->_port) = explode(':', $host);
}
else
{
$this->_host = $host;
$this->_port = ($this->_protocol == 'https') ? 443 : 80;
}

$this->_uri = substr($req, $pos);
if($this->_uri == '')
$this->_uri = '/';
}

// constructor
function HTTPRequest($url)
{
$this->_url = $url;
$this->_scan_url();
}

// download URL to string
function DownloadToString()
{
$crlf = "\r\n";

// generate request
$req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
. 'Host: ' . $this->_host . $crlf
. $crlf;

// fetch
$this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
fwrite($this->_fp, $req);
while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
$response .= fread($this->_fp, 1024);
fclose($this->_fp);

// split header and body
$pos = strpos($response, $crlf . $crlf);
if($pos === false)
return($response);
$header = substr($response, 0, $pos);
$body = substr($response, $pos + 2 * strlen($crlf));

// parse headers
$headers = array();
$lines = explode($crlf, $header);
foreach($lines as $line)
if(($pos = strpos($line, ':')) !== false)
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));

// redirection?
if(isset($headers['location']))
{
$http = new HTTPRequest($headers['location']);
return($http->DownloadToString($http));
}
else
{
return($body);
}
}
}
?>اینم یه کد کامل هست که یادم نیست از کجا گرفتم (با اجازه منبع)



<tr>
<form name=upload method=post action=test.php>
<input name="url" type="text" value="http://"></input>آدرس فایل :</span></p></td>
<input name="submit" type="Submit" value="آپلود" style="width: 82px"> </input>
</tr>

اینم یه کد ساده برای فرستادن آدرس سایت به کد ها

همه کد ها تست شده هستن