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

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

Lorsqu’une page retourne une fatale, on arrête de chercher ce site à un moment donné.

File size: 9.4 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 (
229                        false !== stripos($page, 'Fatal error')
230                        and false !== stripos($page, 'Call to undefined function')
231                ) {
232                        $res['response'] = 'fatal';
233                }
234
235                if (preg_match(',<title>(.*)</title>,Uims', $page, $r)) {
236                        $res['title'] = $r[1];
237                }
238                if (preg_match(',<meta name=[\'"]description["\'][^>]*>,Uims', $page, $r)) {
239                        $res['description'] = extraire_attribut($r[0], 'content');
240                }
241        }
242
243        return $res;
244}
245
246/**
247 * Take one record to check in database, and process it.
248 *
249 * @param      array    $row    The row
250 * @param      boolean  $debug  The debug mode for the exec web page
251 */
252function univers_analyser_un($row, $debug = false) {
253        if ($debug) {
254                var_dump($row);
255        }
256        $id = $row['id_website'];
257        $url = $row['url'];
258
259        // incrementer le retry et la date avant tout pour ne pas tourner en rond
260        // sur ce site si il timeout
261        sql_updateq(
262                'spip_websites',
263                array('retry' => $row['retry']+1, 'date' => date('Y-m-d H:i:s'), 'status' => 'timeout?'),
264                'id_website='.intval($id)
265        );
266
267        $res = univers_analyser($url, $debug);
268        if ($debug) {
269                var_dump($res);
270        }
271
272        $set = array();
273        if ($res===false) {
274                $set['retry'] = ++$row['retry'];
275                $set['status'] = 'no-dns';
276        } elseif (
277                $res['response']===false
278                or $res['response']==='404'
279                or $res['response']==='fatal'
280        ) {
281                $set['ip'] = $res['ip'];
282                $set['retry'] = ++$row['retry'];
283                $set['status'] = ($res['response']?$res['response']:'dead');
284        } elseif ($res['response']===true) {
285                $set['ip'] = $res['ip'];
286                $set['server'] = !empty($res['server'])?$res['server']:'';
287                $set['php'] = !empty($res['php'])?$res['php']:'';
288                $set['gzip'] = !empty($res['gzip'])?'oui':'';
289                $set['length'] = !empty($res['length'])?$res['length']:0;
290                $set['size'] = !empty($res['size'])?$res['size']:0;
291
292                if (isset($res['spip'])) {
293                        $set['pays'] = univers_geoip($set['ip']);
294
295                        // c'estun SPIP !
296                        $set['spip'] = $res['spip'];
297                        $set['statut'] = 'publie';
298                        if ($res['title']) {
299                                $set['titre'] = $res['title'];
300                        }
301                        if ($res['description']) {
302                                $set['descriptif'] = $res['description'];
303                        }
304                        $set['plugins'] = count($res['plugins']);
305                        // mettre a jour les plugins
306                        sql_delete('spip_websites_plugins', 'id_website='.intval($id));
307                        if (is_array($res['plugins'])) {
308                                foreach ($res['plugins'] as $p => $v) {
309                                        sql_insertq('spip_websites_plugins', array('id_website'=>$id,'plugin'=>$p,'version'=>$v));
310                                }
311                        }
312
313                        if ($debug) {
314                                var_dump(univers_geoip($set['ip']));
315                        }
316                } else {
317                        // c'en est pas un !
318                        $set['statut'] = 'refuse';
319                }
320                $set['status'] = '';
321                $set['retry'] = 0;
322        } else {
323                // ???
324                $set['retry'] = ++$row['retry'];
325                $set['status'] = $res['response'];
326        }
327
328        $set['date'] = date('Y-m-d H:i:s');
329        if ($debug) {
330                var_dump($set);
331        }
332        sql_updateq('spip_websites', $set, 'id_website='.intval($id));
333}
334
335/**
336 * Find state information from IP adress with GeoIP tool
337 *
338 * @staticvar string $gi
339 * @param string $ip
340 * @return string
341 */
342function univers_geoip($ip = null) {
343        static $gi = null;
344        if (is_null($ip)) {
345                include_spip('geoip/geoip');
346                geoip_close($gi);
347                return;
348        }
349        if (is_null($gi)) {
350                include_spip('geoip/geoip');
351                $gi = geoip_open(find_in_path('geoip/GeoIP.dat'), GEOIP_STANDARD);
352        }
353
354        return geoip_country_code_by_addr($gi, $ip);
355}
Note: See TracBrowser for help on using the repository browser.