source: spip-zone/_dev_/univers_spip/inc/univers_analyser.php @ 114177

Last change on this file since 114177 was 114177, checked in by marcimat@…, 2 years ago

Quelques améliorations de l’analyseur :

  • Le composed-by de mediaspip est pris en compte
  • Le terme recherché 'spip' (si on n’a pas trouvé de version) dans le contenu des pages devient plus précis (spip_in, spip_out, spip_logo) afin d’éviter de faux positifs
  • Lorsqu’on n’a rien trouvé, c’est probablement que ce n’est plus un SPIP, et pas uniquement un vieux SPIP.
File size: 9.2 KB
Line 
1<?php
2
3/**
4 * Plugin Univers SPIP
5 * (c) 2010 Cedric
6 * Distribue sous licence GPL
7 */
8
9// User agent used to load the page
10@define(
11        '_INC_DISTANT_USER_AGENT',
12        'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; fr; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9'
13);
14@define('_INC_DISTANT_VERSION_HTTP', 'HTTP/1.0');
15
16if (!defined('_ECRIRE_INC_VERSION')) {
17        return;
18}
19
20include_spip('inc/filtres');
21include_spip('inc/distant');
22include_spip('inc/meta');
23
24/**
25 * Get the complete page.
26 * Should be sub.something.tld/spip.php
27 *
28 * Some site set a cookie then redirect before everything else
29 * so we have to accept it
30 *
31 * @param string $url
32 * @param string $cookie
33 *
34 */
35function univers_recuperer_lapage($url, $cookie = '') {
36        $ref = $GLOBALS['meta']['adresse_site'];
37        // let's say we're coming from google, after all...
38        $GLOBALS['meta']['adresse_site'] = 'http://www.google.fr';
39        $datas = ''
40         ."Cookie: $cookie\r\n"
41         ."\r\n"
42        ;
43
44        $site = $url;
45        $max_redir = 10;
46        while ($site and is_string($site) and $max_redir--) {
47                $url = $site;
48                $site = recuperer_lapage($url, false, 'GET', 1048576, $datas);
49        }
50
51        $GLOBALS['meta']['adresse_site'] = $ref;
52        if (!$site) {
53                return $site;
54        }
55        if (is_string($site) and !$max_redir) {
56                return false;
57        }
58        list($header, $page) = $site;
59
60        // if a cookie set, accept it an retry with it
61        if (preg_match(',Set-Cookie: (.*)(;.*)?$,Uims', $header, $r)) {
62                //ne pas relancer si le cookie est déjà présent
63                if (strpos($cookie, $r[1])===false) {
64                        $cookie .= $r[1] . ';';
65                        spip_log("Cookie : $cookie on repart pour un tour ", 'univers_check');
66                        return univers_recuperer_lapage($url, $cookie);
67                }
68        }
69        return $site;
70}
71
72/**
73 * Get address by host.
74 * Use nslookup instead of php function
75 *
76 * @param string $host
77 * @param int $timeout
78 * @return string
79 */
80function univers_getaddrbyhost($host, $timeout = 3) {
81        $ip = gethostbyname($host);
82        if ($ip and $ip !== $host) {
83                return $ip;
84        }
85
86        if (is_callable('shell_exec') && false === stripos(ini_get('disable_functions'), 'shell_exec')) {
87                $query = `nslookup -timeout=$timeout -retry=1 $host`;
88                if (preg_match('/\nAddress: (.*)\n/', $query, $matches)) {
89                        return trim($matches[1]);
90                }
91        }
92
93        return $host;
94}
95
96/**
97 * Analyse a site to check it's made with SPIP and find versions and plugins
98 *
99 * @param string $url
100 * @param bool $debug
101 * @return boolean|array false ou un tableau de donnees
102 */
103function univers_analyser($url, $debug = false) {
104        $res = array();
105
106        spip_log("analyse version : $url ", 'univers_check');
107        $path = parse_url($url);
108        $ip = univers_getaddrbyhost($path['host']);
109        if (!$ip or $ip == $path['host']) {
110                return false;  // pas d'ip, pas de site, rien a faire
111        }
112
113        $res['ip'] = $ip;
114
115        // get the complete page
116        $site = univers_recuperer_lapage($url);
117        if (!$site) {
118                $res['response'] = false;
119                return $res;
120        }
121
122        list($header, $page) = $site;
123        if ($debug) {
124                var_dump($header);
125        }
126
127        // get some generic informations (server, php, gzip, length)
128        if (preg_match(',Server: (.*)$,m', $header, $r)) {
129                $res['server'] = $r[1];
130        }
131        if (preg_match(',X-Powered-By: PHP/(.+)$,m', $header, $r)) {
132                $res['php'] = $r[1];
133        }
134        if (preg_match(',Content-Encoding: gzip$,m', $header)) {
135                $res['gzip'] = true;
136        }
137        if (preg_match(',Content-Length: ([0-9]+)$,m', $header, $r)) {
138                $res['length'] = $r[1];
139        }
140
141        // check if the header says "Hey, i'm made with SPIP"
142        $regexp_plugin_spip = ',Composed-By: (?:.*)\+ (?<plugins>spip\((?<spip>[^)]+)\)(.*)?)$,m';
143        $regexp_generique = ',Composed-By: (?<spip>.*)( @ www.spip.net)( ?\+ ?(?<plugins>.*))?$,m';
144        if (
145                preg_match($regexp_plugin_spip, $header, $r)
146                or preg_match($regexp_generique, $header, $r)
147        ) {
148                // essayer de choper local/config.txt si il est la car plus complet si le header semble coupe
149                if (substr($header, -1)!==')') {
150                        $url_config = suivre_lien($url, 'local/config.txt');
151                        $config = univers_recuperer_lapage($url_config);
152                        if (!$config) {
153                                $url_mutu = str_replace('ww2.', '', str_replace('www.', '', $path['host']));
154                                $url_config = suivre_lien($url, "sites/$url_mutu/local/config.txt");
155                                $config = univers_recuperer_lapage($url_config);
156                        }
157                        if ($config) {
158                                if (
159                                        preg_match($regexp_plugin_spip, $config[1], $rc)
160                                        or preg_match($regexp_generique, $config[1], $rc)
161                                ) {
162                                        $r = $rc;
163                                }
164                        }
165                }
166                $res['spip'] = trim(preg_replace(',^[^0-9]*,', '', $r['spip']));
167                if (!$res['spip']) {
168                        $res['spip'] = '?';
169                }
170                $res['plugins'] = array();
171                if ($p = array_filter(explode(',', $r['plugins']))) {
172                        foreach ($p as $plugin) {
173                                $plugin = trim($plugin);
174                                $res['plugins'][preg_replace(',[(].*,', '', $plugin)] = $plugin;
175                        }
176                }
177        }
178        // else, find another clue
179        // if 'spip_' is in the html, there are some chance that it is a SPIP site
180        if (!isset($res['spip'])) {
181                if (preg_match(',spip_(in|out|logo),i', $page)) {
182                        $res['spip'] = '?';
183                }
184        }
185
186        // if maybe but not sure, try to get the login page
187        // it should have some information that says "SPIP"
188        if (isset($res['spip']) and $res['spip'] === '?') {
189                // recuperer la page de login
190                $login = preg_replace(',spip[.]php.*$,', '', $url).'ecrire/';
191                if ($login = univers_recuperer_lapage($login)) {
192                        list(, $login) = $login;
193                        if (preg_match(',<meta name=[\'"]generator["\'][^>]*>,Uims', $login, $r)
194                                and $v = extraire_attribut($r[0], 'content')
195                                and preg_match(',SPIP ([^\[]+),', $v, $r)) {
196                                $res['spip'] = trim($r[1]);
197                        }
198                }
199        }
200
201        // if we did'nt found login page, or there whas no information
202        // try to get the htaccess.txt delivered with SPIP,
203        // it has some extra informations
204        if (isset($res['spip']) and $res['spip'] === '?') {
205                // tenter de recup le htaccess.txt qui contient un numero de version
206                $ht = preg_replace(',spip[.]php.*$,', '', $url).'htaccess.txt';
207                if ($ht = univers_recuperer_lapage($ht)) {
208                        list(, $htpage) = $ht;
209                        if (preg_match(',SPIP v\s*([0-9.]+),', $htpage, $r)) {
210                                $res['spip'] = $r[1];
211                        }
212                }
213
214                // if we didn't found a confirmation and there was only 'spip' in the html
215                // maybe it's an old spip site, but it’s no more a SPIP now.
216                if ($res['spip'] === '?') {
217                        unset($res['spip']);
218                }
219        }
220
221        // if it is a 404, that was a bad adress
222        if (count($res)==1 and preg_match(',404 ,', $header)) {
223                $res['response'] = '404';
224        } else {
225                // else record the page size and so on
226                $res['size'] = strlen($page);
227                $res['response'] = true;
228                if (preg_match(',<title>(.*)</title>,Uims', $page, $r)) {
229                        $res['title'] = $r[1];
230                }
231                if (preg_match(',<meta name=[\'"]description["\'][^>]*>,Uims', $page, $r)) {
232                        $res['description'] = extraire_attribut($r[0], 'content');
233                }
234        }
235
236        return $res;
237}
238
239/**
240 * Take one record to check in database, and process it.
241 *
242 * @param      array    $row    The row
243 * @param      boolean  $debug  The debug mode for the exec web page
244 */
245function univers_analyser_un($row, $debug = false) {
246        if ($debug) {
247                var_dump($row);
248        }
249        $id = $row['id_website'];
250        $url = $row['url'];
251
252        // incrementer le retry et la date avant tout pour ne pas tourner en rond
253        // sur ce site si il timeout
254        sql_updateq(
255                'spip_websites',
256                array('retry' => $row['retry']+1, 'date' => date('Y-m-d H:i:s'), 'status' => 'timeout?'),
257                'id_website='.intval($id)
258        );
259
260        $res = univers_analyser($url, $debug);
261        if ($debug) {
262                var_dump($res);
263        }
264
265        $set = array();
266        if ($res===false) {
267                $set['retry'] = ++$row['retry'];
268                $set['status'] = 'no-dns';
269        } elseif ($res['response']===false or $res['response']==='404') {
270                $set['ip'] = $res['ip'];
271                $set['retry'] = ++$row['retry'];
272                $set['status'] = ($res['response']?$res['response']:'dead');
273        } elseif ($res['response']===true) {
274                $set['ip'] = $res['ip'];
275                $set['server'] = !empty($res['server'])?$res['server']:'';
276                $set['php'] = !empty($res['php'])?$res['php']:'';
277                $set['gzip'] = !empty($res['gzip'])?'oui':'';
278                $set['length'] = !empty($res['length'])?$res['length']:0;
279                $set['size'] = !empty($res['size'])?$res['size']:0;
280
281                if (isset($res['spip'])) {
282                        $set['pays'] = univers_geoip($set['ip']);
283
284                        // c'estun SPIP !
285                        $set['spip'] = $res['spip'];
286                        $set['statut'] = 'publie';
287                        if ($res['title']) {
288                                $set['titre'] = $res['title'];
289                        }
290                        if ($res['description']) {
291                                $set['descriptif'] = $res['description'];
292                        }
293                        $set['plugins'] = count($res['plugins']);
294                        // mettre a jour les plugins
295                        sql_delete('spip_websites_plugins', 'id_website='.intval($id));
296                        if (is_array($res['plugins'])) {
297                                foreach ($res['plugins'] as $p => $v) {
298                                        sql_insertq('spip_websites_plugins', array('id_website'=>$id,'plugin'=>$p,'version'=>$v));
299                                }
300                        }
301
302                        if ($debug) {
303                                var_dump(univers_geoip($set['ip']));
304                        }
305                } else {
306                        // c'en est pas un !
307                        $set['statut'] = 'refuse';
308                }
309                $set['status'] = '';
310                $set['retry'] = 0;
311        } else {
312                // ???
313                $set['retry'] = ++$row['retry'];
314                $set['status'] = $res['response'];
315        }
316
317        $set['date'] = date('Y-m-d H:i:s');
318        if ($debug) {
319                var_dump($set);
320        }
321        sql_updateq('spip_websites', $set, 'id_website='.intval($id));
322}
323
324/**
325 * Find state information from IP adress with GeoIP tool
326 *
327 * @staticvar string $gi
328 * @param string $ip
329 * @return string
330 */
331function univers_geoip($ip = null) {
332        static $gi = null;
333        if (is_null($ip)) {
334                include_spip('geoip/geoip');
335                geoip_close($gi);
336                return;
337        }
338        if (is_null($gi)) {
339                include_spip('geoip/geoip');
340                $gi = geoip_open(find_in_path('geoip/GeoIP.dat'), GEOIP_STANDARD);
341        }
342
343        return geoip_country_code_by_addr($gi, $ip);
344}
Note: See TracBrowser for help on using the repository browser.