Subversion Repositories Sites.tela-botanica.org

Rev

Rev 609 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 david 1
<?php
2
 
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2005                                                *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
 
13
 
14
//
15
// Ce fichier ne sera execute qu'une fois
16
if (defined("_INC_SITES")) return;
17
define("_INC_SITES", "1");
18
 
19
 
20
// Moderation manuelle des liens
21
if (!_DIR_RESTREINT AND $GLOBALS['connect_statut'] == '0minirezo') {
22
	if ($supprimer_lien = $GLOBALS["supprimer_lien"])
23
		spip_query("UPDATE spip_syndic_articles SET statut='refuse'
24
		WHERE id_syndic_article='$supprimer_lien'");
25
	if ($ajouter_lien = $GLOBALS["ajouter_lien"])
26
		spip_query("UPDATE spip_syndic_articles SET statut='publie'
27
		WHERE id_syndic_article='$ajouter_lien'");
28
}
29
 
30
// Function glue_url : le pendant de parse_url (cf doc spip.net/parse_url)
31
function glue_url ($url){
32
	if (!is_array($url)){
33
		return false;
34
	}
35
	// scheme
36
	$uri = (!empty($url['scheme'])) ? $url['scheme'].'://' : '';
37
	// user & pass
38
	if (!empty($url['user'])){
39
		$uri .= $url['user'].':'.$url['pass'].'@';
40
	}
41
	// host
42
	$uri .= $url['host'];
43
	// port
44
	$port = (!empty($url['port'])) ? ':'.$url['port'] : '';
45
	$uri .= $port;
46
	// path
47
	$uri .= $url['path'];
48
// fragment or query
49
	if (isset($url['fragment'])){
50
		$uri .= '#'.$url['fragment'];
51
	} elseif (isset($url['query'])){
52
		$uri .= '?'.$url['query'];
53
	}
54
	return $uri;
55
}
56
 
57
// Ne pas afficher la partie 'password' du proxy
58
function no_password_proxy_url($http_proxy) {
59
	if ($p = @parse_url($http_proxy)
60
	AND $p['pass']) {
61
		$p['pass'] = '****';
62
		$http_proxy = glue_url($p);
63
	}
64
	return $http_proxy;
65
}
66
 
67
//
68
// Demarre une transaction HTTP (s'arrete a la fin des entetes)
69
// retourne un descripteur de fichier
70
//
71
function init_http($get, $url) {
72
	$http_proxy = lire_meta("http_proxy");
73
	if (!eregi("^http://", $http_proxy))
74
		$http_proxy = '';
75
	else
76
		$via_proxy = " (proxy $http_proxy)";
77
 
78
	spip_log("http $get $url$via_proxy");
79
 
80
	$t = @parse_url($url);
81
	$host = $t['host'];
82
	if ($t['scheme'] == 'http') {
83
		$scheme = 'http'; $scheme_fsock='';
84
	} else {
85
		$scheme = $t['scheme']; $scheme_fsock=$scheme.'://';
86
	}
87
	if (!($port = $t['port'])) $port = 80;
88
	$query = $t['query'];
89
	if (!($path = $t['path'])) $path = "/";
90
 
91
	if ($http_proxy) {
92
		$t2 = @parse_url($http_proxy);
93
		$proxy_host = $t2['host'];
94
		$proxy_user = $t2['user'];
95
		$proxy_pass = $t2['pass'];
96
		if (!($proxy_port = $t2['port'])) $proxy_port = 80;
97
		$f = @fsockopen($proxy_host, $proxy_port);
98
	} else
99
		$f = @fsockopen($scheme_fsock.$host, $port);
100
 
101
	if ($f) {
102
		if ($http_proxy)
103
			fputs($f, "$get $scheme://$host" . (($port != 80) ? ":$port" : "") . $path . ($query ? "?$query" : "") . " HTTP/1.0\r\n");
104
		else
105
			fputs($f, "$get $path" . ($query ? "?$query" : "") . " HTTP/1.0\r\n");
106
 
107
		fputs($f, "Host: $host\r\n");
108
		fputs($f, "User-Agent: SPIP-".$GLOBALS['spip_version_affichee']." (http://www.spip.net/)\r\n");
109
 
110
		// Proxy authentifiant
111
		if ($proxy_user) {
112
			fputs($f, "Proxy-Authorization: Basic "
113
			. base64_encode($proxy_user . ":" . $proxy_pass) . "\r\n");
114
		}
115
		// Referer = c'est nous !
116
		if ($referer = lire_meta("adresse_site"))
117
			fputs($f, "Referer: $referer/\r\n");
118
 
119
		// On sait lire du gzip
120
		if ($GLOBALS['flag_gz'])
121
			fputs($f, "Accept-Encoding: gzip\r\n");
122
 
123
	}
124
	// fallback : fopen
125
	else if (!$GLOBALS['tester_proxy']) {
126
		$f = @fopen($url, "rb");
127
		$fopen = true;
128
	}
129
	// echec total
130
	else {
131
		$f = false;
132
	}
133
 
134
	return array($f, $fopen);
135
}
136
 
137
//
138
// Recupere une page sur le net
139
// et au besoin l'encode dans le charset local
140
//
141
// options : get_headers si on veut recuperer les entetes
142
// taille_max : arreter le contenu au-dela (0 = seulement les entetes)
143
// Par defaut taille_max = 1Mo.
144
function recuperer_page($url, $munge_charset=false, $get_headers=false, $taille_max = 1048576) {
145
 
146
	if ($taille_max == 0)
147
		$get = 'HEAD';
148
	else
149
		$get = 'GET';
150
 
151
 
152
	for ($i=0;$i<10;$i++) {	// dix tentatives maximum en cas d'entetes 301...
153
		list($f, $fopen) = init_http($get, $url);
154
 
155
		// si on a utilise fopen() - passer a la suite
156
		if ($fopen) {
157
			spip_log('connexion via fopen');
158
			break;
159
		} else {
160
			// Fin des entetes envoyees par SPIP
161
			fputs($f,"\r\n");
162
 
163
			// Reponse du serveur distant
164
			$s = trim(fgets($f, 16384));
165
			if (ereg('^HTTP/[0-9]+\.[0-9]+ ([0-9]+)', $s, $r)) {
166
				$status = $r[1];
167
			}
168
			else return;
169
 
170
			// Entetes HTTP de la page
171
			$headers = '';
172
			while ($s = trim(fgets($f, 16384))) {
173
				$headers .= $s."\n";
174
				if (eregi('^Location: (.*)', $s, $r)) {
175
					include_ecrire('inc_filtres.php3');
176
					$location = suivre_lien($url, $r[1]);
177
					spip_log("Location: $location");
178
				}
179
				if (preg_match(",^Content-Encoding: .*gzip,i", $s))
180
					$gz = true;
181
			}
182
			if ($status >= 300 AND $status < 400 AND $location)
183
				$url = $location;
184
			else if ($status != 200)
185
				return;
186
			else
187
				break; # ici on est content
188
			fclose($f);
189
			$f = false;
190
		}
191
	}
192
 
193
	// Contenu de la page
194
	if (!$f) {
195
		spip_log("ECHEC chargement $url");
196
		return false;
197
	}
198
 
199
	$result = '';
200
	while (!feof($f) AND strlen($result)<$taille_max)
201
		$result .= fread($f, 16384);
202
	fclose($f);
203
 
204
	// Decompresser le flux
205
	if ($gz)
206
		$result = gzinflate(substr($result,10));
207
 
208
	// Faut-il l'importer dans notre charset local ?
209
	if ($munge_charset) {
210
		include_ecrire('inc_charsets.php3');
211
		$result = transcoder_page ($result, $headers);
212
	}
213
 
214
	return ($get_headers ? $headers."\n" : '').$result;
215
}
216
 
217
// helas strtotime ne reconnait pas le format W3C
218
// http://www.w3.org/TR/NOTE-datetime
219
function my_strtotime($la_date) {
220
 
221
	$s = strtotime($la_date);
222
	if ($s > 0)
223
		return $s;
224
 
225
	if (ereg('^([0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+(:[0-9]+)?)(\.[0-9]+)?(Z|([-+][0-9][0-9]):[0-9]+)$', $la_date, $match)) {
226
		$la_date = str_replace("T", " ", $match[1])." GMT";
227
		return strtotime($la_date) - intval($match[5]) * 3600;
228
	}
229
 
230
	// erreur
231
	spip_log("Impossible de lire le format de date '$la_date'");
232
	return false;
233
}
234
 
235
 
236
function trouver_format($texte) {
237
	$syndic_version = '';
238
 
239
	// Chercher un numero de version
240
	if (ereg('(rss|feed)[[:space:]](([^>]*[[:space:]])*)version[[:space:]]*=[[:space:]]*[\'"]([-_a-zA-Z0-9\.]+)[\'"]', $texte, $regs)) {
241
		$syndic_version = $regs[4];
242
	} else {
243
		if (strpos($texte,'rdf:RDF')) {
244
			$syndic_version = '1.0';
245
		}
246
	}
247
	return $syndic_version;
248
}
249
 
250
function analyser_site($url) {
251
	include_ecrire("inc_filtres.php3"); # pour filtrer_entites()
252
 
253
	// Accepter les URLs au format feed:// ou qui ont oublie le http://
254
	$url = preg_replace(',^feed://,i', 'http://', $url);
255
	if (!preg_match(',^[a-z]+://,i', $url)) $url = 'http://'.$url;
256
 
257
	$texte = recuperer_page($url, true);
258
	if (!$texte) return false;
259
	$result = '';
260
 
261
	// definir les regexp pour decoder
262
	// il faut deux etapes pour link sous Atom0.3
263
	$syndic_version = trouver_format($texte);
264
	switch ($syndic_version) {
265
		case "1.0" :
266
			$site_regexp = array(
267
				'channel'     => '<channel[^>]*>(.*)</channel>',
268
				'link1'       => '<link[^>]*>([^<]*)</link>',
269
				'link2'       => '(.*)',
270
				'item'        => '<item[^>]*>',
271
				'description' => '<description[^>]*>([^<]*)</description>'
272
			);
273
			break;
274
		case "0.3" :
275
			$site_regexp = array(
276
				'channel'     => '<feed[^>]*>(.*)</feed>',
277
				'link1'       => '<link[[:space:]]([^<]*)rel[[:space:]]*=[[:space:]]*[\'"]alternate[\'"]([^<]*)',
278
				'link2'       => 'href[[:space:]]*=[[:space:]]*[\'"]([^["|\']]+)[\'"]',
279
				'item'        => '<entry[^>]*>',
280
				'description' => '<tagline[^>]*>([^<]*)</tagline>'
281
			);
282
			break;
283
		case "0.91" :
284
		case "0.92" :
285
		case "2.0" :
286
		default :	# backend defectueux, mais il faut une regexp
287
			$site_regexp = array(
288
				'channel'     =>'<channel[^>]*>(.*)</channel>',
289
				'link1'       => '<link[^>]*>([^<]*)</link>',
290
				'link2'       => '(.*)',
291
				'item'        => '<item[^>]*>',
292
				'description' => '<description[^>]*>([^<]*)</description>'
293
			);
294
			break;
295
	}
296
 
297
	if (ereg($site_regexp['channel'], $texte, $regs)) {
298
		$result['syndic'] = true;
299
		$result['url_syndic'] = $url;
300
		$channel = $regs[1];
301
		if (ereg('<title[^>]*>(([^<]|<[^/]|</[^t]>|</t[^i]>)*)</title>', $channel, $r))
302
			$result['nom_site'] = supprimer_tags(filtrer_entites($r[1]));
303
		if (ereg($site_regexp['link1'], $channel, $regs)) {
304
			if (ereg($site_regexp['link2'], $regs[1].$regs[2], $r))
305
				$result['url_site'] = filtrer_entites($r[1]);
306
		}
307
 
308
		// si le channel n'a pas de description, ne pas prendre celle d'un article
309
		list($channel_desc,$drop) = split($site_regexp['item'], $channel, 2);
310
		if (ereg($site_regexp['description'], $channel_desc, $r))
311
			$result['descriptif'] = filtrer_entites($r[1]);
312
	}
313
	else {
314
		$result['syndic'] = false;
315
		$result['url_site'] = $url;
316
		if (eregi('<head>(.*)', $texte, $regs))
317
			$head = filtrer_entites(eregi_replace('</head>.*', '', $regs[1]));
318
		else
319
			$head = $texte;
320
		if (eregi('<title[^>]*>(.*)', $head, $regs))
321
			$result['nom_site'] = filtrer_entites(supprimer_tags(eregi_replace('</title>.*', '', $regs[1])));
322
		if (eregi('<meta[[:space:]]+(name|http\-equiv)[[:space:]]*=[[:space:]]*[\'"]?description[\'"]?[[:space:]]+(content|value)[[:space:]]*=[[:space:]]*[\'"]([^>]+)[\'"]>', $head, $regs))
323
			$result['descriptif'] = filtrer_entites(supprimer_tags($regs[3]));
324
 
325
		// Cherchons quand meme un backend
326
		include_ecrire('feedfinder.php');
327
		$feeds = get_feed_from_url($url, $texte);
328
		if (count($feeds>1)) {
329
			spip_log("feedfinder.php :\n".join("\n", $feeds));
330
			$result['url_syndic'] = "select: ".join(' ',$feeds);
331
		} else
332
			$result['url_syndic'] = $feeds[0];
333
	}
334
	return $result;
335
}
336
 
337
// Inserer les references aux fichiers joints
338
function traiter_les_enclosures_rss($enclosures,$id_syndic,$lelien) {
339
 
340
	list($id_syndic_article) = spip_fetch_array(spip_query(
341
	"SELECT id_syndic_article FROM spip_syndic_articles
342
	WHERE id_syndic=$id_syndic AND url='$lelien'"));
343
 
344
	// Attention si cet article est deja vu, ne pas doubler les references
345
	spip_query("DELETE FROM spip_documents_syndic
346
	WHERE id_syndic_article=$id_syndic_article");
347
 
348
	// Integrer les enclosures
349
	foreach ($enclosures as $enclosure) {
350
		// url et type sont obligatoires
351
		if (preg_match(',[[:space:]]url=[\'"]?([^\'">]*),i',
352
		$enclosure, $enc_regs_url)
353
		AND preg_match(',[[:space:]]type=[\'"]?([^\'">]*),i',
354
		$enclosure, $enc_regs_type)) {
355
 
356
			$url = substr(urldecode($enc_regs_url[1]), 0,255);
357
			$url = addslashes(abs_url($url, $lelien));
358
			$type = $enc_regs_type[1];
359
 
360
			// Verifier que le content-type nous convient
361
			list($id_type) = spip_fetch_array(spip_query("SELECT id_type
362
			FROM spip_types_documents WHERE mime_type='$type'"));
363
			if (!$id_type) {
364
				spip_log("enclosure de type inconnu ($type) $url");
365
				list($id_type) = spip_fetch_array(spip_query("SELECT id_type
366
				FROM spip_types_documents WHERE extension='bin'"));
367
				// si les .bin ne sont pas autorises, on ignore ce document
368
				if (!$id_type) continue;
369
			}
370
 
371
			// length : optionnel (non bloquant)
372
			if (preg_match(',[[:space:]]length=[\'"]?([^\'"]*),i',
373
			$enclosure, $enc_regs_length)) {
374
				$taille = intval($enc_regs_length[1]);
375
			} else {
376
				$taille = 0;
377
			}
378
 
379
			// Inserer l'enclosure dans la table spip_documents
380
			if ($t = spip_fetch_array(spip_query("SELECT id_document FROM
381
			spip_documents WHERE fichier='$url' AND distant='oui'")))
382
				$id_document = $t['id_document'];
383
			else {
384
				spip_query("INSERT INTO spip_documents
385
				(id_type, titre, fichier, date, distant, taille, mode)
386
				VALUES ($id_type,'','$url',NOW(),'oui',$taille, 'document')");
387
				$id_document = spip_insert_id();
388
			}
389
 
390
			// lier avec l'article syndique
391
			spip_query("INSERT INTO spip_documents_syndic
392
			(id_document, id_syndic, id_syndic_article)
393
			VALUES ($id_document, $id_syndic, $id_syndic_article)");
394
 
395
			$n++;
396
		}
397
	}
398
 
399
	return $n; #nombre d'enclosures integrees
400
}
401
 
402
// prend un fichier backend et retourne un tableau des items lus,
403
// et une chaine en cas d'erreur
404
function analyser_backend($rss) {
405
	include_ecrire("inc_texte.php3"); # pour couper()
406
	include_ecrire("inc_filtres.php3"); # pour filtrer_entites()
407
 
408
	$les_auteurs_du_site = "";
409
 
410
	// definir les regexp pour decoder
411
	// il faut deux etapes pour link sous Atom0.3
412
	$syndic_version = trouver_format($rss);
413
	switch ($syndic_version) {
414
		case "0.91" :
415
		case "0.92" :
416
		case "2.0" :
417
			$syndic_regexp = array(
418
				'item'           => ',<item[>[:space:]],i',
419
				'itemfin'        => '</item>',
420
				'link1'          => '<link[^>]*>([^<]*)</link>',
421
				'link2'          => '(.*)',
422
				'date1'          => ',<pubDate>([^<]*)</pubDate>,Uims',
423
				'date2'          => ',<[[:alpha:]]{2}:date>([^<]*)</[[:alpha:]]{2}:date>,Uims',
424
				'author1'        => '<[[:alpha:]]{2}:[Cc]reator>([^<]*)</[[:alpha:]]{2}:[Cc]reator>',
425
				'author2'        => '(.*)',
426
				'authorbis'      => '<author>([^<]*)</author>',
427
				'description'    => ',<description[^>]*>(.*?)</description[^>]*>,ims',
428
				'descriptionbis' =>     ',<content[^>]*>(.*?)</content[^>]*>,ims'
429
			);
430
			break;
431
		case "1.0" :
432
			$syndic_regexp = array(
433
				'item'           => ',<item[>[:space:]],i',
434
				'itemfin'        => '</item>',
435
				'link1'          => '<link[^>]*>([^<]*)</link>',
436
				'link2'          => '(.*)',
437
				'date1'          => ',<[[:alpha:]]{2}:date>([^<]*)</[[:alpha:]]{2}:date>,Uims',
438
				'date2'          => ',<pubDate>([^<]*)</pubDate>,Uims',
439
				'author1'        => '<[[:alpha:]]{2}:[Cc]reator>([^<]*)</[[:alpha:]]{2}:[Cc]reator>',
440
				'author2'        => '(.*)',
441
				'authorbis'      => '<author>([^<]*)</author>',
442
				'description'    => ',<description[^>]*>(.*?)</description[^>]*>,ims',
443
				'descriptionbis' =>     ',<content[^>]*>(.*?)</content[^>]*>,ims'
444
			);
445
			break;
446
		case "0.3" :
447
			$syndic_regexp = array('channel'=>'<feed[^>]*>(.*)</feed>',
448
				'item'           => ',<entry[>[:space:]],i',
449
				'itemfin'        => '</entry>',
450
				'link1'          => '<link[[:space:]]([^<]*)rel[[:space:]]*=[[:space:]]*[\'"]alternate[\'"]([^<]*)',
451
				'link2'          => 'href[[:space:]]*=[[:space:]]*[\'"]([^"|^\']+)[\'"]',
452
				'date1'          => ',<modified>([^<]*)</modified>,Uims',
453
				'date2'          => ',<issued>([^<]*)</issued>,Uims',
454
				'author1'        => '<author>(.*<name>.*</name>.*)</author>',
455
				'author2'        => '<name>([^<]*)</name>',
456
				'authorbis'      => '<[[:alpha:]]{2}:[Cc]reator>([^<]*)</[[:alpha:]]{2}:[Cc]reator>',
457
				'description'    => ',<summary[^>]*>(.*?)</summary[^>]*>,ims',
458
				'descriptionbis' => ',<content[^>]*>(.*?)</content[^>]*>,ims'
459
			);
460
			break;
461
		default :
462
			// format de syndication non reconnu
463
			return _T('avis_echec_syndication_02');
464
	}
465
 
466
	// Echapper les CDATA
467
	$echappe_cdata = array();
468
	if (preg_match_all(',<!\[CDATA\[(.*)]]>,Uims', $rss,
469
	$regs, PREG_SET_ORDER)) {
470
		foreach ($regs as $n => $reg) {
471
			$echappe_cdata[$n] = $reg[1];
472
			$rss = str_replace($reg[0], "@@@SPIP_CDATA$n@@@", $rss);
473
		}
474
	}
475
 
476
	// chercher un auteur dans le fil au cas ou les entry n'en auraient pas
477
	list($channel_head) = preg_split($syndic_regexp['item'], $rss, 2);
478
	if (ereg($syndic_regexp['author1'],$channel_head,$mat)) {
479
		if (ereg($syndic_regexp['author2'],$mat[1],$match))
480
			$les_auteurs_du_site = $match[1];
481
	}
482
 
483
 
484
	$items = array();
485
	if (preg_match_all($syndic_regexp['item'],$rss,$r, PREG_SET_ORDER))
486
	foreach ($r as $regs) {
487
		$debut_item = strpos($rss,$regs[0]);
488
		$fin_item = strpos($rss,
489
			$syndic_regexp['itemfin'])+strlen($syndic_regexp['itemfin']);
490
		$items[] = substr($rss,$debut_item,$fin_item-$debut_item);
491
		$debut_texte = substr($rss, "0", $debut_item);
492
		$fin_texte = substr($rss, $fin_item, strlen($rss));
493
		$rss = $debut_texte.$fin_texte;
494
	}
495
 
496
	// Analyser chaque <item>...</item> du backend et le transformer en tableau
497
	if (!count($items)) return _T('avis_echec_syndication_01');
498
 
499
	foreach ($items as $item) {
500
		$data = array();
501
 
502
		// URL (obligatoire)
503
		if (ereg($syndic_regexp['link1'],$item,$match)) {
504
			$link_match = $match[1].$match[2];
505
			if (ereg($syndic_regexp['link2'], $link_match, $mat))
506
				$data['url'] = addslashes(filtrer_entites($mat[1]));
507
		}
508
		// guid n'est un URL que si marque de <guid permalink="true">
509
		else if (eregi("<guid.*>[[:space:]]*(https?:[^<]*)</guid>",$item,$match))
510
			$data['url'] = addslashes(filtrer_entites($match[1]));
511
		else
512
			$data['url'] = false;
513
 
514
		// Titre (semi-obligatoire)
515
		# note http://static.userland.com/gems/backend/gratefulDead.xml
516
		# n'a que des enclosures, sans url ni titre... tant pis...
517
		if
518
(preg_match(",<title>(.*?)</title>,ims",$item,$match))
519
			$data['titre'] = $match[1];
520
			else if (($syndic_version==0.3) AND (strlen($letitre)==0))
521
				if (preg_match(',title[[:space:]]*=[[:space:]]*([\'"])(.+?)\\1,ims',$link_match,$mat))
522
				$data['titre']=$mat[2];
523
		if (!$data['titre'] = trim($data['titre']))
524
			$data['titre'] = _T('ecrire:info_sans_titre');
525
 
526
		// Date
527
		$la_date = "";
528
		if (preg_match(",<date>([^<]*)</date>,Uims",$item,$match))
529
			$la_date = $match[1];
530
		if (preg_match($syndic_regexp['date1'],$item,$match))
531
			$la_date = $match[1];
532
		else if (preg_match($syndic_regexp['date2'],$item,$match))
533
			$la_date = $match[1];
534
		if ($la_date)
535
			$la_date = my_strtotime($la_date);
536
		if ($la_date < time() - 365 * 24 * 3600
537
		OR $la_date > time() + 48 * 3600)
538
			$la_date = time();
539
		$data['date'] = $la_date;
540
 
541
		// Auteur
542
		if (ereg($syndic_regexp['author1'],$item,$mat)) {
543
			if (ereg($syndic_regexp['author2'],$mat[1],$match))
544
				$data['lesauteurs'] = $match[1];
545
		}
546
		else if (ereg($syndic_regexp['authorbis'],$item,$match))
547
			$data['lesauteurs'] = $match[1];
548
		else
549
			$data['lesauteurs'] = $les_auteurs_du_site;
550
		// Description
551
		if (preg_match($syndic_regexp['description'],$item,$match)) {
552
			$data['descriptif'] = $match[1];
553
		}
554
		else if (preg_match($syndic_regexp['descriptionbis'],$item,$match))
555
			$data['descriptif'] = $match[1];
556
		else
557
			$data['descriptif'] = "";
558
 
559
		// Nettoyer les donnees et remettre les CDATA en place
560
		foreach ($data as $var => $val) {
561
			$data[$var] = filtrer_entites($data[$var]);
562
			foreach ($echappe_cdata as $n => $e)
563
				$data[$var] = str_replace("@@@SPIP_CDATA$n@@@",$e, $data[$var]);
564
			$data[$var] = trim(textebrut($data[$var]));
565
		}
566
 
567
		// Honorer le <lastbuilddate> en forcant la date
568
		if (preg_match(',<(lastbuilddate|modified)>([^<>]+)</\1>,i',
569
		$item, $regs)
570
		AND $lastbuilddate = my_strtotime(trim($regs[2]))
571
		// pas dans le futur
572
		AND $lastbuilddate < time())
573
			$data['lastbuilddate'] = $lastbuilddate;
574
 
575
		// Attraper les URLs des pieces jointes <enclosure>
576
		if (preg_match_all(',<enclosure[[:space:]][^<>]+>,i', $item,
577
		$preg_enclosures, PREG_SET_ORDER)) {
578
			$enclosures = array();
579
			foreach ($preg_enclosures as $e)
580
				$enclosures[] = $e[0];
581
			$data['enclosures'] = $enclosures;
582
		}
583
 
584
		$data['item'] = $item;
585
		$articles[] = $data;
586
	}
587
 
588
	return $articles;
589
}
590
 
591
//
592
// Insere un article syndique (renvoie true si l'article est nouveau)
593
//
594
function inserer_article_syndique ($data, $now_id_syndic, $statut, $url_site) {
595
 
596
	// Creer le lien s'il est nouveau - cle=(id_syndic,url)
597
	$le_lien = addslashes(substr($data['url'], 0,255));
598
	if (spip_num_rows(spip_query(
599
		"SELECT * FROM spip_syndic_articles
600
		WHERE url='$le_lien'
601
		AND id_syndic=$now_id_syndic"
602
	)) == 0 and !spip_sql_error()) {
603
		spip_query("INSERT INTO spip_syndic_articles
604
		(id_syndic, url, date, statut) VALUES
605
		('$now_id_syndic', '$le_lien',
606
		FROM_UNIXTIME(".$data['date']."), '$statut')");
607
		$ajout = true;
608
	}
609
 
610
	// Nettoyer le descriptif par une fonction personnalisee ?
611
	if (function_exists('nettoyer_descriptif_syndication')) {
612
		$data['descriptif'] = nettoyer_descriptif_syndication(
613
			$data['descriptif'], $now_id_syndic, $url_site
614
		);
615
	} else {
616
		// fonction standard
617
		$data['descriptif'] = couper($data['descriptif'], 300);
618
	}
619
 
620
	// Mise a jour du contenu (titre,auteurs,description)
621
	spip_query ("UPDATE spip_syndic_articles SET
622
	titre='".addslashes($data['titre'])."',
623
	lesauteurs='".addslashes($data['lesauteurs'])."',
624
	descriptif='".addslashes($data['descriptif'])."'
625
	WHERE id_syndic='$now_id_syndic' AND url='$le_lien'");
626
 
627
	// Mettre a jour la date si lastbuilddate
628
	if ($data['lastbuilddate'])
629
		spip_query("UPDATE spip_syndic_articles
630
		SET date = FROM_UNIXTIME(".$data['lastbuilddate'].")
631
		WHERE id_syndic='$now_id_syndic' AND url='$le_lien'");
632
 
633
	// Inserer les enclosures
634
	if ($data['enclosures']) {
635
		traiter_les_enclosures_rss($data['enclosures'],
636
			$now_id_syndic, $le_lien);
637
	}
638
 
639
	return $ajout;
640
}
641
 
642
//
643
// Mettre a jour le site
644
//
645
function syndic_a_jour($now_id_syndic, $statut = 'off') {
646
	include_ecrire("inc_texte.php3");
647
	include_ecrire("inc_filtres.php3");
648
 
649
	$query = "SELECT * FROM spip_syndic WHERE id_syndic='$now_id_syndic'";
650
	$result = spip_query($query);
651
	if (!$row = spip_fetch_array($result))
652
		return;
653
 
654
	$url_syndic = $row['url_syndic'];
655
	$url_site = $row['url_site'];
656
 
657
	if ($row['moderation'] == 'oui')
658
		$moderation = 'dispo';	// a valider
659
	else
660
		$moderation = 'publie';	// en ligne sans validation
661
 
662
	// Section critique : n'autoriser qu'une seule syndication
663
	// simultanee pour un site donne
664
	if (!spip_get_lock("syndication $url_syndic")) {
665
		spip_log("lock pour $url_syndic");
666
		return;
667
	}
668
	spip_query("UPDATE spip_syndic SET syndication='$statut',
669
		date_syndic=NOW() WHERE id_syndic='$now_id_syndic'");
670
 
671
	// Aller chercher les donnees du RSS et les analyser
672
	$rss = recuperer_page($url_syndic, true);
673
	if (!$rss)
674
		$articles = _T('avis_echec_syndication_02');
675
	else
676
		$articles = analyser_backend($rss);
677
 
678
	// Les enregistrer dans la base
679
	if (is_array($articles)) {
680
		$urls = array();
681
		foreach ($articles as $data) {
682
			if ($data['url']) {
683
				inserer_article_syndique ($data, $now_id_syndic, $moderation, $url_site);
684
				$urls[] = $data['url'];
685
			}
686
		}
687
 
688
		// moderation automatique des liens qui sont sortis du feed
689
		if (count($urls) > 0
690
		AND $row['miroir'] == 'oui') {
691
			spip_query("UPDATE spip_syndic_articles
692
				SET statut='off', maj=maj
693
				WHERE id_syndic=$now_id_syndic
694
				AND NOT (url IN ('"
695
				. join("','", array_map('addslashes',$urls))
696
				. "'))");
697
		}
698
 
699
		// suppression apres 2 mois des liens qui sont sortis du feed
700
		if (count($urls) > 0
701
		AND $row['oubli'] == 'oui') {
702
			$time = date('U') - 61*24*3600; # deux mois
703
			spip_query("DELETE FROM spip_syndic_articles
704
				WHERE id_syndic=$now_id_syndic
705
				AND UNIX_TIMESTAMP(maj) < $time
706
				AND UNIX_TIMESTAMP(date) < $time
707
				AND NOT (url IN ('"
708
				. join("','", array_map('addslashes',$urls))
709
				. "'))");
710
		}
711
 
712
 
713
		// Noter que la syndication est OK
714
		spip_query("UPDATE spip_syndic SET syndication='oui'
715
		WHERE id_syndic='$now_id_syndic'");
716
	}
717
 
718
	// Ne pas oublier de liberer le verrou
719
	spip_release_lock($url_syndic);
720
 
721
	if ($liens_ajoutes) {
722
		spip_log("Syndication: $liens_ajoutes nouveau(x) lien(s)");
723
		include_ecrire('inc_rubriques.php3');
724
		calculer_rubriques();
725
	}
726
 
727
	// Renvoyer l'erreur le cas echeant
728
	if (!is_array($articles))
729
		return $articles;
730
	else
731
		return false; # c'est bon
732
}
733
 
734
 
735
function afficher_sites($titre_table, $requete) {
736
	global $couleur_claire, $couleur_foncee, $spip_lang_left, $spip_lang_right;
737
	global $connect_id_auteur;
738
 
739
	$tranches = afficher_tranches_requete($requete, 3);
740
 
741
	if ($tranches) {
742
//		debut_cadre_relief("site-24.gif");
743
		if ($titre_table) echo "<div style='height: 12px;'></div>";
744
		echo "<div class='liste'>";
745
		bandeau_titre_boite2($titre_table, "site-24.gif", $couleur_claire, "black");
746
		echo "<table width='100%' cellpadding='2' cellspacing='0' border='0'>";
747
 
748
		echo $tranches;
749
 
750
	 	$result = spip_query($requete);
751
		$num_rows = spip_num_rows($result);
752
 
753
		$ifond = 0;
754
		$premier = true;
755
 
756
		$compteur_liste = 0;
757
		while ($row = spip_fetch_array($result)) {
758
			$vals = '';
759
			$id_syndic=$row["id_syndic"];
760
			$id_rubrique=$row["id_rubrique"];
761
			$nom_site=typo($row["nom_site"]);
762
			$url_site=$row["url_site"];
763
			$url_syndic=$row["url_syndic"];
764
			$description=propre($row["description"]);
765
			$syndication=$row["syndication"];
766
			$statut=$row["statut"];
767
			$date=$row["date"];
768
			$moderation=$row['moderation'];
769
 
770
			$tous_id[] = $id_syndic;
771
 
772
			//echo "<tr bgcolor='$couleur'>";
773
 
774
			//echo "<td class='arial2'>";
775
			$link = new Link("sites.php3?id_syndic=$id_syndic");
776
			switch ($statut) {
777
			case 'publie':
778
				if (acces_restreint_rubrique($id_rubrique))
779
					$puce = 'puce-verte-anim.gif';
780
				else
781
					$puce='puce-verte-breve.gif';
782
				$title = _T('info_site_reference');
783
				break;
784
			case 'prop':
785
				if (acces_restreint_rubrique($id_rubrique))
786
					$puce = 'puce-orange-anim.gif';
787
				else
788
					$puce='puce-orange-breve.gif';
789
				$title = _T('info_site_attente');
790
				break;
791
			case 'refuse':
792
				if (acces_restreint_rubrique($id_rubrique))
793
					$puce = 'puce-poubelle-anim.gif';
794
				else
795
					$puce='puce-poubelle-breve.gif';
796
				$title = _T('info_site_refuse');
797
				break;
798
			}
799
			if ($syndication == 'off' OR $syndication == 'sus') {
800
				$puce = 'puce-orange-anim.gif';
801
				$title = _T('info_panne_site_syndique');
802
			}
803
 
804
			$s = "<a href=\"".$link->getUrl()."\" title=\"$title\">";
805
 
806
			if ($spip_display != 1 AND $spip_display != 4 AND lire_meta('image_process') != "non") {
807
				include_ecrire("inc_logos.php3");
808
				$logo = decrire_logo("siteon$id_syndic");
809
				if ($logo) {
810
					$s.= "<div style='float: $spip_lang_right; margin-top: -2px; margin-bottom: -2px;'>"
811
					. reduire_image_logo(_DIR_IMG.$logo[0], 26, 20)
812
					. "</div>\n";
813
				}
814
			}
815
 
816
 
817
			$s .= http_img_pack($puce, $statut, "width='7' height='7' border='0'") ."&nbsp;&nbsp;";
818
 
819
			$s .= typo($nom_site);
820
 
821
			$s .= "</a> &nbsp;&nbsp; <font size='1'>[<a href='$url_site'>"._T('lien_visite_site')."</a>]</font>";
822
			$vals[] = $s;
823
 
824
			//echo "</td>";
825
 
826
			$s = "";
827
			//echo "<td class='arial1' align='right'> &nbsp;";
828
			if ($syndication == 'off' OR $syndication == 'sus') {
829
				$s .= "<font color='red'>"._T('info_probleme_grave')." </font>";
830
			}
831
			if ($syndication == "oui" or $syndication == "off" OR $syndication == 'sus'){
832
				$s .= "<font color='red'>"._T('info_syndication')."</font>";
833
			}
834
				$vals[] = $s;
835
			//echo "</td>";
836
			//echo "<td class='arial1'>";
837
			$s = "";
838
			if ($syndication == "oui" OR $syndication == "off" OR $syndication == "sus") {
839
				$result_art = spip_query("SELECT COUNT(*) FROM spip_syndic_articles WHERE id_syndic='$id_syndic'");
840
				list($total_art) = spip_fetch_array($result_art);
841
				$s .= " $total_art "._T('info_syndication_articles');
842
			} else {
843
				$s .= "&nbsp;";
844
			}
845
			$vals[] = $s;
846
			//echo "</td>";
847
			//echo "</tr></n>";
848
			$table[] = $vals;
849
		}
850
		spip_free_result($result);
851
 
852
		$largeurs = array('','','');
853
		$styles = array('arial11', 'arial1', 'arial1');
854
		afficher_liste($largeurs, $table, $styles);
855
		echo "</table>";
856
		//fin_cadre_relief();
857
		echo "</div>\n";
858
	}
859
	return $tous_id;
860
}
861
 
862
 
863
function afficher_syndic_articles($titre_table, $requete, $afficher_site = false) {
864
	global $couleur_claire;
865
	global $connect_statut;
866
	global $REQUEST_URI;
867
	global $debut_liste_sites;
868
	global $flag_editable;
869
 
870
	static $n_liste_sites;
871
	global $spip_lang_rtl, $spip_lang_right;
872
 
873
	$adresse_page = substr($REQUEST_URI, strpos($REQUEST_URI, "/ecrire")+8, strlen($REQUEST_URI));
874
	$adresse_page = ereg_replace("\&?debut\_liste\_sites\[$n_liste_sites\]\=[0-9]+","",$adresse_page);
875
	$adresse_page = ereg_replace("\&?(ajouter\_lien|supprimer_lien)\=[0-9]+","",$adresse_page);
876
 
877
	if (ereg("\?",$adresse_page)) $lien_url = "&";
878
	else $lien_url = "?";
879
 
880
	$lien_url .= "debut_liste_sites[".$n_liste_sites."]=".$debut_liste_sites[$n_liste_sites]."&";
881
 
882
	$cols = 2;
883
	if ($connect_statut == '0minirezo') $cols ++;
884
	if ($afficher_site) $cols ++;
885
 
886
	$tranches = afficher_tranches_requete($requete, $cols);
887
 
888
	if (strlen($tranches)) {
889
 
890
		if ($titre_table) echo "<div style='height: 12px;'></div>";
891
		echo "<div class='liste'>";
892
		//debut_cadre_relief("rubrique-24.gif");
893
 
894
		if ($titre_table) {
895
			bandeau_titre_boite2($titre_table, "site-24.gif", "#999999", "white");
896
		}
897
		echo "<table width=100% cellpadding=3 cellspacing=0 border=0 background=''>";
898
 
899
		echo $tranches;
900
 
901
		$result = spip_query($requete);
902
 
903
		$table = '';
904
		while ($row = spip_fetch_array($result)) {
905
			$vals = '';
906
 
907
			$id_syndic_article=$row["id_syndic_article"];
908
			$id_syndic=$row["id_syndic"];
909
			$titre=typo($row["titre"]);
910
			$url=$row["url"];
911
			$date=$row["date"];
912
			$lesauteurs=typo($row["lesauteurs"]);
913
			$statut=$row["statut"];
914
			$descriptif=propre($row["descriptif"]);
915
 
916
 
917
			if ($statut=='publie') {
918
				if (acces_restreint_rubrique($id_rubrique))
919
					$puce = 'puce-verte-anim.gif';
920
				else
921
					$puce='puce-verte.gif';
922
			}
923
			else if ($statut == "refuse") {
924
					$puce = 'puce-poubelle.gif';
925
			}
926
 
927
			else if ($statut == "dispo") { // moderation : a valider
928
					$puce = 'puce-rouge.gif';
929
			}
930
 
931
			else if ($statut == "off") { // feed d'un site en mode "miroir"
932
					$puce = 'puce-rouge-anim.gif';
933
			}
934
 
935
			$s = http_img_pack($puce, $statut, "width='7' height='7' border='0'");
936
			$vals[] = $s;
937
 
938
			$s = "<a href='$url'>$titre</a>";
939
 
940
			$date = affdate_court($date);
941
			if (strlen($lesauteurs) > 0) $date = $lesauteurs.', '.$date;
942
			$s.= " ($date)";
943
 
944
			// S'il y a des fichiers joints (enclosures), on les affiche ici
945
			if (spip_num_rows($q = spip_query("SELECT docs.* FROM spip_documents AS docs, spip_documents_syndic AS lien WHERE lien.id_syndic_article = $id_syndic_article AND lien.id_document = docs.id_document"))) {
946
				include_ecrire('inc_documents.php3');
947
				while ($t = spip_fetch_array($q)) {
948
					$t = $t['fichier'];
949
					$s .= '&nbsp;' .
950
						http_href_img($t,
951
							'attachment.gif',
952
							'height="15" width="15" border="0"',
953
							entites_html($t));
954
				}
955
			}
956
 
957
			if (strlen($descriptif) > 0) $s .= "<div class='arial1'>$descriptif</div>";
958
			$vals[] = $s;
959
 
960
			// $my_sites cache les resultats des requetes sur les sites
961
			if (!$my_sites[$id_syndic])
962
				$my_sites[$id_syndic] = spip_fetch_array(spip_query(
963
					"SELECT * FROM spip_syndic WHERE id_syndic=$id_syndic"));
964
 
965
			if ($afficher_site) {
966
				$aff = $my_sites[$id_syndic]['nom_site'];
967
				if ($my_sites[$id_syndic]['moderation'] == 'oui')
968
					$s = "<i>$aff</i>";
969
				else
970
					$s = $aff;
971
 
972
				$s = "<a href='sites.php3?id_syndic=$id_syndic'>$aff</a>";
973
 
974
				$vals[] = $s;
975
			}
976
 
977
 
978
			if ($connect_statut == '0minirezo'){
979
				if ($statut == "publie"){
980
					$s =  "[<a href='".$adresse_page.$lien_url."id_syndic=$id_syndic&supprimer_lien=$id_syndic_article'><font color='black'>"._T('info_bloquer_lien')."</font></a>]";
981
 
982
				}
983
				else if ($statut == "refuse"){
984
					$s =  "[<a href='".$adresse_page.$lien_url."id_syndic=$id_syndic&ajouter_lien=$id_syndic_article'>"._T('info_retablir_lien')."</a>]";
985
				}
986
				else if ($statut == "off"
987
				AND $my_sites[$id_syndic]['miroir'] == 'oui') {
988
					$s = '('._T('syndic_lien_obsolete').')';
989
				}
990
				else /* 'dispo' ou 'off' (dans le cas ancien site 'miroir') */
991
				{
992
					$s = "[<a href='".$adresse_page.$lien_url."id_syndic=$id_syndic&ajouter_lien=$id_syndic_article'>"._T('info_valider_lien')."</a>]";
993
				}
994
				$vals[] = $s;
995
			}
996
 
997
			$table[] = $vals;
998
		}
999
		spip_free_result($result);
1000
 
1001
 
1002
		if ($afficher_site) {
1003
			$largeurs = array(7, '', '100');
1004
			$styles = array('','arial11', 'arial1');
1005
		} else {
1006
			$largeurs = array(7, '');
1007
			$styles = array('','arial11');
1008
		}
1009
		if ($connect_statut == '0minirezo') {
1010
			$largeurs[] = '80';
1011
			$styles[] = 'arial1';
1012
		}
1013
 
1014
		afficher_liste($largeurs, $table, $styles);
1015
 
1016
		echo "</TABLE>";
1017
		//fin_cadre_relief();
1018
		echo "</div>";
1019
	}
1020
	return $tous_id;
1021
}
1022
 
1023
 
1024
//
1025
// Effectuer la syndication d'un unique site, retourne 0 si aucun a faire.
1026
//
1027
 
1028
function executer_une_syndication() {
1029
	$id_syndic = 0;
1030
 
1031
	// On va tenter un site 'sus' ou 'off' de plus de 24h, et le passer en 'off'
1032
	// s'il echoue
1033
	if ($row = spip_fetch_array(spip_query("SELECT * FROM spip_syndic WHERE syndication IN ('sus','off') AND statut='publie' AND date_syndic < DATE_SUB(NOW(), INTERVAL 24 HOUR) ORDER BY date_syndic LIMIT 0,1"))) {
1034
		$id_syndic = $row["id_syndic"];
1035
		syndic_a_jour($id_syndic, 'off');
1036
	}
1037
 
1038
	// Et un site 'oui' de plus de 2 heures, qui passe en 'sus' s'il echoue
1039
	if ($row = spip_fetch_array(spip_query("SELECT * FROM spip_syndic WHERE syndication='oui' AND statut='publie' AND date_syndic < DATE_SUB(NOW(), INTERVAL 2 HOUR) ORDER BY date_syndic LIMIT 0,1"))) {
1040
		$id_syndic = $row["id_syndic"];
1041
		syndic_a_jour($id_syndic, 'sus');
1042
	}
1043
	return $id_syndic;
1044
}
1045
 
1046
?>