9.06.15, 14:48
0 комментарий
  Уроки

Пишем простенький скрипт распознания CMS сайта

Будем использовать фреймворк jQuery (скачать)

Для начала сделаем обертку.

1. Создаем фаил index.php с содержимым:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Определение CMS</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script language="javascript" src="jquery.js" type="text/javascript"></script> 
<script language="javascript" src="light.js" type="text/javascript"></script>
</head>
<body onload="$('#site_list').focus()">

<div class='tabs' id='whois_tab'>

<table border="1" width="100%" cellpadding="10px" cellspacing="0" bordercolor="#4d77a0" style="-moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px;" rules="none">

<tr>
<td valign="top">

<form id='cms' action='' method='post'>
Список сайтов:<br><br>
<textarea id='site_list' style='width:500px; height:300px'></textarea><br><br>
<input type='button' value='Определить' onclick='check_cms();'>     <input type='reset' value='Очистить' onclick='$("#site_list").focus();'>
</form>

<table width='100%' border='1' bordercolor='lightblue' style='BORDER-COLLAPSE: collapse; display: none;' id='show_cms' cellpadding="3"></table>

</td>
</tr>
</table>

</div>

<br>
© <a href="http://techno-c.ru/" target="_blank" title="Techno-Co - всё для веб-мастера!">Techno-Co - всё для веб-мастера!</a>

</body>
</html>


Здесь мы рисуем внешний вид. Вы можете оформить все на свой вкус style.css.

2. Создаем фаил light.js:

function check_cms() {
 var wl, kwl;

 if ($("#site_list").attr("value") == "")
    alert("Не введены сайты для проверки !");
 else {
    var url = $("#site_list").val().split(/[\n\r]+/);
    wl = url.length;
    if (wl <= 10) {

    $("#cms").fadeOut(function() {

    $("#show_cms").html("<tr bgcolor='#dfecfd'><td>Сайт</td><td>CMS</td></tr>");

    kwl=0;
    for(var i = 0; i < wl; i++){
       if ($.trim(url[i]) != "") {
        kwl++;
        $("#show_cms").append("<tr><td>"+ url[i] +"</td><td id='cms_"+ i +"'><img src='ajax-loader.gif'></td></tr>");
       }
    }
    $("#show_cms").append("<tr><td><a onclick='$(\"#show_cms\").fadeOut( function() { $(\"#cms\").fadeIn(); $(\"#site_list\").focus(); });' style='text-decoration:underline;'>к списку сайтов</a></td><td></td></tr>");

    $("#show_cms").fadeIn();

    for (var i = 0; i < wl; i++) {
       if ($.trim(url[i]) != "")
          show_cms_result(i, url[i], kwl);
    }

    });

    }
    else alert("Ограничение в 10 сайтов.");
 }

}

function show_cms_result(i, site, kwl) {
 $.post("cms.php", { url: site }, function(data) {
    $("#cms_" + i).html(data);
    if (kwl == i+1)
       alert("Определение CMS завершено.");
 });
}


Есть 2 функции.
Первая обрабатывает введенные данные (по умолчанию 10 сайтов) и подготавливает таблицу для отображения результата (картинку ajax-loader.gif найдите сами).
Вторая отсылает сайты на обработку в php файл.
Все просто.

3. Создаем фаил cms.php:

<?php

header('Content-type: text/html; charset=utf-8');

include('grab.php');

function check($html) {

$cms = array(
                "Amiro CMS" => array("/amiro_sys_css.php?","/amiro_sys_js.php?","-= Amiro.CMS © =-","Работает на Amiro.CMS"),   
                "Bitrix" => array("/bitrix/templates/", "/bitrix/js/", "/bitrix/admin/"),       
                "Concrete CMS" => array("/concrete/js/", "concrete5 - 5.","/concrete/css/"),    
                "Contao" => array("This website is powered by Contao Open Source CMS", "tl_files"),     
                "CMS Made Simple" => array("Released under the GPL - http://cmsmadesimple",),   
                "Danneo CMS" => array("Danneo Русская CMS", 'content="CMS Danneo'),     
                "DataLife Engine" => array("DataLife Engine", "/engine/", "index.php?do=lostpassword", "/engine/ajax/dle_ajax.js","/engine/opensearch.php","/index.php?do=feedback","/index.php?do=rules","/?do=lastcomments"), 
                "Drupal" => array("Drupal.settings","misc\/drupal.js","drupal_alter_by_ref","/sites/default/files/css/css_","/sites/all/files/css/css_"),       
                "Ektron" => array("EktronClientManager","Ektron.PBSettings","ektron.modal.css","Ektron/Ektron.WebForms.js","EktronSiteDataJS","/Workarea/java/ektron.js","Amend the paths to reflect the ektron system"),       
                "HostCMS" => array("/hostcmsfiles/"),   
                "InSales" => array("InSales.formatMoney", ".html(InSales.formatMoney","Insales.money_format"),  
                "InstantCMS" => array("InstantCMS",),   
                "Joomla!" => array("/css/template_css.css", "Joomla! 1.5 - Open Source Content Management", "/templates/system/css/system.css", "Joomla! - the dynamic portal engine and content management system","/templates/system/css/system.css","/media/system/js/caption.js","/templates/system/css/general.css"),      
                "Kentico" => array("CMSListMenuLI","CMSListMenuUL","Lvl2CMSListMenuLI","/CMSPages/GetResource.ashx"),   
                "LiveStreet" => array("LIVESTREET_SECURITY_KEY"),       
                "Magento" => array("cms-index-index"),  
                "MaxSite CMS" => array("/application/maxsite/shared/","/application/maxsite/templates/","/application/maxsite/common/","/application/maxsite/plugins/"),        
                "MODx" => array("/assets/styles.css", "/assets/templates/","/assets/css/lightbox.css","/assets/styles.css","/assets/js/script.js","assets/templates/design/","assets/images/","/assets/js/","/assets/components"),      
                "NetCat" => array("/netcat_template/","/netcat_files/"),        
                "OpenCart (ocStore)" => array("catalog/view/theme/default/stylesheet/stylesheet.css", "index.php?route=account/account", "index.php?route=account/login","index.php?route=account/simpleregister"),     
                "phpBB" => array("phpBB style name:", "The phpBB Group"),       
                "PrestaShop" => array("/themes/prestashop/cache/","/themes/prestashop/","Prestashop 1.5"." || Presta-Module.com",'meta name="generator" content="PrestaShop"'),         
                "Simpla CMS" => array("design/default/css/main.css","design/default/images/favicon.ico","tooltip='section' section_id="),       
                "TextPattern" => array("/textpattern/index.php"),       
                "TYPO 3" => array("This website is powered by TYPO3","typo3temp/"),     
                "uCoz" => array("cms-index-index","U1BFOOTER1Z","U1DRIGHTER1Z","U1CLEFTER1","U1AHEADER1Z","U1TRAKA1Z" ),        
                "UMI CMS" => array("umi:element-id=", "umi:field-name=","umi:method=", "umi:module="),  
                "vBulletin" => array("vbulletin_css", "vbulletin_important.css","clientscript/vbulletin_read_marker.js", "Powered by vBulletin", "Main vBulletin javascript Initialization"),   
                "WebAsyst" => array("/published/SC/","/published/publicdata/","aux_page=","auxpages_navigation","auxpage_","?show_aux_page="),  
                "Weebly" => array("Weebly.Commerce = Weebly.Commerce","Weebly.setup_rpc","editmysite.com/js/site/main.js","editmysite.com/css/sites.css","editmysite.com/editor/libraries","?show_aux_page="),  
                "Wix" => array("X-Wix-Published-Version", "X-Wix-Renderer-Server","X-Wix-Meta-Site-Id"),        
                "WordPress" => array("/wp-includes/", "/wp-content/", "/wp-admin/", "/wp-login/")
        );

        if (empty($html))
                exit('Сайт не открылся !');

        foreach ($cms as $name => $rules) {
                $c = count($rules);
                for ($i = 0; $i < $c; $i++) {
                        if (stripos($html, $rules[$i]) !== FALSE) {
                                exit($name);
                        }
                }
        }
        exit("Хрен его знает");
}

check(grab($_POST['url']));

?>

,
По сути в массиве лишь задаются правила для определения движка (их может быть несколько). Главной целью было ввести их таким образом, чтобы не пришлось каждый раз менять сам алгоритм (я лентяй, ага). Затем берется html код страницы и проверяется на вхождение этих сигнатур. В примере использовалась простейшая функция stripos, если вам нужна большая гибкость, то лучше остановиться на регулярных выражениях и preg_match.

4. Создаем фаил grab.php:

<?php

function curl_redir_exec($ch) {
        static $curl_loops = 0;
        static $curl_max_loops = 2; # Максимальное количество перебросов.
        if ($curl_loops++ >= $curl_max_loops) {
                $curl_loops = 0;
                return FALSE;
        }
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $data = curl_exec($ch);
        list($header, $data) = explode("\n\n", $data, 2);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if ($http_code == 301 || $http_code == 302) {
                $matches = array();
                preg_match('/Location:(.*?)\n/', $header, $matches);
                $url = @parse_url(trim(array_pop($matches)));
                if (!$url) {
                        $curl_loops = 0;
                        return $data;
                }
                $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
                if (!$url['scheme'])
                        $url['scheme'] = $last_url['scheme'];
                if (!$url['host'])
                        $url['host'] = $last_url['host'];
                if (!$url['path'])
                        $url['path'] = $last_url['path'];
                $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query']?'?'.$url['query']:'');
                curl_setopt($ch, CURLOPT_URL, $new_url);
                return curl_redir_exec($ch);
        } else {
                $curl_loops = 0;
                return $data;
        }
}

function grab($site) {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $site);
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_redir_exec($ch);

        $data = curl_exec($ch);

        curl_close($ch);

        if ($data)
                return $data;
        else
                return FALSE;
}

?>


Можно сказать, что здесь все стандартно, если бы не функция curl_redir_exec. Вы, наверно, догадались, что она нужна для перехода по редиректам. Минусом такого подхода будет разве что небольшое проседание по скорости. Конечно, можно было ограничиться обычным CURLOPT_FOLLOWLOCATION, но тогда пришлось бы отключать safe_mode и open_basedir, что не всем доступно и негативно скажется на безопасности.

Вот и все.

Урок подготовил Хедин

ДЕМО

Посмотреть
пример

Напишите своё мнение