Your IP : 216.73.216.216


Current Path : /home/e/t/i/etiennec/www/f1f54/
Upload File :
Current File : /home/e/t/i/etiennec/www/f1f54/base.tar

create.php000066600000013331152502550120006522 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

include_spip('inc/acces');
include_spip('base/objets');
include_spip('base/typedoc');
include_spip('base/abstract_sql');

/**
 * Determiner le flag autoinc pour une table
 * en fonction de si c'est une table principale
 *
 * @param string $table
 * @param array $desc
 * @return bool
 */
function base_determine_autoinc($table,$desc=array()){
	if ($t=lister_tables_principales() AND isset($t[$table]))
		$autoinc = true;
	elseif ($t=lister_tables_auxiliaires() AND isset($t[$table]))
		$autoinc = false;
	else {
		// essayer de faire au mieux !
		$autoinc = (isset($desc['key']['PRIMARY KEY'])
						AND strpos($desc['key']['PRIMARY KEY'],',')===false
						AND strpos($desc['field'][$desc['key']['PRIMARY KEY']],'default')===false);
	}
	return $autoinc;
}

/**
 * Creer une table,
 * ou ajouter les champs manquants si elle existe deja
 *
 * http://doc.spip.org/@creer_ou_upgrader_table
 *
 * @param string $table
 * @param array $desc
 * @param bool|string $autoinc
 *   'auto' pour detecter automatiquement si le champ doit etre autoinc ou non
 *   en fonction de la table
 * @param bool $upgrade
 * @param string $serveur
 * @return void
 */
function creer_ou_upgrader_table($table,$desc,$autoinc,$upgrade=false,$serveur='') {
	#spip_log("creer_ou_upgrader_table table=$table autoinc=$autoinc upgrade=$upgrade","dbinstall"._LOG_INFO_IMPORTANTE);
	$sql_desc = $upgrade ? sql_showtable($table,true,$serveur) : false;
	#if (!$sql_desc) $sql_desc = false;
	#spip_log("table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
	if (!$sql_desc) {
		if ($autoinc==='auto')
			$autoinc = base_determine_autoinc($table,$desc);
		#spip_log("sql_create $table autoinc=$autoinc","dbinstall"._LOG_INFO_IMPORTANTE);
		sql_create($table, $desc['field'], $desc['key'], $autoinc, false, $serveur);
		// verifier la bonne installation de la table (php-fpm es-tu la ?)
		$sql_desc = sql_showtable($table,true,$serveur);
		#if (!$sql_desc) $sql_desc = false;
		#spip_log("Resultat table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
		if (!$sql_desc){
			// on retente avec un sleep ?
			sleep(1);
			sql_create($table, $desc['field'], $desc['key'], $autoinc, false, $serveur);
			$sql_desc = sql_showtable($table,true,$serveur);
			#if (!$sql_desc) $sql_desc = false;
			#spip_log("Resultat table=$table sql_desc:$sql_desc","dbinstall"._LOG_INFO_IMPORTANTE);
			if (!$sql_desc){
				spip_log("Echec creation table $table","maj"._LOG_CRITIQUE);
			}
		}
	}
	else {
		#spip_log("sql_alter $table ... (on s'en fiche)","dbinstall"._LOG_INFO_IMPORTANTE);
		// ajouter les champs manquants
		// on ne supprime jamais les champs, car c'est dangereux
		// c'est toujours a faire manuellement
		$last = '';
		foreach($desc['field'] as $field=>$type){
			if (!isset($sql_desc['field'][$field]))
				sql_alter("TABLE $table ADD $field $type".($last?" AFTER $last":""),$serveur);
			$last = $field;
		}
		foreach($desc['key'] as $key=>$type){
			// Ne pas oublier les cas des cles non nommees dans la declaration et qui sont retournees
			// par le showtable sous la forme d'un index de tableau "KEY $type" et non "KEY"
			if (!isset($sql_desc['key'][$key]) AND !isset($sql_desc['key']["$key $type"]))
				sql_alter("TABLE $table ADD $key ($type)",$serveur);
			$last = $field;
		}

	}
}

/**
 * Creer ou mettre a jour un ensemble de tables
 * en fonction du flag $up
 *
 * @param array $tables_inc
 *   tables avec autoincrement sur la cle primaire
 * @param  $tables_noinc
 *   tables sans autoincrement sur la cle primaire
 * @param bool|array $up
 *   upgrader (true) ou creer (false)
 *   si un tableau de table est fournie, seules l'intersection de ces tables
 *   et des $tables_inc / $tables_noinc seront traitees
 * @param string $serveur
 *   serveur sql
 * @return void
 */
function alterer_base($tables_inc, $tables_noinc, $up=false, $serveur='')
{
	if ($up === false) {
		$old = false;
		$up = array();
	} else {
		$old = true;
		if (!is_array($up)) $up = array($up);
	}
	foreach($tables_inc as $k => $v)
		if (!$old OR in_array($k, $up))
			creer_ou_upgrader_table($k,$v,true,$old,$serveur);

	foreach($tables_noinc as $k => $v)
		if (!$old OR in_array($k, $up))
			creer_ou_upgrader_table($k,$v,false,$old,$serveur);
}

/**
 * Creer une base de donnee
 * a partir des tables principales et auxiliaires
 *
 * http://doc.spip.org/@creer_base
 *
 * @param string $serveur
 * @return void
 */
function creer_base($serveur='') {

	// Note: les mises a jour reexecutent ce code pour s'assurer
	// de la conformite de la base
	// pas de panique sur  "already exists" et "duplicate entry" donc.

	alterer_base(lister_tables_principales(),
		     lister_tables_auxiliaires(),
		     false,
		     $serveur);
}

/**
 * Mettre a jour une liste de tables,
 * fonction facilitatrice utilisee pour les maj de base
 * dans les plugins
 *
 * @param array $upgrade_tables
 * @param string $serveur
 * @return void
 */
function maj_tables($upgrade_tables=array(),$serveur=''){
	alterer_base(lister_tables_principales(),
		     lister_tables_auxiliaires(),
		     $upgrade_tables,
		     $serveur);
}

?>
index.php000066600000000002152502550120006355 0ustar00X
auxiliaires.php000066600000002015152502550120007573 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Déclare la liste des tables auxiliaires
 *
 * @todo
 *     Nettoyages à faire dans le core : on ne devrait plus appeler
 *     Ce fichier mais directement base/objets si nécessaire
 *
 * @package SPIP\SQL\Tables
**/

if (!defined('_ECRIRE_INC_VERSION')) return;

include_spip('base/objets');
lister_tables_objets_sql();

?>
upgrade.php000066600000040175152502550120006714 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Programme de mise a jour des tables SQL lors d'un chgt de version.
 * L'entree dans cette fonction est reservee au maj de SPIP coeur
 *
 * Marche aussi pour les plugins en appelant directement la fonction maj_plugin
 * Pour que ceux-ci profitent aussi de la reprise sur interruption,
 * ils doivent simplement indiquer leur numero de version installee dans une meta
 * et fournir le tableau maj a la fonction maj_plugin.
 * La reprise sur timeout se fait alors par la page admin_plugin et jamais par ici
 *
 * http://doc.spip.org/@base_upgrade_dist
 *
 * @param string $titre
 * @param string $reprise
 * @return
 */
function base_upgrade_dist($titre='', $reprise='')
{
	if (!$titre) return; // anti-testeur automatique
	if ($GLOBALS['spip_version_base']!=$GLOBALS['meta']['version_installee']) {
		if (!is_numeric(_request('reinstall'))) {
			include_spip('base/create');
			spip_log("recree les tables eventuellement disparues","maj."._LOG_INFO_IMPORTANTE);
			creer_base();
		}
		
		// quand on rentre par ici, c'est toujours une mise a jour de SPIP
		// lancement de l'upgrade SPIP
		$res = maj_base();

		if ($res) {
			// on arrete tout ici !
			exit;
		}
	}
	spip_log("Fin de mise a jour SQL. Debut m-a-j acces et config","maj."._LOG_INFO_IMPORTANTE);
	
	// supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
	@spip_unlink(_CACHE_RUBRIQUES);
	@spip_unlink(_CACHE_PIPELINES);
	@spip_unlink(_CACHE_PLUGINS_PATH);
	@spip_unlink(_CACHE_PLUGINS_OPT);
	@spip_unlink(_CACHE_PLUGINS_FCT);
	@spip_unlink(_CACHE_CHEMIN);
	@spip_unlink(_DIR_TMP."plugin_xml_cache.gz");

	include_spip('inc/auth');
	auth_synchroniser_distant();
	$config = charger_fonction('config', 'inc');
	$config();
}

/**
 * MAJ de base de SPIP
 *
 * http://doc.spip.org/@maj_base
 *
 * @param int $version_cible
 * @param string $redirect
 * @return array|bool
 */
function maj_base($version_cible = 0, $redirect = '') {
	global $spip_version_base;

	$version_installee = @$GLOBALS['meta']['version_installee'];
	//
	// Si version nulle ou inexistante, c'est une nouvelle installation
	//   => ne pas passer par le processus de mise a jour.
	// De meme en cas de version superieure: ca devait etre un test,
	// il y a eu le message d'avertissement il doit savoir ce qu'il fait
	//
	// version_installee = 1.702; quand on a besoin de forcer une MAJ
	
	spip_log("Version anterieure: $version_installee. Courante: $spip_version_base","maj."._LOG_INFO_IMPORTANTE);
	if (!$version_installee OR ($spip_version_base < $version_installee)) {
		sql_replace('spip_meta', 
		      array('nom' => 'version_installee',
			    'valeur' => $spip_version_base,
			    'impt' => 'non'));
		return false;
	}
	if (!upgrade_test()) return true;
	
	$cible = ($version_cible ? $version_cible : $spip_version_base);

	if ($version_installee <= 1.926) {
		$n = floor($version_installee * 10);
		while ($n < 19) {
			$nom  = sprintf("v%03d",$n);
			$f = charger_fonction($nom, 'maj', true);
			if ($f) {
				spip_log( "$f repercute les modifications de la version " . ($n/10),"maj."._LOG_INFO_IMPORTANTE);
				$f($version_installee, $spip_version_base);
			} else spip_log( "pas de fonction pour la maj $n $nom","maj."._LOG_INFO_IMPORTANTE);
			$n++;
		}
		include_spip('maj/v019_pre193');
		v019_pre193($version_installee, $version_cible);
	}
	if ($version_installee < 2000) {
		if ($version_installee < 2)
			$version_installee = $version_installee*1000;
		include_spip('maj/v019');
	}
	if ($cible < 2)
		$cible = $cible*1000;

	include_spip('maj/svn10000');
	ksort($GLOBALS['maj']);
	$res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee','meta', $redirect, true);
	if ($res) {
		if (!is_array($res))
			spip_log("Pb d'acces SQL a la mise a jour","maj."._LOG_INFO_ERREUR);
		else {
			echo _T('avis_operation_echec') . ' ' . join(' ', $res);
			echo install_fin_html();
		}
	}
	return $res;
}

/**
 * Mise à jour d'un plugin de SPIP
 * 
 * Fonction appelée par la fonction de maj d'un plugin.
 * On lui fournit un tableau de fonctions élementaires
 * dont l'indice est la version
 * 
 * @param string $nom_meta_base_version
 *     Nom de la meta informant de la version du schéma de données du plugin installé dans SPIP
 * @param string $version_cible
 *     Version du schéma de données dans le plugin (déclaré dans paquet.xml)
 * @param array $maj
 *     Tableau d'actions à faire à l'installation (clé 'create') et pour chaque
 *     version intermédiaire entre la version actuelle du schéma du plugin dans SPIP
 *     et la version du schéma déclaré dans le plugin (ex. clé '1.1.0').
 *     
 *     Chaque valeur est un tableau contenant une liste de fonctions à exécuter,
 *     cette liste étant elle-même un tableau avec premier paramètre le nom de la fonction
 *     et les suivant les paramètres à lui passer
 *     @example
 *        array(
 *            'create' => array(
 *                array('maj_tables', array('spip_rubriques', 'spip_articles')),
 *                array('creer_base)),
 *            '1.1.0' => array(
 *                array('sql_alter', 'TABLE spip_articles ADD INDEX truc (truc)'))
 *        )
 * @param string $table_meta
 *     Nom de la table meta (sans le prefixe spip_) dans laquelle trouver la meta $nom_meta_base_version
 * @return void
 */
function maj_plugin($nom_meta_base_version, $version_cible, $maj, $table_meta='meta'){

	if ($table_meta!=='meta')
		lire_metas($table_meta);
	if ( (!isset($GLOBALS[$table_meta][$nom_meta_base_version]) )
			|| (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version],$version_cible,'='))){

		// $maj['create'] contient les directives propres a la premiere creation de base
		// c'est une operation derogatoire qui fait aboutir directement dans la version_cible
		if (isset($maj['create'])){
			if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])){
				// installation : on ne fait que l'operation create
				$maj = array("init"=>$maj['create']);
				// et on lui ajoute un appel a inc/config
				// pour creer les metas par defaut
				$config = charger_fonction('config','inc');
				$maj[$version_cible] = array(array($config));
			}
			// dans tous les cas enlever cet index du tableau
			unset($maj['create']);
		}
		// si init, deja dans le bon ordre
		if (!isset($maj['init'])){
			include_spip('inc/plugin'); // pour spip_version_compare
			uksort($maj,'spip_version_compare');
		}

		// la redirection se fait par defaut sur la page d'administration des plugins
		// sauf lorsque nous sommes sur l'installation de SPIP
		// ou define _REDIRECT_MAJ_PLUGIN
		$redirect = (defined('_REDIRECT_MAJ_PLUGIN')?_REDIRECT_MAJ_PLUGIN:generer_url_ecrire('admin_plugin'));
		if (defined('_ECRIRE_INSTALL')) {
			$redirect = parametre_url(generer_url_ecrire('install'),'etape', _request('etape'));
		}
		
		$res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
		if ($res) {
			if (!is_array($res))
				spip_log("Pb d'acces SQL a la mise a jour","maj."._LOG_INFO_ERREUR);
			else {
				echo "<p>"._T('avis_operation_echec') . ' ' . join(' ', $res)."</p>";
			}
		}
	}
}

/**
 * Relancer le hit de maj avant timeout
 * si pas de redirect fourni, on redirige vers exec=upgrade pour finir
 * ce qui doit etre une maj SPIP
 * 
 * @param string $meta
 * @param string $table
 * @param string $redirect
 * @return void
 */
function relance_maj($meta,$table,$redirect=''){
	include_spip('inc/headers');
	if (!$redirect){
		// recuperer la valeur installee en cours
		// on la tronque numeriquement, elle ne sert pas reellement
		// sauf pour verifier que ce n'est pas oui ou non
		// sinon is_numeric va echouer sur un numero de version 1.2.3
		$installee = intval($GLOBALS[$table][$meta]);
		$redirect = generer_url_ecrire('upgrade',"reinstall=$installee&meta=$meta&table=$table",true);
	}
	echo redirige_formulaire($redirect);
	exit();
}

/**
 * Initialiser la page pour l'affichage des progres de l'upgrade
 * uniquement si la page n'a pas deja ete initilalisee
 * 
 * @param string $installee
 * @param string $meta
 * @param string $table
 * @return
 */
function maj_debut_page($installee,$meta,$table){
	static $done = false;
	if ($done) return;
	include_spip('inc/minipres');
	@ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure
	$timeout = _UPGRADE_TIME_OUT*2;
	$titre = _T('titre_page_upgrade');
	$balise_img = charger_filtre('balise_img');
	$titre .= $balise_img(chemin_image('searching.gif'));
	echo ( install_debut_html($titre));
	// script de rechargement auto sur timeout
	$redirect = generer_url_ecrire('upgrade',"reinstall=$installee&meta=$meta&table=$table",true);
	echo http_script("window.setTimeout('location.href=\"".$redirect."\";',".($timeout*1000).")");
	echo "<div style='text-align: left'>\n";
	ob_flush();flush();
	$done = true;
}

define('_UPGRADE_TIME_OUT', 20);

/**
 * A partir des > 1.926 (i.e SPIP > 1.9.2), cette fonction gere les MAJ.
 * Se relancer soi-meme pour eviter l'interruption pendant une operation SQL
 * (qu'on espere pas trop longue chacune)
 * evidemment en ecrivant dans la meta a quel numero on en est.
 *
 * Cette fonction peut servir aux plugins qui doivent donner comme arguments:
 * 1. le numero de version courant (numero de version 1.2.3 ou entier)
 * 2. le numero de version a atteindre (numero de version 1.2.3 ou entier)
 * 3. le tableau des instructions de mise a jour a executer
 * Pour profiter du mecanisme de reprise sur interruption il faut de plus
 * 4. le nom de la meta permettant de retrouver tout ca
 * 5. la table des meta ou elle se trouve ($table_prefix . '_meta' par defaut)
 * (cf debut de fichier)
 * en cas d'echec, cette fonction retourne un tableau (etape,sous-etape)
 * sinon elle retourne un tableau vide
 *
 * les fonctions sql_xx appelees lors des maj sont supposees atomiques et ne sont pas relancees
 * en cas de timeout
 * mais les fonctions specifiques sont relancees jusqu'a ce qu'elles finissent
 * elles doivent donc s'assurer de progresser a chaque reprise
 *
 * http://doc.spip.org/@maj_while
 *
 * @param  $installee
 * @param  $cible
 * @param  $maj
 * @param string $meta
 * @param string $table
 * @param string $redirect
 * @param bool $debut_page
 * @return array
 */
function maj_while($installee, $cible, $maj, $meta='', $table='meta', $redirect='', $debut_page = false)
{
	# inclusions pour que les procedures d'upgrade disposent des fonctions de base
	include_spip('base/create');
	include_spip('base/abstract_sql');
	$trouver_table = charger_fonction('trouver_table','base');
	include_spip('inc/plugin'); // pour spip_version_compare
	$n = 0;
	$time = time();
	// definir le timeout qui peut etre utilise dans les fonctions
	// de maj qui durent trop longtemps
	define('_TIME_OUT',$time+_UPGRADE_TIME_OUT);

	reset($maj);
	while (list($v,)=each($maj)) {
		// si une maj pour cette version
		if ($v=='init' OR
			(spip_version_compare($v,$installee,'>')
			AND spip_version_compare($v,$cible,'<='))) {
			if ($debut_page)
				maj_debut_page($v,$meta,$table);
			echo "MAJ $v";
			$etape = serie_alter($v, $maj[$v], $meta, $table, $redirect);
			$trouver_table(''); // vider le cache des descriptions de table
			# echec sur une etape en cours ?
			# on sort
			if ($etape) return array($v, $etape);
			$n = time() - $time;
			spip_log( "$table $meta: $v en $n secondes",'maj.'._LOG_INFO_IMPORTANTE);
			if ($meta) ecrire_meta($meta, $installee=$v,'oui', $table);
			echo "<br />";
		}
		if (time() >= _TIME_OUT) {
			relance_maj($meta,$table,$redirect);
		}
	}
	$trouver_table(''); // vider le cache des descriptions de table
	// indispensable pour les chgt de versions qui n'ecrivent pas en base
	// tant pis pour la redondance eventuelle avec ci-dessus
	if ($meta) ecrire_meta($meta, $cible,'oui',$table);
	spip_log( "MAJ terminee. $meta: $installee",'maj.'._LOG_INFO_IMPORTANTE);
	return array();
}

/**
 * Appliquer une serie de chgt qui risquent de partir en timeout
 * (Alter cree une copie temporaire d'une table, c'est lourd)
 *
 * http://doc.spip.org/@serie_alter
 *
 * @param string $serie
 *   numero de version upgrade
 * @param array $q
 *   tableau des operations pour cette version
 * @param string $meta
 *   nom de la meta qui contient le numero de version
 * @param string $table
 *   nom de la table meta
 * @param string $redirect
 *   url de redirection en cas d'interruption
 * @return int
 */
function serie_alter($serie, $q = array(), $meta='', $table='meta', $redirect='') {
	$meta2 = $meta . '_maj_' . $serie;
	$etape = intval(@$GLOBALS[$table][$meta2]);
	foreach ($q as $i => $r) {
		if ($i >= $etape) {
			$msg = "maj $table $meta2 etape $i";
			if (is_array($r)
			  AND function_exists($f = array_shift($r))) {
				spip_log( "$msg: $f " . join(',',$r),'maj.'._LOG_INFO_IMPORTANTE);
				// pour les fonctions atomiques sql_xx
				// on enregistre le meta avant de lancer la fonction,
				// de maniere a eviter de boucler sur timeout
				// mais pour les fonctions complexes,
				// il faut les rejouer jusqu'a achevement.
				// C'est a elle d'assurer qu'elles progressent a chaque rappel
				if (strncmp($f,"sql_",4)==0)
					ecrire_meta($meta2, $i+1, 'non', $table);
				echo " <span title='$i'>.</span>";
				call_user_func_array($f, $r);
				// si temps imparti depasse, on relance sans ecrire en meta
				// car on est peut etre sorti sur timeout si c'est une fonction longue
				if (time() >= _TIME_OUT) {
					relance_maj($meta,$table,$redirect);
				}
				ecrire_meta($meta2, $i+1, 'non', $table);
				spip_log( "$meta2: ok", 'maj.'._LOG_INFO_IMPORTANTE);
			}
			else {
				if (!is_array($r))
					spip_log("maj $i format incorrect","maj."._LOG_ERREUR);
				else
					spip_log("maj $i fonction $f non definie","maj."._LOG_ERREUR);
				// en cas d'erreur serieuse, on s'arrete
				// mais on permet de passer par dessus en rechargeant la page.
				return $i+1;
			}
		}
	}
	effacer_meta($meta2, $table);
	return 0;
}



// La fonction a appeler dans le tableau global $maj 
// quand on rajoute des types MIME. cf par exemple la 1.953

// http://doc.spip.org/@upgrade_types_documents
function upgrade_types_documents() {
	if (include_spip('base/medias')
	AND function_exists('creer_base_types_doc'))
		creer_base_types_doc();
}

// http://doc.spip.org/@upgrade_test
function upgrade_test() {
	sql_drop_table("spip_test", true);
	sql_create("spip_test", array('a' => 'int'));
	sql_alter("TABLE spip_test ADD b INT");
	sql_insertq('spip_test', array('b' => 1), array('field'=>array('b' => 'int')));
	$result = sql_select('b', "spip_test");
	// ne pas garder le resultat de la requete sinon sqlite3 
	// ne peut pas supprimer la table spip_test lors du sql_alter qui suit
	// car cette table serait alors 'verouillee'
	$result = $result?true:false; 
	sql_alter("TABLE spip_test DROP b");
	return $result;
}

// pour versions <= 1.926
// http://doc.spip.org/@maj_version
function maj_version ($version, $test = true) {
	if ($test) {
		if ($version>=1.922)
			ecrire_meta('version_installee', $version, 'oui');
		else {
			// on le fait manuellement, car ecrire_meta utilise le champs impt qui est absent sur les vieilles versions
			$GLOBALS['meta']['version_installee'] = $version;
			sql_updateq('spip_meta',  array('valeur' => $version), "nom=" . sql_quote('version_installee') );
		}
		spip_log( "mise a jour de la base en $version","maj."._LOG_INFO_IMPORTANTE);
	} else {
		echo _T('alerte_maj_impossible', array('version' => $version));
		exit;
	}
}

// pour versions <= 1.926
// http://doc.spip.org/@upgrade_vers
function upgrade_vers($version, $version_installee, $version_cible = 0){
	return ($version_installee<$version
		AND (($version_cible>=$version) OR ($version_cible==0))
	);
}
?>
repair.php000066600000007474152502550120006554 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

// http://doc.spip.org/@base_admin_repair_dist
function base_repair_dist($titre='', $reprise='') {

	$res = admin_repair_tables();
	if (!$res) {
		$res = "<div class='error'>"._T('avis_erreur_mysql').' '.sql_errno().': '.sql_error() ."</div>\n";
	} else {
		include_spip('inc/rubriques');
		calculer_rubriques();
		propager_les_secteurs();
	}
	include_spip('inc/minipres');
	$res .= pipeline('base_admin_repair',$res);
	echo minipres(_T('texte_tentative_recuperation'),
	$res . generer_form_ecrire('accueil', '','',_T('public:accueil_site')));
}

// http://doc.spip.org/@admin_repair_plat
function admin_repair_plat(){
	spip_log( "verification des documents joints", _LOG_INFO_IMPORTANTE);
	$out = "";
	$repertoire = array();
	include_spip('inc/getdocument');
	$res = sql_select('*','spip_documents',"fichier REGEXP CONCAT('^',extension,'[^/\]') AND distant='non'");

	while ($row=sql_fetch($res)){
		$ext = $row['extension'];
		if (!$ext) {
			spip_log("document sans extension: " . $row['id_document'], _LOG_INFO_IMPORTANTE);
			continue;
		}
		if (!isset($repertoire[$ext])){
			if (@file_exists($plat = _DIR_IMG. $ext .".plat"))
				spip_unlink($plat);
			$repertoire[$ext] = creer_repertoire_documents($ext);
			if (preg_match(',_$,',$repertoire[$ext]))
				$repertoire[$ext] = false;
		}
		if ($d=$repertoire[$ext]){
			$d = substr($d,strlen(_DIR_IMG));
			$src = $row['fichier'];
			$dest = $d . substr($src,strlen($d));
			if (@copy(_DIR_IMG . $src, _DIR_IMG . $dest)
			  AND file_exists(_DIR_IMG . $dest)) {
				sql_updateq('spip_documents',array('fichier'=>$dest),'id_document='.intval($row['id_document']));
				spip_unlink(_DIR_IMG . $src);
				$out .= "$src => $dest<br />";
			}
		}
	}

	return $out;
}

// http://doc.spip.org/@admin_repair_tables
function admin_repair_tables() {

	$repair = sql_repair('repair', NULL, 'continue');

	// recreer les tables manquantes eventuelles
	include_spip('base/create');
	creer_base();

	$connexion = $GLOBALS['connexions'][0];
	$prefixe = $connexion['prefixe'];
	$res1 = sql_showbase();
	$res = "";
	if ($res1) {
		while ($r = sql_fetch($res1)) {
			$tab = array_shift($r);

			$class = "";
			$m = "<strong>$tab</strong> ";
			spip_log("Repare $tab", _LOG_INFO_IMPORTANTE);
			// supprimer la meta avant de lancer la reparation
			// car le repair peut etre long ; on ne veut pas boucler
			effacer_meta('admin_repair');
			if ($repair){
				$result_repair = sql_repair($tab);
				if (!$result_repair) return false;
			}

			// essayer de maj la table (creation de champs manquants)
			maj_tables($tab);

			$count = sql_countsel($tab);
	
			if ($count>1)
				$m .= "("._T('texte_compte_elements', array('count' => $count)).")\n";
			else if ($count==1)
				$m .= "("._T('texte_compte_element', array('count' => $count)).")\n";
			else
				$m .= "("._T('texte_vide').")\n";
	
			if ($result_repair
			  AND $msg = join(" ", sql_fetch($result_repair)) . ' '
				AND strpos($msg, ' OK ')==FALSE){
				$class = " class='notice'";
				$m .= "<br /><tt>".spip_htmlentities($msg)."</tt>\n";
			}
			else
				$m .= " "._T('texte_table_ok');

			$res .="<div$class>$m</div>";
	  }
	}
	return $res;
}
?>
dump.php000066600000061404152502550120006230 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 *
 * Fonctions de base pour la sauvegarde
 * Boite a outil commune, sans prejuger de la methode de sauvegarde
 *
 */

if (!defined('_ECRIRE_INC_VERSION')) return;

define('_VERSION_ARCHIVE', '1.3');

include_spip('base/serial');
include_spip('base/auxiliaires');
include_spip('public/interfaces'); // pour table_jointures

// NB: Ce fichier peut ajouter des tables (old-style)
// donc il faut l'inclure "en globals"
if ($f = find_in_path('mes_fonctions.php')) {
	global $dossier_squelettes;
	@include_once (_ROOT_CWD . $f);
}

if (@is_readable(_CACHE_PLUGINS_FCT)){
	// chargement optimise precompile
	include_once(_CACHE_PLUGINS_FCT);
}

function base_dump_meta_name($rub){
	return $meta = "status_dump_{$rub}_"  . abs($GLOBALS['visiteur_session']['id_auteur']);
}
function base_dump_dir($meta){
	include_spip('inc/documents');
	// determine upload va aussi initialiser l'index "restreint"
	$maindir = determine_upload();
	if (!$GLOBALS['visiteur_session']['restreint'])
		$maindir = _DIR_DUMP;
	$dir = sous_repertoire($maindir, $meta);
	return $dir;
}

/**
 * Lister toutes les tables d'un serveur
 * en excluant eventuellement une liste fournie
 *
 * @param string $serveur
 * @param array $tables
 * @param array $exclude
 * @param bool $affiche_vrai_prefixe
 * @return array
 */
function base_lister_toutes_tables($serveur='', $tables=array(), $exclude = array(),$affiche_vrai_prefixe=false) {
	spip_connect($serveur);
	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
	$prefixe = $connexion['prefixe'];

	$p = '/^' . $prefixe . '/';
	$res = $tables;
	foreach(sql_alltable(null,$serveur) as $t) {
		if (preg_match($p, $t)) {
			$t1 = preg_replace($p, 'spip', $t);
			if (!in_array($t1, $tables) AND !in_array($t1, $exclude))
				$res[]= ($affiche_vrai_prefixe?$t:$t1);
		}
	}
	sort($res);
	return $res;
}

/**
 * Retrouver le prefixe des tables
 * @param string $serveur
 * @return string
 */
function base_prefixe_tables($serveur=''){
	spip_connect($serveur);
	$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
	$prefixe = $connexion['prefixe'];
	return $prefixe;
}


/**
 * Fabrique la liste a cocher des tables a traiter (copie, delete, sauvegarde)
 *
 * @param string $name
 * @param array $tables
 * @param array $exclude
 * @param array|null $post
 * @param string $serveur
 * @return array
 */
function base_saisie_tables($name, $tables, $exclude = array(), $post=null, $serveur='') {
	include_spip('inc/filtres');
	$res = array();
	foreach ($tables as $k => $t) {
		// par defaut tout est coche sauf les tables dans $exclude
		if (is_null($post))
			$check = (in_array($t,$exclude)?false:true);
		// mais si on a poste une selection, la reprendre
		else
			$check = in_array($t,$post);

		$res[$k] = "<input type='checkbox' value='$t' name='$name"
			. "[]' id='$name$k'"
			. ($check ? " checked='checked'" : '')
			. "/>\n"
			. "<label for='$name$k'>".$t."</label>"
			. " ("
			. sinon(singulier_ou_pluriel(sql_countsel($t,'','','',$serveur), 'dump:une_donnee', 'dump:nb_donnees'),_T('dump:aucune_donnee'))
	  		. ")";
	}
	return $res;
}


/**
 * Lister les tables non exportables par defaut
 * (liste completable par le pipeline lister_tables_noexport
 *
 * @staticvar array $EXPORT_tables_noexport
 * @return array
 */
function lister_tables_noexport(){
	// par defaut tout est exporte sauf les tables ci-dessous
	static $EXPORT_tables_noexport = null;
	if (!is_null($EXPORT_tables_noexport))
		return $EXPORT_tables_noexport;

	$EXPORT_tables_noexport= array(
		'spip_caches', // plugin invalideur
		'spip_resultats', // resultats de recherche ... c'est un cache !
		'spip_test', // c'est un test !
		#'spip_referers',
		#'spip_referers_articles',
		#'spip_visites',
		#'spip_visites_articles',
		#'spip_versions',
		#'spip_versions_fragments'
		);

	$EXPORT_tables_noexport = pipeline('lister_tables_noexport',$EXPORT_tables_noexport);
	return $EXPORT_tables_noexport;
}

/**
 * Lister les tables non importables par defaut
 * (liste completable par le pipeline lister_tables_noimport
 *
 * @staticvar array $IMPORT_tables_noimport
 * @return array
 */
function lister_tables_noimport(){
	static $IMPORT_tables_noimport=null;
	if (!is_null($IMPORT_tables_noimport))
		return $IMPORT_tables_noimport;

	$IMPORT_tables_noimport = array();
	// par defaut tout est importe sauf les tables ci-dessous
	// possibiliter de definir cela tables via la meta
	// compatibilite
	if (isset($GLOBALS['meta']['IMPORT_tables_noimport'])){
		$IMPORT_tables_noimport = unserialize($GLOBALS['meta']['IMPORT_tables_noimport']);
		if (!is_array($IMPORT_tables_noimport)){
			include_spip('inc/meta');
			effacer_meta('IMPORT_tables_noimport');
		}
	}
	$IMPORT_tables_noimport = pipeline('lister_tables_noimport',$IMPORT_tables_noimport);
	return $IMPORT_tables_noimport;
}


/**
 * Lister les tables a ne pas effacer
 * (liste completable par le pipeline lister_tables_noerase
 *
 * @staticvar array $IMPORT_tables_noerase
 * @return array
 */
function lister_tables_noerase(){
	static $IMPORT_tables_noerase=null;
	if (!is_null($IMPORT_tables_noerase))
		return $IMPORT_tables_noerase;

	$IMPORT_tables_noerase = array(
		'spip_meta',
		// par defaut on ne vide pas les stats, car elles ne figurent pas dans les dump
		// et le cas echeant, un bouton dans l'admin permet de les vider a la main...
		'spip_referers',
		'spip_referers_articles',
		'spip_visites',
		'spip_visites_articles'
	);
	$IMPORT_tables_noerase = pipeline('lister_tables_noerase',$IMPORT_tables_noerase);
	return $IMPORT_tables_noerase;
}


/**
 * construction de la liste des tables pour le dump :
 * toutes les tables principales
 * + toutes les tables auxiliaires hors relations
 * + les tables relations dont les deux tables liees sont dans la liste
 *
 * @param array $exclude_tables
 * @return array
 */
function base_liste_table_for_dump($exclude_tables = array()){
	$tables_for_dump = array();
	$tables_pointees = array();
	$tables = array();
	$tables_principales = $GLOBALS['tables_principales'];
	$tables_auxiliaires = $GLOBALS['tables_auxiliaires'];
	$tables_jointures = $GLOBALS['tables_jointures'];

	if (include_spip('base/objets')
		AND function_exists('lister_tables_objets_sql')){
		$tables = lister_tables_objets_sql();
		foreach($tables as $t=>$infos){
			if ($infos['principale'] AND !isset($tables_principales[$t]))
				$tables_principales[$t] = true;
			if (!$infos['principale'] AND !isset($tables_auxiliaires[$t]))
				$tables_auxiliaires[$t] = true;
			if (count($infos['tables_jointures']))
				$tables_jointures[$t] = array_merge(isset($tables_jointures[$t])?$tables_jointures[$t]:array(),$infos['tables_jointures']);
		}
	}

	// on construit un index des tables de liens
	// pour les ajouter SI les deux tables qu'ils connectent sont sauvegardees
	$tables_for_link = array();
	foreach($tables_jointures as $table => $liste_relations)
		if (is_array($liste_relations))
		{
			$nom = $table;
			if (!isset($tables_auxiliaires[$nom])&&!isset($tables_principales[$nom]))
				$nom = "spip_$table";
			if (isset($tables_auxiliaires[$nom])||isset($tables_principales[$nom])){
				foreach($liste_relations as $link_table){
					if (isset($tables_auxiliaires[$link_table])/*||isset($tables_principales[$link_table])*/){
						$tables_for_link[$link_table][] = $nom;
					}
					else if (isset($tables_auxiliaires["spip_$link_table"])/*||isset($tables_principales["spip_$link_table"])*/){
						$tables_for_link["spip_$link_table"][] = $nom;
					}
				}
			}
		}

	$liste_tables = array_merge(array_keys($tables_principales),array_keys($tables_auxiliaires),array_keys($tables));
	foreach($liste_tables as $table){
	  //		$name = preg_replace("{^spip_}","",$table);
	  if (		!isset($tables_pointees[$table])
	  		&&	!in_array($table,$exclude_tables)
	  		&&	!isset($tables_for_link[$table])){
			$tables_for_dump[] = $table;
			$tables_pointees[$table] = 1;
		}
	}
	foreach ($tables_for_link as $link_table =>$liste){
		$connecte = true;
		foreach($liste as $connect_table)
			if (!in_array($connect_table,$tables_for_dump))
				$connecte = false;
		if ($connecte)
			# on ajoute les liaisons en premier
			# si une restauration est interrompue,
			# cela se verra mieux si il manque des objets
			# que des liens
			array_unshift($tables_for_dump,$link_table);
	}
	return array($tables_for_dump, $tables_for_link);
}

/**
 * Vider les tables de la base de destination
 * pour la copie dans une base
 *
 * peut etre utilise pour l'import depuis xml,
 * ou la copie de base a base (mysql<->sqlite par exemple)
 *
 * @param array $tables
 * @param array $exclure_tables
 * @param string $serveur
 */
function base_vider_tables_destination_copie($tables, $exclure_tables = array(), $serveur=''){
	$trouver_table = charger_fonction('trouver_table', 'base');

	spip_log('Vider '.count($tables) . " tables sur serveur '$serveur' : " . join(', ', $tables),'base.'._LOG_INFO_IMPORTANTE);
	foreach($tables as $table){
		if (!in_array($table,$exclure_tables)){
			// sur le serveur principal, il ne faut pas supprimer l'auteur loge !
			if (($table!='spip_auteurs') OR $serveur!=''){
				// regarder si il y a au moins un champ impt='non'
				$desc = $trouver_table($table,$serveur);
				if (isset($desc['field']['impt'])){
					sql_delete($table, "impt='oui'", $serveur);
				}
				else{
					sql_delete($table, "", $serveur);
				}
			}
		}
	}

	// sur le serveur principal, il ne faut pas supprimer l'auteur loge !
	// Bidouille pour garder l'acces admin actuel pendant toute la restauration
	if ($serveur==''
	  AND in_array('spip_auteurs',$tables)
	  AND !in_array('spip_auteurs',$exclure_tables)) {
		base_conserver_copieur(true, $serveur);
		sql_delete("spip_auteurs", "id_auteur>0",$serveur);
	}
}

/**
 * Conserver le copieur si besoin
 * @param bool $move
 * @param string $serveur
 * @return void
 */
function base_conserver_copieur($move = true,$serveur=''){
	// s'asurer qu'on a pas deja fait la manip !
	if ($GLOBALS['visiteur_session']['id_auteur']>0 AND sql_countsel("spip_auteurs", "id_auteur>0")) {
		spip_log('Conserver copieur '.$GLOBALS['visiteur_statut']['id_auteur'] . " dans id_auteur=".$GLOBALS['visiteur_statut']['id_auteur']." pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
		sql_delete("spip_auteurs", "id_auteur<0",$serveur);
		if ($move){
			sql_updateq('spip_auteurs', array('id_auteur'=>-$GLOBALS['visiteur_session']['id_auteur']), "id_auteur=".intval($GLOBALS['visiteur_session']['id_auteur']),array(),$serveur);
		}
		else {
			$row = sql_fetsel('*','spip_auteurs','id_auteur='.$GLOBALS['visiteur_session']['id_auteur'],'','','','',$serveur);
			$row['id_auteur'] = -$GLOBALS['visiteur_session']['id_auteur'];
			sql_insertq('spip_auteurs',$row,array(),$serveur);
		}
	}
}

/**
 * Effacement de la bidouille ci-dessus
 * Toutefois si la table des auteurs ne contient plus qu'elle
 * c'est que la copie etait incomplete et on restaure le compte
 * pour garder la connection au site
 *
 * (mais il doit pas etre bien beau
 * et ca ne marche que si l'id_auteur est sur moins de 3 chiffres)
 *
 * @param string $serveur
 */
function base_detruire_copieur_si_besoin($serveur='')
{
	// rien a faire si ce n'est pas le serveur principal !
	if ($serveur=='') {
		if (sql_countsel("spip_auteurs", "id_auteur>0")) {
			spip_log("Detruire copieur id_auteur<0 pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
			sql_delete("spip_auteurs", "id_auteur<0", $serveur);
		}
		else {
			spip_log( "Restaurer copieur id_auteur<0 pour le serveur '$serveur' (aucun autre auteur en base)",'dump.'._LOG_INFO_IMPORTANTE);
			sql_update('spip_auteurs', array('id_auteur'=>'-id_auteur'), "id_auteur<0");
		}
	}
	else
		spip_log("Pas de destruction copieur sur serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE);
}

/**
 * Preparer la table dans la base de destination :
 * la droper si elle existe (sauf si auteurs ou meta sur le serveur principal)
 * la creer si necessaire, ou ajouter simplement les champs manquants
 *
 * @param string $table
 * @param array $desc
 * @param string $serveur_dest
 * @param bool $init
 * @return array
 */
function base_preparer_table_dest($table, $desc, $serveur_dest, $init=false) {
	$upgrade = false;
	// si la table existe et qu'on est a l'init, la dropper
	if ($desc_dest=sql_showtable($table,true,$serveur_dest) AND $init) {
		if ($serveur_dest=='' AND in_array($table,array('spip_meta','spip_auteurs'))) {
			// ne pas dropper auteurs et meta sur le serveur principal
			// faire un simple upgrade a la place
			// pour ajouter les champs manquants
			$upgrade = true;
			// coherence avec le drop sur les autres tables
			base_vider_tables_destination_copie(array($table),array(),$serveur_dest);
			if ($table=='spip_meta'){
				// virer les version base qui vont venir avec l'import
				sql_delete($table, "nom like '%_base_version'",$serveur_dest);
				// hum casse la base si pas version_installee a l'import ...
				sql_delete($table, "nom='version_installee'",$serveur_dest);
			}
		}
		else {
			sql_drop_table($table, '', $serveur_dest);
			spip_log( "drop table '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);
		}
		$desc_dest = false;
	}
	// si la table n'existe pas dans la destination, la creer a l'identique !
	if (!$desc_dest) {
		spip_log( "creation '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);
		include_spip('base/create');
		creer_ou_upgrader_table($table, $desc, 'auto', $upgrade,$serveur_dest);
		$desc_dest = sql_showtable($table,true,$serveur_dest);
	}
	if (!$desc_dest){
		spip_log( "Erreur creation '$table' sur serveur '$serveur_dest'".var_export($desc,1),'dump.'._LOG_ERREUR);
	}

	return $desc_dest;
}

/**
 * Copier de base a base
 *
 * @param string $status_file
 *   nom avec chemin complet du fichier ou est stocke le status courant
 * @param array $tables
 *   liste des tables a copier
 * @param string $serveur_source
 * @param string $serveur_dest
 * @param array $options
 *   parametres optionnels sous forme de tableau :
 *   param string $callback_progression
 *     fonction a appeler pour afficher la progression, avec les arguments (compteur,total,table)
 *   param int $max_time
 *     limite de temps au dela de laquelle sortir de la fonction proprement (de la forme time()+15)
 *   param bool $drop_source
 *     vider les tables sources apres copie
 *   param array $no_erase_dest
 *     liste des tables a ne pas vider systematiquement (ne seront videes que si existent dans la base source)
 *   param array $where
 *     liste optionnelle de condition where de selection des donnees pour chaque table
 *   param string $racine_fonctions_dest
 *     racine utilisee pour charger_fonction() des operations elementaires sur la base de destination.
 *     Permet de deleguer vers une autre voie de communication.
 *     Par defaut on utilise 'base', ce qui route vers les fonctions de ce fichier. Concerne :
 *     - vider_tables_destination_copie
 *     - preparer_table_dest
 *     - detruire_copieur_si_besoin
 *     - inserer_copie
 *   param array $fonction_base_inserer
 *     fonction d'insertion en base. Par defaut "inserer_copie" qui fait un insertq a l'identique.
 *     Attention, la fonction appelee est prefixee par $racine_fonctions_dest via un charger_fonction()
 *     Peut etre personalisee pour filtrer, renumeroter....
 *   param array $desc_tables_dest
 *     description des tables de destination a utiliser de preference a la description de la table source
 *   param int data_pool
 *     nombre de ko de donnees a envoyer d'un coup en insertion dans la table cible (par defaut 1)
 *     permet des envois groupes pour plus de rapidite, notamment si l'insertion est distante
 *
 * @return bool
 */
function base_copier_tables($status_file, $tables, $serveur_source, $serveur_dest, $options=array()){

	$callback_progression = isset($options['callback_progression'])?$options['callback_progression']:'';
	$max_time = isset($options['max_time'])?$options['max_time']:0;
	$drop_source = isset($options['drop_source'])?$options['drop_source']:false;
	$no_erase_dest = isset($options['no_erase_dest'])?$options['no_erase_dest']:array();
	$where = isset($options['where'])?$options['where']:array();
	$fonction_base_inserer = isset($options['fonction_base_inserer'])?$options['fonction_base_inserer']:'inserer_copie';
	$desc_tables_dest = isset($options['desc_tables_dest'])?$options['desc_tables_dest']:array();
	$racine_fonctions = (isset($options['racine_fonctions_dest'])?$options['racine_fonctions_dest']:'base');
	$data_pool = (isset($options['data_pool'])?$options['data_pool']:50*1024);

	spip_log( "Copier ".count($tables)." tables de '$serveur_source' vers '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE);

	if (!$inserer_copie = charger_fonction($fonction_base_inserer,$racine_fonctions, true)) {
		spip_log( "Fonction '{$racine_fonctions}_$fonction_base_inserer' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
		return true; // echec mais on a fini, donc true
	}
	if (!$preparer_table_dest = charger_fonction('preparer_table_dest',$racine_fonctions, true)) {
		spip_log( "Fonction '{$racine_fonctions}_$preparer_table_dest' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
		return true; // echec mais on a fini, donc true
	}

	if (!lire_fichier($status_file, $status)
		OR !$status = unserialize($status))
		$status = array();
	$status['etape'] = 'basecopie';

	// puis relister les tables a importer
	// et les vider si besoin, au moment du premier passage ici
	$initialisation_copie = (!isset($status["dump_status_copie"])) ? 0 : $status["dump_status_copie"];

	// si init pas encore faite, vider les tables du serveur destination
	if (!$initialisation_copie) {
		if (!$vider_tables_destination_copie = charger_fonction('vider_tables_destination_copie',$racine_fonctions, true)) {
			spip_log( "Fonction '{$racine_fonctions}_vider_tables_destination_copie' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE);
			return true; // echec mais on a fini, donc true
		}
		$vider_tables_destination_copie($tables, $no_erase_dest, $serveur_dest);
		$status["dump_status_copie"]='ok';
		ecrire_fichier($status_file,serialize($status));
	}

	// les tables auteurs et meta doivent etre copiees en dernier !
	if (in_array('spip_auteurs',$tables)){
		$tables = array_diff($tables,array('spip_auteurs'));
		$tables[] = 'spip_auteurs';
	}
	if (in_array('spip_meta',$tables)){
		$tables = array_diff($tables,array('spip_meta'));
		$tables[] = 'spip_meta';
	}
	spip_log( "Tables a copier :".implode(", ",$tables),'dump.'._LOG_INFO);

	$trouver_table = charger_fonction('trouver_table','base');

	foreach ($tables as $table){
		// si table commence par spip_ c'est une table SPIP, renommer le prefixe si besoin
		// sinon chercher la vraie table
		$desc_source = false;
		if (strncmp($table,"spip_",5)==0){
			$desc_source = $trouver_table(preg_replace(",^spip_,","",$table), $serveur_source, true);
		}
		if (!$desc_source OR !isset($desc_source['exist']) OR !$desc_source['exist'])
			$desc_source = $trouver_table($table, $serveur_source, false);

		// verifier que la table est presente dans la base source
		if ($desc_source){
			// $status['tables_copiees'][$table] contient l'avancement
			// de la copie pour la $table : 0 a N et -N quand elle est finie (-1 si vide et finie...)
			if (!isset($status['tables_copiees'][$table]))
				$status['tables_copiees'][$table] = 0;

			if (is_numeric($status['tables_copiees'][$table])
				AND $status['tables_copiees'][$table]>=0
				AND $desc_dest = $preparer_table_dest(
								$table,
								isset($desc_tables_dest[$table])?$desc_tables_dest[$table]:$desc_source,
								$serveur_dest,
								$status['tables_copiees'][$table] == 0)){
				if ($callback_progression)
					$callback_progression($status['tables_copiees'][$table],0,$table);
				while (true) {
					$n = intval($status['tables_copiees'][$table]);
					// on copie par lot de 400
					$res = sql_select('*',$table,isset($where[$table])?$where[$table]:'','','',"$n,400",'',$serveur_source);
					while ($row = sql_fetch($res,$serveur_source)){
						$rows = array($row);
						// lire un groupe de donnees si demande en option
						// (permet un envoi par lot vers la destination)
						if ($data_pool>0){
							$s = strlen(serialize($row));
							while ($s<$data_pool AND $row = sql_fetch($res,$serveur_source)){
								$s += strlen(serialize($row));
								$rows[]= $row;
							}
						}
						// si l'enregistrement est deja en base, ca fera un echec ou un doublon
						// mais si ca renvoie false c'est une erreur fatale => abandon
						if ($inserer_copie($table,$rows,$desc_dest,$serveur_dest)===false) {
							// forcer la sortie, charge a l'appelant de gerer l'echec
							spip_log("Erreur fatale dans $inserer_copie table $table","dump"._LOG_ERREUR);
							$status['errors'][] = "Erreur fatale  lors de la copie de la table $table";
							ecrire_fichier($status_file,serialize($status));
							// copie finie
							return true;
						}
						$status['tables_copiees'][$table]+=count($rows);
						if ($max_time AND time()>$max_time)
							break;
					}
					if ($n == $status['tables_copiees'][$table])
						break;
					spip_log( "recopie $table ".$status['tables_copiees'][$table],'dump.'._LOG_INFO_IMPORTANTE);
					if ($callback_progression)
						$callback_progression($status['tables_copiees'][$table],0,$table);
					ecrire_fichier($status_file,serialize($status));
					if ($max_time AND time()>$max_time)
						return false; // on a pas fini, mais le temps imparti est ecoule
				}
				if ($drop_source) {
					sql_drop_table($table,'',$serveur_source);
					spip_log( "drop $table sur serveur source '$serveur_source'",'dump.'._LOG_INFO_IMPORTANTE);
				}
				$status['tables_copiees'][$table]=($status['tables_copiees'][$table]?-$status['tables_copiees'][$table]:"zero");
				ecrire_fichier($status_file,serialize($status));
				spip_log( "tables_recopiees ".implode(',',$status['tables_copiees']),'dump.'._LOG_INFO);
				if ($callback_progression)
					$callback_progression($status['tables_copiees'][$table],$status['tables_copiees'][$table],$table);
			}
			else {
				if ($status['tables_copiees'][$table]<0)
					spip_log("Table $table deja copiee : ".$status['tables_copiees'][$table],"dump."._LOG_INFO);
				if ($callback_progression)
					$callback_progression(0,$status['tables_copiees'][$table],"$table".((is_numeric($status['tables_copiees'][$table]) AND $status['tables_copiees'][$table]>=0)?"[Echec]":""));
			}
		}
		else {
			$status['errors'][] = "Impossible de lire la description de la table $table";
			ecrire_fichier($status_file,serialize($status));
			spip_log("Impossible de lire la description de la table $table","dump."._LOG_ERREUR);
		}
	}

	// si le nombre de tables envoyees n'est pas egal au nombre de tables demandees
	// abandonner
	if (count($status['tables_copiees'])<count($tables)){
		spip_log("Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables),"dump."._LOG_ERREUR);
		$status['errors'][] = "Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables);
		ecrire_fichier($status_file,serialize($status));
	}

	if ($detruire_copieur_si_besoin = charger_fonction('detruire_copieur_si_besoin',$racine_fonctions, true)) {
		$detruire_copieur_si_besoin($serveur_dest);
	}
	else {
		spip_log( "Fonction '{$racine_fonctions}_detruire_copieur_si_besoin' inconnue.",'dump.'._LOG_INFO_IMPORTANTE);
	}

	// OK, copie complete
	return true;
}

/**
 * fonction d'insertion en base lors de la copie de base a base
 *
 * @param string $table
 * @param array $rows
 * @param array $desc_dest
 * @param string $serveur_dest
 * @return int/bool
 */
function base_inserer_copie($table,$rows,$desc_dest,$serveur_dest){

	// verifier le nombre d'insertion
	$nb1 = sql_countsel($table,'','','',$serveur_dest);
	// si l'enregistrement est deja en base, ca fera un echec ou un doublon
	$r = sql_insertq_multi($table,$rows,$desc_dest,$serveur_dest);
	$nb = sql_countsel($table,'','','',$serveur_dest);
	if ($nb-$nb1<count($rows)){
		spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows).". On retente 1 par 1","dump"._LOG_INFO_IMPORTANTE);
		foreach($rows as $row){
			// si l'enregistrement est deja en base, ca fera un echec ou un doublon
			$r = sql_insertq($table,$row,$desc_dest,$serveur_dest);
		}
		// on reverifie le total
		$r = 0;
		$nb = sql_countsel($table,'','','',$serveur_dest);
		if ($nb-$nb1<count($rows)){
			spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows)." apres insertion 1 par 1","dump"._LOG_ERREUR);
			$r = false;
		}
	}
	return $r;
}
?>
serial.php000066600000002015152502550120006533 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Déclare la liste des tables principales
 *
 * @todo
 *     Nettoyages à faire dans le core : on ne devrait plus appeler
 *     Ce fichier mais directement base/objets si nécessaire
 *
 * @package SPIP\SQL\Tables
**/

if (!defined('_ECRIRE_INC_VERSION')) return;

include_spip('base/objets');
lister_tables_objets_sql();

?>
connect_sql.php000066600000030612152502550120007570 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('base/objets');

//
// Utilitaires indispensables autour des serveurs SQL
//

// API d'appel aux bases de donnees:
// on charge le fichier config/$serveur ($serveur='connect' pour le principal)
// qui est cense initaliser la connexion en appelant spip_connect_db
// laquelle met dans la globale db_ok la description de la connexion
// On la memorise dans un tableau pour permettre plusieurs serveurs.
// A l'installation, il faut simuler l'existence de ce fichier

// http://doc.spip.org/@spip_connect
function spip_connect($serveur='', $version='') {
	global $connexions, $spip_sql_version;

	$serveur = !is_string($serveur) ? '' : strtolower($serveur);
	$index = $serveur ? $serveur : 0;
	if (!$version) $version = $spip_sql_version;
	if (isset($connexions[$index][$version])) return $connexions[$index];

	include_spip('base/abstract_sql');
	$install = (_request('exec') == 'install');

	// Premiere connexion ?
	if (!($old = isset($connexions[$index]))) {
		$f = (!preg_match('/^[\w\.]*$/', $serveur))
		? '' // nom de serveur mal ecrit
		: ($serveur ?
		   ( _DIR_CONNECT. $serveur . '.php') // serveur externe
		    : (_FILE_CONNECT ? _FILE_CONNECT // serveur principal ok
		       : ($install ? _FILE_CONNECT_TMP // init du serveur principal
			 : ''))); // installation pas faite

		unset($GLOBALS['db_ok']);
		unset($GLOBALS['spip_connect_version']);
		if ($f) { 
			if (is_readable($f)) { 
				include($f);
			} elseif ($serveur AND !$install) {
				// chercher une declaration de serveur dans le path
				// qui pourra un jour servir a declarer des bases sqlite
				// par des plugins. Et sert aussi aux boucles POUR.
				find_in_path("$serveur.php",'connect/',true);
			}
		}
		if (!isset($GLOBALS['db_ok'])) {
		  // fera mieux la prochaine fois
			if ($install) return false;
			if ($f AND is_readable($f))
				spip_log("spip_connect: fichier de connexion '$f' OK.", _LOG_INFO_IMPORTANTE);
			else
				spip_log("spip_connect: fichier de connexion '$f' non trouve", _LOG_INFO_IMPORTANTE);
			spip_log("spip_connect: echec connexion ou serveur $index mal defini dans '$f'.", _LOG_HS);
			// ne plus reessayer si ce n'est pas l'install
			return $connexions[$index]=false;
		}
		$connexions[$index] = $GLOBALS['db_ok'];
	}
	// si la connexion a deja ete tentee mais a echoue, le dire!
	if (!$connexions[$index]) return false;

	// la connexion a reussi ou etait deja faite.
	// chargement de la version du jeu de fonctions
	// si pas dans le fichier par defaut
	$type = $GLOBALS['db_ok']['type'];
	$jeu = 'spip_' . $type .'_functions_' . $version;
	if (!isset($GLOBALS[$jeu])) {
		if (!find_in_path($type . '_' . $version . '.php', 'req/', true)){
		  spip_log("spip_connect: serveur $index version '$version' non defini pour '$type'", _LOG_HS);
			// ne plus reessayer
			return $connexions[$index][$version] = array();
		}
	}
	$connexions[$index][$version] = $GLOBALS[$jeu];
	if ($old) return $connexions[$index];

	$connexions[$index]['spip_connect_version'] = isset($GLOBALS['spip_connect_version']) ? $GLOBALS['spip_connect_version'] : 0;

	// initialisation de l'alphabet utilise dans les connexions SQL
	// si l'installation l'a determine.
	// Celui du serveur principal l'impose aux serveurs secondaires
	// s'ils le connaissent

	if (!$serveur) {
		$charset = spip_connect_main($GLOBALS[$jeu]);
		if (!$charset) {
			unset($connexions[$index]);
			spip_log("spip_connect: absence de charset", _LOG_AVERTISSEMENT);
			return false;
		}
	} else	{
		// spip_meta n'existe pas toujours dans la base
		// C'est le cas d'un dump sqlite par exemple 
		if ($connexions[$index]['spip_connect_version']
		AND sql_showtable('spip_meta', true, $serveur)
		AND $r = sql_getfetsel('valeur', 'spip_meta', "nom='charset_sql_connexion'",'','','','',$serveur))
			$charset = $r;
		else $charset = -1;
	}
	if ($charset != -1) {
		$f = $GLOBALS[$jeu]['set_charset'];
		if (function_exists($f))
			$f($charset, $serveur);
	}
	return $connexions[$index];
}

function spip_sql_erreur($serveur='')
{
	$connexion = spip_connect($serveur);
	$e = sql_errno($serveur);
	$t = (isset($connexion['type']) ? $connexion['type'] : 'sql');
	$m = "Erreur $e de $t: " . sql_error($serveur) . "\n" . $connexion['last'];
	$f = $t . $serveur;
	spip_log($m, $f.'.'._LOG_ERREUR);
}

// Cette fonction ne doit etre appelee qu'a travers la fonction sql_serveur
// definie dans base/abstract_sql
// Elle existe en tant que gestionnaire de versions,
// connue seulement des convertisseurs automatiques

// http://doc.spip.org/@spip_connect_sql
function spip_connect_sql($version, $ins='', $serveur='', $cont=false) {
	$desc = spip_connect($serveur, $version);
	if (function_exists($f = @$desc[$version][$ins])) return $f;
	if ($cont) return $desc;
	if ($ins)
		spip_log("Le serveur '$serveur' version $version n'a pas '$ins'", _LOG_ERREUR);
	include_spip('inc/minipres');
	echo minipres(_T('info_travaux_titre'), _T('titre_probleme_technique'));
	exit;
}

/**
 * Fonction appelee par le fichier cree dans config/ a l'instal'.
 * Il contient un appel direct a cette fonction avec comme arguments
 * les identifants de connexion.
 * Si la connexion reussit, la globale db_ok memorise sa description.
 * C'est un tableau egalement retourne en valeur, pour les appels a l'install'
 *
 * http://doc.spip.org/@spip_connect_db
 *
 * @param string $host
 * @param string $port
 * @param string $login
 * @param string $pass
 * @param string $db
 * @param string $type
 * @param string $prefixe
 * @param string $auth
 * @return array
 */
function spip_connect_db($host, $port, $login, $pass, $db='', $type='mysql', $prefixe='', $auth='') {
	global $db_ok;

	// temps avant nouvelle tentative de connexion
	// suite a une connection echouee
	if (!defined('_CONNECT_RETRY_DELAY'))
		define('_CONNECT_RETRY_DELAY',30);

	$f = "";
	// un fichier de identifiant par combinaison (type,host,port,db)
	// pour ne pas declarer tout indisponible d'un coup
	// si en cours d'installation ou si db=@test@ on ne pose rien
	// car c'est un test de connexion
	if (!defined('_ECRIRE_INSTALL') AND !$db=="@test@")
		$f = _DIR_TMP . $type . '.' . substr(md5($host.$port.$db),0,8) . '.out';
	elseif ($db=='@test@')
		$db = '';

	if ($f
		AND @file_exists($f)
	  AND (time() - @filemtime($f) < _CONNECT_RETRY_DELAY)) {
		spip_log( "Echec : $f recent. Pas de tentative de connexion", _LOG_HS);
		return;
	}

	if (!$prefixe)
		$prefixe = isset($GLOBALS['table_prefix'])
		? $GLOBALS['table_prefix'] : $db;
	$h = charger_fonction($type, 'req', true);
	if (!$h) {
		spip_log( "les requetes $type ne sont pas fournies", _LOG_HS);
		return;
	}
	if ($g = $h($host, $port, $login, $pass, $db, $prefixe)) {

		if (!is_array($auth)) {
			// compatibilite version 0.7 initiale
			$g['ldap'] = $auth;
			$auth = array('ldap' => $auth);
		}
		$g['authentification'] = $auth;
		$g['type'] = $type;
		return $db_ok = $g;
	}
	// En cas d'indisponibilite du serveur, eviter de le bombarder
	if ($f) {
		@touch($f);
		spip_log( "Echec connexion serveur $type : host[$host] port[$port] login[$login] base[$db]", $type.'.'._LOG_HS);
	}
}

// Premiere connexion au serveur principal:
// retourner le charset donnee par la table principale
// mais verifier que le fichier de connexion n'est pas trop vieux
// Version courante = 0.7 
// La version 0.7 indique un serveur d'authentification comme 8e arg
// La version 0.6 indique le prefixe comme 7e arg
// La version 0.5 indique le serveur comme 6e arg
//
// La version 0.0 (non numerotee) doit etre refaite par un admin
// les autres fonctionnent toujours, meme si :
// - la version 0.1 est moins performante que la 0.2
// - la 0.2 fait un include_ecrire('inc_db_mysql.php3').

// http://doc.spip.org/@spip_connect_main
function spip_connect_main($connexion)
{
	if ($GLOBALS['spip_connect_version']< 0.1 AND _DIR_RESTREINT){
		include_spip('inc/headers');
		redirige_url_ecrire('upgrade', 'reinstall=oui');
	}

	if (!($f = $connexion['select'])) return false;
	// en cas d'erreur select retourne la requette (is_string=true donc)
	if (!$r = $f('valeur','spip_meta', "nom='charset_sql_connexion'")
	  OR is_string($r))
		return false;
	if (!($f = $connexion['fetch'])) return false;
	$r = $f($r);
	return ($r['valeur'] ? $r['valeur'] : -1);
}

// compatibilite
function spip_connect_ldap($serveur='') {
	include_spip('auth/ldap');
	return auth_ldap_connect($serveur);
}

// Echappement d'une valeur (num, string, array) sous forme de chaine PHP
// pour un array(1,'a',"a'") renvoie la chaine "'1','a','a\''"
// Usage sql un peu deprecie, a remplacer par sql_quote()
// http://doc.spip.org/@_q
function _q ($a) {
	return (is_numeric($a)) ? strval($a) :
		(!is_array($a) ? ("'" . addslashes($a) . "'")
		 : join(",", array_map('_q', $a)));
}


// Recuperer le nom de la table de jointure xxxx sur l'objet yyyy
// http://doc.spip.org/@table_jointure
function table_jointure($x, $y) {
	$trouver_table = charger_fonction('trouver_table', 'base');
	$xdesc = $trouver_table(table_objet($x));
	$ydesc = $trouver_table(table_objet($y));
	$ix = @$xdesc['key']["PRIMARY KEY"];
	$iy = @$ydesc['key']["PRIMARY KEY"];
	if ($table = $ydesc['tables_jointures'][$ix]) return $table;
	if ($table = $xdesc['tables_jointures'][$iy]) return $table;
	return '';
}

/**
 * Echapper les textes entre ' ' ou " " d'une requete SQL
 * avant son pre-traitement
 * On renvoi la query sans textes et les textes separes, dans
 * leur ordre d'apparition dans la query
 *
 * @param string $query
 * @return array
 */
function query_echappe_textes($query){
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
	$query = str_replace(array_keys($codeEchappements), array_values($codeEchappements), $query);
	if (preg_match_all("/((['])[^']*(\\2))|(([\"])[^\"]*(\\5))/S",$query,$textes)){
		$textes = reset($textes); // indice 0 du match
		switch(count($textes)){
			case 0:$replace=array();break;
			case 1:$replace=array('%1$s');break;
			case 2:$replace=array('%1$s','%2$s');break;
			case 3:$replace=array('%1$s','%2$s','%3$s');break;
			case 4:$replace=array('%1$s','%2$s','%3$s','%4$s');break;
			case 5:$replace=array('%1$s','%2$s','%3$s','%4$s','%5$s');break;
			default:
				$replace = range(1,count($textes));
				$replace = '%'.implode('$s,%',$replace).'$s';
				$replace = explode(',',$replace);
				break;
		}
		$query = str_replace($textes,$replace,$query);
	}
	else
		$textes = array();

	return array($query, $textes);
}

/**
 * Reinjecter les textes d'une requete SQL a leur place initiale,
 * apres traitement de la requete
 *
 * @param string $query
 * @param array $textes
 * @return string
 */
function query_reinjecte_textes($query, $textes){
	static $codeEchappements = array("''"=>"\x1@##@\x1", "\'"=>"\x2@##@\x2", "\\\""=>"\x3@##@\x3");
	# debug de la substitution
	#if (($c1=substr_count($query,"%"))!=($c2=count($textes))){
	#	spip_log("$c1 ::". $query,"tradquery"._LOG_ERREUR);
	#	spip_log("$c2 ::". var_export($textes,1),"tradquery"._LOG_ERREUR);
	#	spip_log("ini ::". $qi,"tradquery"._LOG_ERREUR);
	#}
	switch (count($textes)){
		case 0:break;
		case 1:$query=sprintf($query,$textes[0]);break;
		case 2:$query=sprintf($query,$textes[0],$textes[1]);break;
		case 3:$query=sprintf($query,$textes[0],$textes[1],$textes[2]);break;
		case 4:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3]);break;
		case 5:$query=sprintf($query,$textes[0],$textes[1],$textes[2],$textes[3],$textes[4]);break;
		default:
			array_unshift($textes,$query);
			$query = call_user_func_array('sprintf',$textes);
			break;
	}

	$query = str_replace(array_values($codeEchappements), array_keys($codeEchappements), $query);

	return $query;
}

// Pour compatibilite. Ne plus utiliser.
// http://doc.spip.org/@spip_query
function spip_query($query, $serveur='') {
	global $spip_sql_version;
	$f = spip_connect_sql($spip_sql_version, 'query', $serveur, true);
	return function_exists($f) ? $f($query, $serveur) : false;
}

?>
abstract_sql.php000066600000123577152502550120007757 0ustar00<?php

/* *************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Definition de l'API SQL
 * 
 * Ce fichier definit la couche d'abstraction entre SPIP et ses serveurs SQL.
 * Cette version 1 est un ensemble de fonctions ecrites rapidement
 * pour generaliser le code strictement MySQL de SPIP <= 1.9.2
 * Des retouches sont a prevoir apres l'experience des premiers portages.
 * Les symboles sql_* (constantes et nom de fonctions) sont reserves
 * a cette interface, sans quoi le gestionnaire de version dysfonctionnera.
 *
 * @package SPIP\SQL\API
 * @version 1
 */

if (!defined('_ECRIRE_INC_VERSION')) return;

/** Version de l'API SQL */
define('sql_ABSTRACT_VERSION', 1);
include_spip('base/connect_sql');



/**
 * Charge le serveur de base de donnees
 * 
 * Fonction principale. Elle charge l'interface au serveur de base de donnees
 * via la fonction spip_connect_version qui etablira la connexion au besoin.
 * Elle retourne la fonction produisant la requete SQL demandee
 * Erreur fatale si la fonctionnalite est absente sauf si le 3e arg <> false
 *
 * @internal Cette fonction de base est appelee par les autres fonctions sql_*
 * @param string $ins_sql
 * 		Instruction de l'API SQL demandee (insertq, update, select...)
 * @param string $serveur
 * 		Nom du connecteur ('' pour celui par defaut a l'installation de SPIP)
 * @param bool $continue
 * 		true pour ne pas generer d'erreur si le serveur SQL ne dispose pas de la fonction demandee
 * @return string|array
 * 		Nom de la fonction a appeler pour l'instruction demandee pour le type de serveur SQL correspondant au fichier de connexion.
 * 		Si l'instruction demandee n'existe pas, retourne la liste de toutes les instructions du serveur SQL avec $continue a true.
 * 
**/
function sql_serveur($ins_sql='', $serveur='', $continue=false) {
	static $sql_serveur = array();
	if (!isset($sql_serveur[$serveur][$ins_sql])){
		$f = spip_connect_sql(sql_ABSTRACT_VERSION, $ins_sql, $serveur, $continue);
		if (!is_string($f) OR !$f) return $f;
		$sql_serveur[$serveur][$ins_sql] = $f;
	}
	return $sql_serveur[$serveur][$ins_sql];
}

/**
 * Demande si un charset est disponible
 *
 * Demande si un charset (tel que utf-8) est disponible
 * sur le gestionnaire de base de donnees de la connexion utilisee
 *
 * @api
 * @see sql_set_charset() pour utiliser un charset
 * 
 * @param string $charset
 * 		Le charset souhaite
 * @param string $serveur
 * 		Le nom du connecteur
 * @param bool $option
 * 		Inutilise
 * @return string|bool
 * 		Retourne le nom du charset si effectivement trouve, sinon false.
**/
function sql_get_charset($charset, $serveur='', $option=true){
  // le nom http du charset differe parfois du nom SQL utf-8 ==> utf8 etc.
	$desc = sql_serveur('', $serveur, true,true);
	$desc = $desc[sql_ABSTRACT_VERSION];
	$c = $desc['charsets'][$charset];
	if ($c) {
		if (function_exists($f=@$desc['get_charset'])) 
			if ($f($c, $serveur, $option!==false)) return $c;
	}
	spip_log( "SPIP ne connait pas les Charsets disponibles sur le serveur $serveur. Le serveur choisira seul.", _LOG_AVERTISSEMENT);
	return false;
}


/**
 * Regler le codage de connexion
 *
 * Affecte un charset (tel que utf-8) sur la connexion utilisee
 * avec le gestionnaire de base de donnees
 *
 * @api
 * @see sql_get_charset() pour tester l'utilisation d'un charset
 * 
 * @param string $charset
 * 		Le charset souhaite
 * @param string $serveur
 * 		Le nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true pour executer la requete.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 * 
 * @return bool
 * 		Retourne true si elle reussie.
**/
function sql_set_charset($charset,$serveur='', $option=true){
	$f = sql_serveur('set_charset', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($charset, $serveur, $option!==false);
}



/**
 * Effectue une requete de selection
 * 
 * Fonction de selection (SELECT), retournant la ressource interrogeable par sql_fetch.
 *
 * @api
 * @see sql_fetch()      Pour boucler sur les resultats de cette fonction
 * 
 * @param array|string $select
 * 		Liste des champs a recuperer (Select)
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array|string $orderby
 * 		Tableau de classement (Order By)
 * @param string $limit
 * 		Critere de limite (Limit)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- false -> ne pas l'executer mais la retourner, 
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible,
 * 		- true|array -> executer la requete.
 * 		Le cas array est, pour une requete produite par le compilateur,
 * 		un tableau donnnant le contexte afin d'indiquer le lieu de l'erreur au besoin
 *
 * 
 * @return mixed
 * 		Ressource SQL
 * 		- Ressource SQL pour sql_fetch, si la requete est correcte
 * 		- false en cas d'erreur
 * 		- Chaine contenant la requete avec $option=false
 * 
 * Retourne false en cas d'erreur, apres l'avoir denoncee.
 * Les portages doivent retourner la requete elle-meme en cas d'erreur,
 * afin de disposer du texte brut.
 *
**/
function sql_select ($select = array(), $from = array(), $where = array(),
	$groupby = array(), $orderby = array(), $limit = '', $having = array(),
	$serveur='', $option=true) {
	$f = sql_serveur('select', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;

	$debug = (defined('_VAR_MODE') AND _VAR_MODE == 'debug');
	if (($option !== false) AND !$debug) {
		$res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, is_array($option) ? true : $option);
	} else {
		$query = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
		if (!$option) return $query;
		// le debug, c'est pour ce qui a ete produit par le compilateur
		if (isset($GLOBALS['debug']['aucasou'])) {
			list($table, $id,) = $GLOBALS['debug']['aucasou'];
			$nom = $GLOBALS['debug_objets']['courant'] . $id;
			$GLOBALS['debug_objets']['requete'][$nom] = $query;
		}
		$res = $f($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, true);
	}

	// en cas d'erreur
	if (!is_string($res)) return $res;
	// denoncer l'erreur SQL dans sa version brute
	spip_sql_erreur($serveur);
	// idem dans sa version squelette (prefixe des tables non substitue)
	erreur_squelette(array(sql_errno($serveur), sql_error($serveur), $res), $option);
	return false;
}


/**
 * Recupere la syntaxe de la requete select sans l'executer
 *
 * Passe simplement $option a false au lieu de true
 * sans obliger a renseigner tous les arguments de sql_select.
 * Les autres parametres sont identiques.
 *
 * @api
 * @uses sql_select()
 *
 * @param array|string $select
 * 		Liste des champs a recuperer (Select)
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array|string $orderby
 * 		Tableau de classement (Order By)
 * @param string $limit
 * 		Critere de limite (Limit)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * 
 * @return mixed
 * 		Chaine contenant la requete
 * 		ou false en cas d'erreur
 *  
**/
function sql_get_select($select = array(), $from = array(), $where = array(),
	$groupby = array(), $orderby = array(), $limit = '', $having = array(),
	$serveur='') {
	return sql_select ($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur, false);
}


/**
 * Retourne le nombre de lignes d'une selection
 *
 * Ramene seulement et tout de suite le nombre de lignes
 * Pas de colonne ni de tri a donner donc.
 *
 * @api
 * 
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- false -> ne pas l'executer mais la retourner, 
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible,
 * 		- true -> executer la requete.
 *
 * @return int|bool
 * 		Nombre de lignes de resultat
 * 		ou false en cas d'erreur
 *
**/
function sql_countsel($from = array(), $where = array(),
		      $groupby = array(), $having = array(),
	$serveur='', $option=true) {
	$f = sql_serveur('countsel', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($from, $where, $groupby, $having, $serveur, $option!==false);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}

/**
 * Modifie la structure de la base de donnees
 *
 * Effectue une operation ALTER.
 *
 * @example
 * 		<code>sql_alter('DROP COLUMN supprimer');</code>
 *
 * @api
 * @param string $q
 * 		La requete a executer (sans la preceder de 'ALTER ')
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * @return mixed
 * 		2 possibilites :
 * 		- Incertain en cas d'execution correcte de la requete
 * 		- false en cas de serveur indiponible ou d'erreur
 * 		Ce retour n'est pas pertinent pour savoir si l'operation est correctement realisee.
**/
function sql_alter($q, $serveur='', $option=true) {
	$f = sql_serveur('alter', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($q, $serveur, $option!==false);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}

/**
 * Retourne un enregistrement d'une selection
 *
 * Retourne un resultat d'une ressource obtenue avec sql_select()
 *
 * @api
 * @param mixed
 * 		Ressource retournee par sql_select()
 * @param string $serveur
 * 		Le nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return array
 * 		Tableau de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
 * 		presentant une ligne de resultat d'une selection 
 */
function sql_fetch($res, $serveur='', $option=true) {
	$f = sql_serveur('fetch', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($res, NULL, $serveur, $option!==false);
}


/**
 * Retourne tous les enregistrements d'une selection
 *
 * Retourne tous les resultats d'une ressource obtenue avec sql_select()
 * dans un tableau
 *
 * @api
 * @param mixed
 * 		Ressource retournee par sql_select()
 * @param string $serveur
 * 		Le nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return array
 * 		Tableau contenant les enregistrements.
 * 		Chaque entree du tableau est un autre tableau
 * 		de cles (colonnes SQL ou alias) / valeurs (valeurs dans la colonne de la table ou calculee)
 * 		presentant une ligne de resultat d'une selection 
 */
function sql_fetch_all($res, $serveur='', $option=true){
	$rows = array();
	if (!$res) return $rows;
	$f = sql_serveur('fetch', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return array();
	while ($r = $f($res, NULL, $serveur, $option!==false))
		$rows[] = $r;
	sql_free($res, $serveur);
	return $rows;
}

/**
 * Deplace le pointeur d'une ressource de selection
 *
 * Deplace le pointeur sur un numero de ligne precise
 * sur une ressource issue de sql_select, afin que
 * le prochain sql_fetch recupere cette ligne.
 *
 * @api
 * @see sql_skip() Pour sauter des enregistrements
 *
 * @param mixed $res
 * 		Ressource issue de sql_select
 * @param int $row_number
 * 		Numero de ligne sur laquelle placer le pointeur
 * @param string $serveur
 * 		Le nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return bool
 * 		Operation effectuee (true), sinon false.
**/
function sql_seek($res, $row_number, $serveur='', $option=true) {
	$f = sql_serveur('seek', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($res, $row_number, $serveur, $option!==false);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}


/**
 * Liste des bases de donnees accessibles
 *
 * Retourne un tableau du nom de toutes les bases de donnees
 * accessibles avec les permissions de l'utilisateur SQL
 * de cette connexion.
 * Attention on n'a pas toujours les droits !
 *
 * @api
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return array|bool
 * 		Tableau contenant chaque nom de base de donnees.
 * 		False en cas d'erreur.
**/
function sql_listdbs($serveur='', $option=true) {
	$f = sql_serveur('listdbs', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($serveur);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}


/**
 * Demande d'utiliser d'une base de donnees
 *
 * @api
 * @param string $nom
 * 		Nom de la base a utiliser
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true -> executer la requete
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return bool|string
 * 		True ou nom de la base en cas de success.
 * 		False en cas d'erreur.
**/
function sql_selectdb($nom, $serveur='', $option=true)
{
	$f = sql_serveur('selectdb', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($nom, $serveur, $option!==false);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_count
function sql_count($res, $serveur='', $option=true)
{
	$f = sql_serveur('count', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($res, $serveur, $option!==false);
	if ($r===false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_free
function sql_free($res, $serveur='', $option=true)
{
	$f = sql_serveur('free', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($res);
}

// Cette fonction ne garantit pas une portabilite totale
//  ===> lui preferer la suivante.
// Elle est fournie pour permettre l'actualisation de vieux codes 
// par un Sed brutal qui peut donner des resultats provisoirement acceptables
// http://doc.spip.org/@sql_insert
function sql_insert($table, $noms, $valeurs, $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('insert', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $noms, $valeurs, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_insertq
function sql_insertq($table, $couples=array(), $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('insertq', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $couples, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_insertq_multi
function sql_insertq_multi($table, $couples=array(), $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('insertq_multi', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $couples, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_update
function sql_update($table, $exp, $where='', $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('update', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $exp, $where, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// Update est presque toujours appelee sur des constantes ou des dates
// Cette fonction est donc plus utile que la precedente,d'autant qu'elle
// permet de gerer les differences de representation des constantes.
// http://doc.spip.org/@sql_updateq
function sql_updateq($table, $exp, $where='', $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('updateq', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $exp, $where, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_delete
function sql_delete($table, $where='', $serveur='', $option=true)
{
	$f = sql_serveur('delete', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $where, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_replace
function sql_replace($table, $couples, $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('replace', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $couples, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}


// http://doc.spip.org/@sql_replace_multi
function sql_replace_multi($table, $tab_couples, $desc=array(), $serveur='', $option=true)
{
	$f = sql_serveur('replace_multi', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $tab_couples, $desc, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_drop_table
function sql_drop_table($table, $exist='', $serveur='', $option=true)
{
	$f = sql_serveur('drop_table', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $exist, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// supprimer une vue sql
// http://doc.spip.org/@sql_drop_view
function sql_drop_view($table, $exist='', $serveur='', $option=true)
{
	$f = sql_serveur('drop_view', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $exist, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

/**
 * Retourne une ressource de la liste des tables de la base de données 
 *
 * @api
 * @param string $spip
 *     Filtre sur tables retournées
 *     - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
 *     - '%' : retourne toutes les tables de la base
 * @param string $serveur
 *     Le nom du connecteur
 * @param bool|string $option
 *     Peut avoir 3 valeurs : 
 *     - false -> ne pas l'executer mais la retourner, 
 *     - continue -> ne pas echouer en cas de serveur sql indisponible,
 *     - true -> executer la requete.
 * @return ressource
 *     Ressource à utiliser avec sql_fetch()
**/
function sql_showbase($spip=NULL, $serveur='', $option=true)
{
	$f = sql_serveur('showbase', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;

	// la globale n'est remplie qu'apres l'appel de sql_serveur.
	if ($spip == NULL){
		$connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
		$spip = $connexion['prefixe'] . '\_%';
	}

	return $f($spip, $serveur, $option!==false);
}

/**
 * Retourne la liste des tables SQL
 *
 * @api
 * @uses sql_showbase()
 * @param string $spip
 *     Filtre sur tables retournées
 *     - NULL : retourne les tables SPIP uniquement (tables préfixées avec le préfixe de la connexion)
 *     - '%' : retourne toutes les tables de la base
 * @param string $serveur
 *     Le nom du connecteur
 * @param bool|string $option
 *     Peut avoir 3 valeurs : 
 *     - false -> ne pas l'executer mais la retourner, 
 *     - continue -> ne pas echouer en cas de serveur sql indisponible,
 *     - true -> executer la requete.
 * @return array
 *     Liste des tables SQL
**/
function sql_alltable($spip=NULL, $serveur='', $option=true)
{
	$q = sql_showbase($spip, $serveur, $option);
	$r = array();
	if ($q) while ($t = sql_fetch($q, $serveur)) { $r[] = array_shift($t);}
	return $r;
}

// http://doc.spip.org/@sql_showtable
function sql_showtable($table, $table_spip = false, $serveur='', $option=true)
{
	$f = sql_serveur('showtable', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;

	// la globale n'est remplie qu'apres l'appel de sql_serveur.
	if ($table_spip){
		$connexion = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
		$prefixe = $connexion['prefixe'];
		$vraie_table = preg_replace('/^spip/', $prefixe, $table);
	} else $vraie_table = $table;

	$f = $f($vraie_table, $serveur, $option!==false);
	if (!$f) return array();
	if (isset($GLOBALS['tables_principales'][$table]['join']))
		$f['join'] = $GLOBALS['tables_principales'][$table]['join'];
	elseif (isset($GLOBALS['tables_auxiliaires'][$table]['join']))
		$f['join'] = $GLOBALS['tables_auxiliaires'][$table]['join'];
	return $f;
}

// http://doc.spip.org/@sql_create
function sql_create($nom, $champs, $cles=array(), $autoinc=false, $temporary=false, $serveur='', $option=true) {
	$f = sql_serveur('create', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($nom, $champs, $cles, $autoinc, $temporary, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

function sql_create_base($nom, $serveur='', $option=true)
{
	$f = sql_serveur('create_base', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($nom, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// Fonction pour creer une vue 
// nom : nom de la vue,
// select_query : une requete select, idealement cree avec $req = sql_select()
// (en mettant $option du sql_select a false pour recuperer la requete)
// http://doc.spip.org/@sql_create_view
function sql_create_view($nom, $select_query, $serveur='', $option=true) {
	$f = sql_serveur('create_view', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($nom, $select_query, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_multi
function sql_multi($sel, $lang, $serveur='', $option=true)
{
	$f = sql_serveur('multi', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($sel, $lang);
}


/**
 * Retourne la dernière erreur connue
 *
 * @api
 * @param string $serveur
 *      Nom du connecteur
 * @return bool|string
 *      Description de l'erreur
 *      False si le serveur est indisponible
 */
function sql_error($serveur='') {
	$f = sql_serveur('error', $serveur, 'continue');
	if (!is_string($f) OR !$f) return false;
	return $f('query inconnue', $serveur);
}

/**
 * Retourne le numéro de la derniere erreur connue
 *
 * @api
 * @param string $serveur
 *      Nom du connecteur
 * @return bool|int
 *      Numéro de l'erreur
 *      False si le serveur est indisponible
 */
function sql_errno($serveur='') {
	$f = sql_serveur('errno', $serveur, 'continue');
	if (!is_string($f) OR !$f) return false;
	return $f($serveur);
}

// http://doc.spip.org/@sql_explain
function sql_explain($q, $serveur='', $option=true) {
	$f = sql_serveur('explain', $serveur,  'continue');
	if (!is_string($f) OR !$f) return false;
	$r = $f($q, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_optimize
function sql_optimize($table, $serveur='', $option=true) {
	$f = sql_serveur('optimize', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// http://doc.spip.org/@sql_repair
function sql_repair($table, $serveur='', $option=true) {
	$f = sql_serveur('repair', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($table, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

// Fonction la plus generale ... et la moins portable
// A n'utiliser qu'en derniere extremite

// http://doc.spip.org/@sql_query
function sql_query($ins, $serveur='', $option=true) {
	$f = sql_serveur('query', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	$r = $f($ins, $serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
}

/**
 * Retourne la premiere ligne d'une selection
 * 
 * Retourne la premiere ligne de resultat d'une selection
 * comme si l'on appelait successivement sql_select() puis sql_fetch()
 * 
 * @example
 * 		<code>
 * 		$art = sql_fetsel(array('id_rubrique','id_secteur'), 'spip_articles', 'id_article='.sql_quote($id_article));
 *		$id_rubrique = $art['id_rubrique'];
 * 		</code>
 * 
 * @api
 * @uses sql_select()
 * @uses sql_fetch()
 * 
 * @param array|string $select
 * 		Liste des champs a recuperer (Select)
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array|string $orderby
 * 		Tableau de classement (Order By)
 * @param string $limit
 * 		Critere de limite (Limit)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- true -> executer la requete.
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible.
 * 		- false -> ne pas l'executer mais la retourner.
 * 
 * @return array
 * 		Tableau de la premiere ligne de resultat de la selection
 * 		{@example
 * 			<code>array('id_rubrique' => 1, 'id_secteur' => 2)</code>
 * 		}
 *
**/
function sql_fetsel($select = array(), $from = array(), $where = array(),
	$groupby = array(), $orderby = array(), $limit = '',
	$having = array(), $serveur='', $option=true) {
	$q = sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur, $option);
	if ($option===false) return $q;
	if (!$q) return array();
	$r = sql_fetch($q, $serveur, $option);
	sql_free($q, $serveur, $option);
	return $r;
}


/**
 * Retourne le tableau de toutes les lignes d'une selection
 * 
 * Retourne toutes les lignes de resultat d'une selection
 * comme si l'on appelait successivement sql_select() puis while(sql_fetch())
 * 
 * @example
 * 		<code>
 * 		$rubs = sql_allfetsel('id_rubrique', 'spip_articles', 'id_secteur='.sql_quote($id_secteur));
 *		// $rubs = array(array('id_rubrique'=>1), array('id_rubrique'=>3, ...)
 * 		</code>
 * 
 * @api
 * @uses sql_select()
 * @uses sql_fetch()
 * 
 * @param array|string $select
 * 		Liste des champs a recuperer (Select)
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array|string $orderby
 * 		Tableau de classement (Order By)
 * @param string $limit
 * 		Critere de limite (Limit)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- true -> executer la requete.
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible.
 * 		- false -> ne pas l'executer mais la retourner.
 * 
 * @return array
 * 		Tableau de toutes les lignes de resultat de la selection
 * 		Chaque entree contient un tableau des elements demandees dans le SELECT.
 * 		{@example
 * 			<code>
 * 			array(
 * 				array('id_rubrique' => 1, 'id_secteur' => 2)
 * 				array('id_rubrique' => 4, 'id_secteur' => 2)
 * 				...
 * 			)
 * 			</code>
 * 		}
 *
**/
function sql_allfetsel($select = array(), $from = array(), $where = array(),
	$groupby = array(), $orderby = array(), $limit = '',
	$having = array(), $serveur='', $option=true) {
	$q = sql_select($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur, $option);
	if ($option===false) return $q;
	return sql_fetch_all($q, $serveur, $option);
}


/**
 * Retourne un unique champ d'une selection
 * 
 * Retourne dans la premiere ligne de resultat d'une selection
 * un unique champ demande
 * 
 * @example
 * 		<code>
 * 		$id_rubrique = sql_getfetsel('id_rubrique', 'spip_articles', 'id_article='.sql_quote($id_article));
 * 		</code>
 *
 * @api
 * @uses sql_fetsel()
 * 
 * @param array|string $select
 * 		Liste des champs a recuperer (Select)
 * @param array|string $from
 * 		Tables a consulter (From)
 * @param array|string $where
 * 		Conditions a remplir (Where)
 * @param array|string $groupby
 * 		Critere de regroupement (Group by)
 * @param array|string $orderby
 * 		Tableau de classement (Order By)
 * @param string $limit
 * 		Critere de limite (Limit)
 * @param array $having
 * 		Tableau des des post-conditions a remplir (Having)
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- true -> executer la requete.
 * 		- continue -> ne pas echouer en cas de serveur sql indisponible.
 * 		- false -> ne pas l'executer mais la retourner.
 * 
 * @return mixed
 * 		Contenu de l'unique valeur demandee du premier enregistrement retourne
 *
**/
function sql_getfetsel($select, $from = array(), $where = array(), $groupby = array(), 
	$orderby = array(), $limit = '', $having = array(), $serveur='', $option=true) {
	if (preg_match('/\s+as\s+(\w+)$/i', $select, $c)) $id = $c[1];
	elseif (!preg_match('/\W/', $select)) $id = $select;
	else {$id = 'n'; $select .= ' AS n';}
	$r = sql_fetsel($select, $from, $where,	$groupby, $orderby, $limit, $having, $serveur, $option);
	if ($option===false) return $r;
	if (!$r) return NULL;
	return $r[$id]; 
}

/**
 * Retourne le numero de version du serveur SQL 
 *
 * @api
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true pour executer la requete.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 * 
 * @return string
 * 		Numero de version du serveur SQL
**/
function sql_version($serveur='', $option=true) {
	$row = sql_fetsel("version() AS n", '','','','','','',$serveur);
	return ($row['n']);
}

/**
 * Informe si le moteur SQL prefere utiliser des transactions
 *
 * Cette fonction experimentale est pour l'instant presente pour accelerer certaines
 * insertions multiples en SQLite, en les encadrant d'une transaction.
 * SQLite ne cree alors qu'un verrou pour l'ensemble des insertions
 * et non un pour chaque, ce qui accelere grandement le processus.
 * Evidemment, si une des insertions echoue, rien ne sera enregistre.
 * Pour ne pas perturber les autres moteurs, cette fonction permet
 * de verifier que le moteur prefere utiliser des transactions dans ce cas.
 *
 * @example
 * 		<code>
 * 		if (sql_preferer_transaction()) {
 * 			sql_demarrer_transaction();
 * 		}
 * 		</code>
 *
 * @api
 * @see sql_demarrer_transaction()
 * @see sql_terminer_transaction()
 *
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true pour executer la requete.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 *
 * @return bool
 * 		Le serveur SQL prefere t'il des transactions pour les insertions multiples ?
**/
function sql_preferer_transaction($serveur='', $option=true) {
	$f = sql_serveur('preferer_transaction', $serveur,  'continue');
	if (!is_string($f) OR !$f) return false;
	$r = $f($serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
};

/**
 * Demarre une transaction
 *
 * @api
 * @see sql_terminer_transaction() Pour cloturer la transaction
 * 
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- true pour executer la requete.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 * 		- false pour obtenir le code de la requete
 * 
 * @return bool
 *      true si la transaction est demarree
 *      false en cas d'erreur
**/
function sql_demarrer_transaction($serveur='', $option=true) {
	$f = sql_serveur('demarrer_transaction', $serveur,  'continue');
	if (!is_string($f) OR !$f) return false;
	$r = $f($serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
};

/**
 * Termine une transaction
 *
 * @api
 * @see sql_demarrer_transaction() Pour demarrer une transaction
 * 
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 3 valeurs : 
 * 		- true pour executer la requete.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 * 		- false pour obtenir le code de la requete
 * 
 * @return bool
 *      true si la transaction est demarree
 *      false en cas d'erreur
**/
function sql_terminer_transaction($serveur='', $option=true) {
	$f = sql_serveur('terminer_transaction', $serveur,  'continue');
	if (!is_string($f) OR !$f) return false;
	$r = $f($serveur, $option!==false);
	if ($r === false) spip_sql_erreur($serveur);
	return $r;
};


/**
 * Prepare une chaine hexadecimale
 * 
 * Prend une chaine sur l'aphabet hexa
 * et retourne sa representation numerique attendue par le serveur SQL.
 * Par exemple : FF ==> 0xFF en MySQL mais x'FF' en PG
 *
 * @api
 * @param string $val
 * 		Chaine hexadecimale
 * @param string $serveur
 * 		Nom du connecteur
 * @param bool|string $option
 * 		Peut avoir 2 valeurs : 
 * 		- true pour executer la demande.
 * 		- continue pour ne pas echouer en cas de serveur sql indisponible.
 * @return string
 * 		Retourne la valeur hexadecimale attendue par le serveur SQL
**/
function sql_hex($val, $serveur='', $option=true)
{
	$f = sql_serveur('hex', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($val);
}

/**
 * Echapper du contenu
 * 
 * Echappe du contenu selon ce qu'attend le type de serveur SQL
 * et en fonction du type de contenu.
 * 
 * Cette fonction est automatiquement appelee par les fonctions sql_*q
 * tel que sql_instertq ou sql_updateq
 *
 * @api
 * @param string $val
 * 		Chaine a echapper
 * @param string $serveur
 * 		Nom du connecteur
 * @param string $type
 * 		Peut contenir une declaration de type de champ SQL
 * 		{@example <code>int NOT NULL</code>} qui sert alors aussi a calculer le type d'echappement
 * @return string
 * 		La chaine echappee
**/
function sql_quote($val, $serveur='', $type='')
{
	$f = sql_serveur('quote', $serveur, true);
	if (!is_string($f) OR !$f) $f = '_q';
	return $f($val, $type);
}

function sql_date_proche($champ, $interval, $unite, $serveur='', $option=true)
{
	$f = sql_serveur('date_proche', $serveur, true);
	if (!is_string($f) OR !$f) return false;
	return $f($champ, $interval, $unite);
}

/**
 * Retourne une expression IN pour le gestionnaire de base de données
 *
 * Retourne un code à insérer dans une requête SQL pour récupérer
 * les éléments d'une colonne qui appartiennent à une liste donnée
 *
 * @example
 *     sql_in('id_rubrique', array(3,4,5))
 *     retourne approximativement «id_rubrique IN (3,4,5)» selon ce qu'attend
 *     le gestionnaire de base de donnée du connecteur en cours.
 *
 * @api
 * @param string $val
 *     Colonne SQL sur laquelle appliquer le test
 * @param string|array $valeurs
 *     Liste des valeurs possibles (séparés par des virgules si string)
 * @param string $not
 *     - '' sélectionne les éléments correspondant aux valeurs
 *     - 'NOT' inverse en sélectionnant les éléments ne correspondant pas aux valeurs
 * @param string $serveur
 *   Nom du connecteur
 * @param bool|string $option
 *   Peut avoir 2 valeurs : 
 *   - continue -> ne pas echouer en cas de serveur sql indisponible
 *   - true ou false -> retourne l'expression
 * @return string
 *     Expression de requête SQL
**/
function sql_in($val, $valeurs, $not='', $serveur='', $option=true) {
	if (is_array($valeurs)) {
		$f = sql_serveur('quote', $serveur, true);
		if (!is_string($f) OR !$f) return false;
		$valeurs = join(',', array_map($f, array_unique($valeurs)));
	} elseif (isset($valeurs[0]) AND $valeurs[0]===',') $valeurs = substr($valeurs,1);
	if (!strlen(trim($valeurs))) return ($not ? "0=0" : '0=1');

	$f = sql_serveur('in', $serveur,  $option==='continue' OR $option===false);
	if (!is_string($f) OR !$f) return false;
	return $f($val, $valeurs, $not, $serveur, $option!==false);
}

// Penser a dire dans la description du serveur 
// s'il accepte les requetes imbriquees afin d'optimiser ca

// http://doc.spip.org/@sql_in_select
function sql_in_select($in, $select, $from = array(), $where = array(),
		    $groupby = array(), $orderby = array(), $limit = '', $having = array(), $serveur='')
{
	$liste = array(); 
	$res = sql_select($select, $from, $where, $groupby, $orderby, $limit, $having, $serveur); 
	while ($r = sql_fetch($res)) {$liste[] = array_shift($r);}
	sql_free($res);
	return sql_in($in, $liste);
}

/**
 * Implementation securisee du saut en avant,
 * qui ne depend pas de la disponibilite de la fonction sql_seek
 * ne fait rien pour une valeur negative ou nulle de $saut
 * retourne la position apres le saut
 *
 * @see sql_seek()
 * 
 * @param resource $res
 * 		Ressource issue d'une selection sql_select
 * @param int $pos
 *   position courante
 * @param int $saut
 *   saut demande
 * @param int $count
 *   position maximale
 *   (nombre de resultat de la requete OU position qu'on ne veut pas depasser)
 * @param string $serveur
 *   Nom du connecteur
 * @param bool|string $option
 *   Peut avoir 2 valeurs : 
 *   - true -> executer la requete
 *   - continue -> ne pas echouer en cas de serveur sql indisponible
 * 
 * @return int
 *    Position apres le saut.
 */
function sql_skip($res, $pos, $saut, $count, $serveur='', $option=true){
	// pas de saut en arriere qu'on ne sait pas faire sans sql_seek
	if (($saut=intval($saut))<=0) return $pos;

	$seek = $pos + $saut;
	// si le saut fait depasser le maxi, on libere la resource
	// et on sort
	if ($seek>=$count) {sql_free($res, $serveur, $option); return $count;}

	if (sql_seek($res, $seek))
		$pos = $seek;
	else
		while ($pos<$seek AND sql_fetch($res, $serveur, $option))
			$pos++;
	return $pos;
}

// http://doc.spip.org/@sql_test_int
function sql_test_int($type, $serveur='', $option=true)
{
  return preg_match('/^(TINYINT|SMALLINT|MEDIUMINT|INT|INTEGER|BIGINT)/i',trim($type));
}

// http://doc.spip.org/@sql_test_date
function sql_test_date($type, $serveur='', $option=true)
{
  return preg_match('/^(DATE|DATETIME|TIMESTAMP|TIME)/i',trim($type));
}

/**
 * Formate une date
 * 
 * Formater une date Y-m-d H:i:s sans passer par mktime
 * qui ne sait pas gerer les dates < 1970
 *
 * http://doc.spip.org/@format_mysql_date
 *
 * @param int $annee Annee
 * @param int $mois  Numero du mois
 * @param int $jour  Numero du jour dans le mois
 * @param int $h     Heures
 * @param int $m     Minutes
 * @param int $s     Secondes
 * @param string $serveur
 * 		Le serveur sollicite (pour retrouver la connexion)
 * @return string
 * 		La date formatee
 */
function sql_format_date($annee=0, $mois=0, $jour=0, $h=0, $m=0, $s=0, $serveur=''){
	$annee = sprintf("%04s",$annee);
	$mois = sprintf("%02s",$mois);

	if ($annee == "0000") $mois = 0;
	if ($mois == "00") $jour = 0;

	return sprintf("%04u",$annee) . '-' . sprintf("%02u",$mois) . '-'
		. sprintf("%02u",$jour) . ' ' . sprintf("%02u",$h) . ':'
		. sprintf("%02u",$m) . ':' . sprintf("%02u",$s);
}



/**
 * Retourne la description de la table SQL
 *
 * Retrouve la description de la table SQL en privilegiant
 * la structure reelle de la base de donnees.
 * En absence, ce qui arrive lors de l'installation, la fonction
 * s'appuie sur la declaration des tables SQL principales ou auxiliaires.
 * 
 * @internal Cette fonction devrait disparaître
 * 
 * @param string $nom
 * 		Nom de la table dont on souhait la description
 * @param string $serveur
 * 		Nom du connecteur
 * @return array|bool
 * 		Description de la table ou false si elle n'est pas trouvee ou declaree.
**/
function description_table($nom, $serveur=''){

	global $tables_principales, $tables_auxiliaires;
	static $trouver_table;

	/* toujours utiliser trouver_table
	 qui renverra la description theorique
	 car sinon on va se comporter differement selon que la table est declaree
	 ou non
	 */
	if (!$trouver_table) $trouver_table = charger_fonction('trouver_table', 'base');
	if ($desc = $trouver_table($nom, $serveur))
		return $desc;

	// sauf a l'installation :
	include_spip('base/serial');
	if (isset($tables_principales[$nom]))
		return $tables_principales[$nom];

	include_spip('base/auxiliaires');
	if (isset($tables_auxiliaires[$nom]))
		return $tables_auxiliaires[$nom];

	return false;
}


?>
delete_all.php000066600000002654152502550120007357 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

// http://doc.spip.org/@base_delete_all_dist
function base_delete_all_dist($titre)
{
	$delete = _request('delete');
	$res = array();
	if (is_array($delete)) {
		foreach ($delete as $table) {
			if (sql_drop_table($table))
				$res[] = $table;
			else spip_log( "SPIP n'a pas pu detruire $table.", _LOG_ERREUR);
		}

	// un pipeline pour detruire les tables installees par les plugins
		pipeline('delete_tables', '');

		spip_unlink(_FILE_CONNECT);
		spip_unlink(_FILE_CHMOD);
		spip_unlink(_FILE_META);
		spip_unlink(_ACCESS_FILE_NAME);
		spip_unlink(_CACHE_RUBRIQUES);
	}
	$d = count($delete);
	$r = count($res);
	spip_log("Tables detruites: $r sur $d: " . join(', ',$res), _LOG_INFO_IMPORTANTE);
}
?>
objets.php000066600000110504152502550120006545 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Fonctions relatives aux objets éditoriaux et SQL
 *
 * @package SPIP\SQL\Tables
**/

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Merge dans un tableau une de ses clés avec une valeur
 *
 * @param array $table
 *     Tableau dont on veut compléter une clé
 * @param string $index
 *     Clé du tableau que l'on souhaite compléter
 * @param array $valeur
 *     Sous tableau à merger dans la clé.
 * @return void
**/
function array_set_merge(&$table,$index,$valeur){
	if (!isset($table[$index]))
		$table[$index] = $valeur;
	else
		$table[$index] = array_merge($table[$index],$valeur);
}

/**
 * Lister les infos de toutes les tables sql declarées
 * 
 * Si un argument est fourni, on ne renvoie que les infos de cette table.
 * Elle est auto-declarée si inconnue jusqu'alors.
 *
 * @api
 * @param string $table_sql
 *   table_sql demandee explicitement
 * @param array $desc
 *   description connue de la table sql demandee
 * @return array|bool
 */
function lister_tables_objets_sql($table_sql=null, $desc=array()){
	static $deja_la = false;
	static $infos_tables = null;
	static $md5 = null;
	static $plugin_hash = null;
	// prealablement recuperer les tables_principales
	if (is_null($infos_tables)
	  OR $plugin_hash!==_PLUGINS_HASH){
		// pas de reentrance (cas base/serial)
		if ($deja_la) {
			spip_log ("Re-entrance anormale sur lister_tables_objets_sql :"
				. var_export(debug_backtrace(),true),_LOG_CRITIQUE);
			return ($table_sql==="::md5"?$md5:array());
		}
		$deja_la = true;
		$plugin_hash = _PLUGINS_HASH; // avant de lancer les pipelines

		// recuperer les declarations explicites ancienne mode
		// qui servent a completer declarer_tables_objets_sql
		base_serial($GLOBALS['tables_principales']);
		base_auxiliaires($GLOBALS['tables_auxiliaires']);
		$infos_tables = array(
			'spip_articles'=> array(
				'page'=>'article',
				'texte_retour' => 'icone_retour_article',
				'texte_modifier' => 'icone_modifier_article',
				'texte_creer' => 'icone_ecrire_article',
				'texte_objets' => 'public:articles',
				'texte_objet' => 'public:article',
				'texte_signale_edition' => 'texte_travail_article',
				'info_aucun_objet'=> 'info_aucun_article',
				'info_1_objet' => 'info_1_article',
				'info_nb_objets' => 'info_nb_articles',
				'texte_logo_objet' => 'logo_article',
				'texte_langue_objet' => 'titre_langue_article',
				'texte_definir_comme_traduction_objet' => 'trad_lier',
				'titre' => 'titre, lang',
				'date' => 'date',
				'principale' => 'oui',
				'champs_editables' => array('surtitre', 'titre', 'soustitre', 'descriptif','nom_site', 'url_site', 'chapo', 'texte', 'ps','virtuel'),
				'champs_versionnes' => array('id_rubrique', 'surtitre', 'titre', 'soustitre', 'jointure_auteurs', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps'),
				'field' => array(
					"id_article"	=> "bigint(21) NOT NULL",
					"surtitre"	=> "text DEFAULT '' NOT NULL",
					"titre"	=> "text DEFAULT '' NOT NULL",
					"soustitre"	=> "text DEFAULT '' NOT NULL",
					"id_rubrique"	=> "bigint(21) DEFAULT '0' NOT NULL",
					"descriptif"	=> "text DEFAULT '' NOT NULL",
					"chapo"	=> "mediumtext DEFAULT '' NOT NULL",
					"texte"	=> "longtext DEFAULT '' NOT NULL",
					"ps"	=> "mediumtext DEFAULT '' NOT NULL",
					"date"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"statut"	=> "varchar(10) DEFAULT '0' NOT NULL",
					"id_secteur"	=> "bigint(21) DEFAULT '0' NOT NULL",
					"maj"	=> "TIMESTAMP",
					"export"	=> "VARCHAR(10) DEFAULT 'oui'",
					"date_redac"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"visites"	=> "integer DEFAULT '0' NOT NULL",
					"referers"	=> "integer DEFAULT '0' NOT NULL",
					"popularite"	=> "DOUBLE DEFAULT '0' NOT NULL",
					"accepter_forum"	=> "CHAR(3) DEFAULT '' NOT NULL",
					"date_modif"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"lang"		=> "VARCHAR(10) DEFAULT '' NOT NULL",
					"langue_choisie"	=> "VARCHAR(3) DEFAULT 'non'",
					"id_trad"	=> "bigint(21) DEFAULT '0' NOT NULL",
					"nom_site"	=> "tinytext DEFAULT '' NOT NULL",
					"url_site"	=> "VARCHAR(255) DEFAULT '' NOT NULL",
					"virtuel"	=> "VARCHAR(255) DEFAULT '' NOT NULL",
				),
				'key' => array(
					"PRIMARY KEY"		=> "id_article",
					"KEY id_rubrique"	=> "id_rubrique",
					"KEY id_secteur"	=> "id_secteur",
					"KEY id_trad"		=> "id_trad",
					"KEY lang"		=> "lang",
					"KEY statut"		=> "statut, date",
				),
				'join' => array(
					"id_article"=>"id_article",
					"id_rubrique"=>"id_rubrique"
				),
				'rechercher_champs' => array(
					'surtitre' => 5, 'titre' => 8, 'soustitre' => 5, 'chapo' => 3,
					'texte' => 1, 'ps' => 1, 'nom_site' => 1, 'url_site' => 1,
					'descriptif' => 4
				),
				'rechercher_jointures' => array(
					'auteur' => array('nom' => 10),
				),
				'statut'=> array(
					array(
						'champ' => 'statut',
						'publie' => 'publie',
						'previsu' => 'publie,prop,prepa/auteur',
						'post_date' => 'date',
						'exception' => 'statut'
					)
				),
				'statut_titres' => array(
					'prepa'=>'info_article_redaction',
					'prop'=>'info_article_propose',
					'publie'=>'info_article_publie',
					'refuse'=>'info_article_refuse',
					'poubelle'=>'info_article_supprime'
				),
				'statut_textes_instituer' => 	array(
					'prepa' => 'texte_statut_en_cours_redaction',
					'prop' => 'texte_statut_propose_evaluation',
					'publie' => 'texte_statut_publie',
					'refuse' => 'texte_statut_refuse',
					'poubelle' => 'texte_statut_poubelle',
				),
				'texte_changer_statut' => 'texte_article_statut',
				'aide_changer_statut' => 'artstatut',
				'tables_jointures' => array(
					'profondeur' => 'rubriques',
					#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
				),
			),
			'spip_auteurs' => array(
				'page'=>'auteur',
				'texte_retour' => 'icone_retour',
				'texte_ajouter' => 'titre_ajouter_un_auteur',
				'texte_modifier' => 'admin_modifier_auteur',
				'texte_objets' => 'icone_auteurs',
				'texte_objet' => 'public:auteur',
				'info_aucun_objet'=> 'info_aucun_auteur',
				'info_1_objet' => 'info_1_auteur',
				'info_nb_objets' => 'info_nb_auteurs',
				'texte_logo_objet' => 'logo_auteur',
				'texte_creer_associer' => 'creer_et_associer_un_auteur',
				'titre' => "nom AS titre, '' AS lang",
				'date' => 'date',
				'principale' => 'oui',
				'champs_editables' => array('nom','email','bio','nom_site','url_site','imessage','pgp'),
				'champs_versionnes' => array('nom', 'bio', 'email', 'nom_site', 'url_site', 'login'),
				'field' => array(
					"id_auteur"	=> "bigint(21) NOT NULL",
					"nom"	=> "text DEFAULT '' NOT NULL",
					"bio"	=> "text DEFAULT '' NOT NULL",
					"email"	=> "tinytext DEFAULT '' NOT NULL",
					"nom_site"	=> "tinytext DEFAULT '' NOT NULL",
					"url_site"	=> "text DEFAULT '' NOT NULL",
					"login"	=> "VARCHAR(255) BINARY",
					"pass"	=> "tinytext DEFAULT '' NOT NULL",
					"low_sec"	=> "tinytext DEFAULT '' NOT NULL",
					"statut"	=> "varchar(255)  DEFAULT '0' NOT NULL",
					"webmestre"	=> "varchar(3)  DEFAULT 'non' NOT NULL",
					"maj"	=> "TIMESTAMP",
					"pgp"	=> "TEXT DEFAULT '' NOT NULL",
					"htpass"	=> "tinytext DEFAULT '' NOT NULL",
					"en_ligne"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"alea_actuel"	=> "tinytext",
					"alea_futur"	=> "tinytext",
					"prefs"	=> "tinytext",
					"cookie_oubli"	=> "tinytext",
					"source"	=> "VARCHAR(10) DEFAULT 'spip' NOT NULL",
					"lang"	=> "VARCHAR(10) DEFAULT '' NOT NULL"
				),
				'key' => array(
					"PRIMARY KEY"	=> "id_auteur",
					"KEY login"	=> "login",
					"KEY statut"	=> "statut",
					"KEY en_ligne"	=> "en_ligne",
				),
				'join' => array(
					"id_auteur"=>"id_auteur",
					"login"=>"login"
				),
				'rechercher_champs' => array(
					'nom' => 5, 'bio' => 1, 'email' => 1, 'nom_site' => 1, 'url_site' => 1, 'login' => 1
				),
				// 2 conditions pour les auteurs : statut!=poubelle,
				// et avoir des articles publies
				'statut'=> array(
					array(
						'champ' => 'statut',
						'publie' => '!5poubelle',
						'previsu' => '!5poubelle',
						'exception' => 'statut'
					),
					array(
						'champ' => array(
							array('spip_auteurs_liens', 'id_auteur'),
							array(
								'spip_articles',
								array('id_objet','id_article','objet','article')
							),
							'statut'
						),
						'publie' => 'publie',
						'previsu' => '!',
						'post_date' => 'date',
						'exception' => array('statut','lien','tout')
					),
				),
				'statut_images' => array(
					'auteur-6forum-16.png',
					'0minirezo'=>'auteur-0minirezo-16.png',
					'1comite'=>'auteur-1comite-16.png',
					'6forum'=>'auteur-6forum-16.png',
					'5poubelle'=>'auteur-5poubelle-16.png',
					'nouveau'=>''
				),
				'statut_titres' => array(
					'titre_image_visiteur',
					'0minirezo'=>'titre_image_administrateur',
					'1comite'=>'titre_image_redacteur_02',
					'6forum'=>'titre_image_visiteur',
					'5poubelle'=>'titre_image_auteur_supprime',
				),
				'tables_jointures' => array(
					#'auteurs_liens' // declaration generique plus bas
				),
			),
			'spip_rubriques' => array(
				'page'=>'rubrique',
				'url_voir' => 'rubrique',
				'url_edit' => 'rubrique_edit',
				'texte_retour' => 'icone_retour',
				'texte_objets' => 'public:rubriques',
				'texte_objet' => 'public:rubrique',
				'texte_modifier' => 'icone_modifier_rubrique',
				'texte_creer' => 'icone_creer_rubrique',
				'texte_ajouter' => 'titre_ajouter_une_rubrique',
				'texte_creer_associer' => 'creer_et_associer_une_rubrique',
				'info_aucun_objet'=> 'info_aucun_rubrique',
				'info_1_objet' => 'info_1_rubrique',
				'info_nb_objets' => 'info_nb_rubriques',
				'texte_logo_objet' => 'logo_rubrique',
				'texte_langue_objet' => 'titre_langue_rubrique',
				'titre'=>'titre, lang',
				'date' => 'date',
				'principale' => 'oui',
				'champs_editables' => array('titre', 'texte', 'descriptif', 'extra'),
				'champs_versionnes' => array('titre', 'descriptif', 'texte'),
				'field' => array(
					"id_rubrique"	=> "bigint(21) NOT NULL",
					"id_parent"	=> "bigint(21) DEFAULT '0' NOT NULL",
					"titre"	=> "text DEFAULT '' NOT NULL",
					"descriptif"	=> "text DEFAULT '' NOT NULL",
					"texte"	=> "longtext DEFAULT '' NOT NULL",
					"id_secteur"	=> "bigint(21) DEFAULT '0' NOT NULL",
					"maj"	=> "TIMESTAMP",
					"statut"	=> "varchar(10) DEFAULT '0' NOT NULL",
					"date"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"lang"	=> "VARCHAR(10) DEFAULT '' NOT NULL",
					"langue_choisie"	=> "VARCHAR(3) DEFAULT 'non'",
					"statut_tmp"	=> "varchar(10) DEFAULT '0' NOT NULL",
					"date_tmp"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
					"profondeur" => "smallint(5) DEFAULT '0' NOT NULL"
				),
				'key' => array(
					"PRIMARY KEY"	=> "id_rubrique",
					"KEY lang"	=> "lang",
					"KEY id_parent"	=> "id_parent",
				),
				'rechercher_champs' => array(
					'titre' => 8, 'descriptif' => 5, 'texte' => 1
				),
				'statut' => array(
					array(
						'champ' => 'statut',
						'publie' => 'publie',
						'previsu' => '!',
						'exception' => array('statut','tout')
					),
				),
				'tables_jointures' => array(
					#'id_auteur' => 'auteurs_liens' // declaration generique plus bas
				),
			),
			// toutes les tables ont le droit a une jointure sur les auteurs
			array('tables_jointures'=>array('id_auteur'=>'auteurs_liens'))
		);

		// avant d'appeller les pipeline qui peuvent generer une reentrance a l'install
		// initialiser la signature
		$md5 = md5(serialize($infos_tables));

		$GLOBALS['tables_principales'] = pipeline('declarer_tables_principales',$GLOBALS['tables_principales']);
		$GLOBALS['tables_auxiliaires'] = pipeline('declarer_tables_auxiliaires',$GLOBALS['tables_auxiliaires']);
		$infos_tables =	pipeline('declarer_tables_objets_sql',$infos_tables);

		// completer les informations manquantes ou implicites
		$all = array();
		foreach(array_keys($infos_tables) as $t) {
			// les cles numeriques servent a declarer
			// les proprietes applicables a tous les objets
			// on les mets de cote
			if (is_numeric($t)) {
				$all = array_merge_recursive($all,$infos_tables[$t]);
				unset($infos_tables[$t]);
			}
			else
				$infos_tables[$t] = renseigner_table_objet_sql($t,$infos_tables[$t]);
		}

		// repercuter les proprietes generales communes a tous les objets
		foreach(array_keys($infos_tables) as $t) {
			foreach($all as $i=>$v)
				if (in_array($i,array('tables_jointures','champs_versionnes'))){
					$add = $all[$i];
					// eviter les doublons de declaration de table jointure (ex des mots sur auteurs)
					// pour les declarations generiques avec cles numeriques
					if ($i=='tables_jointures' AND isset($infos_tables[$t][$i]) AND count($infos_tables[$t][$i])) {
						$doublons = array_intersect($infos_tables[$t][$i],$add);
						foreach($doublons as $d){
							if (is_numeric(array_search($d,$infos_tables[$t][$i]))
								AND is_numeric($k=array_search($d,$add)))
								unset($add[$k]);
						}
					}
					$infos_tables[$t][$i] = array_merge(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$add);
				}
				else
					$infos_tables[$t][$i] = array_merge_recursive(isset($infos_tables[$t][$i])?$infos_tables[$t][$i]:array(),$all[$i]);
		}

		// completer les tables principales et auxiliaires
		// avec celles declarees uniquement dans declarer_table_objets_sql
		// pour assurer la compat en transition
		foreach($infos_tables as $table=>$infos) {
			$principale_ou_auxiliaire = ($infos['principale']?'tables_principales':'tables_auxiliaires');
			// memoriser des champs eventuels declares par des plugins dans le pipeline tables_xxx
			// qui a ete appelle avant
			$mem = (isset($GLOBALS[$principale_ou_auxiliaire][$table])?$GLOBALS[$principale_ou_auxiliaire][$table]:array());
			// l'ajouter au tableau
			$GLOBALS[$principale_ou_auxiliaire][$table] = array();
			if (isset($infos['field']) AND isset($infos['key'])){
				foreach(array('field','key','join') as $k)
					if (isset($infos_tables[$table][$k]))
						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = &$infos_tables[$table][$k];
			}
			else {
				// ici on ne renvoie que les declarations, donc RIEN
				// pour avoir la vrai description en base, il faut passer par trouver_table
				$GLOBALS[$principale_ou_auxiliaire][$table] = array();
			}
			if (count($mem)){
				foreach(array_keys($mem) as $k)
					if (isset($GLOBALS[$principale_ou_auxiliaire][$table][$k]))
						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = array_merge($GLOBALS[$principale_ou_auxiliaire][$table][$k],$mem[$k]);
					else
						$GLOBALS[$principale_ou_auxiliaire][$table][$k] = $mem[$k];
			}
		}

		// recuperer les interfaces (table_titre, table_date)
		// on ne le fait que dans un second temps pour que table_objet soit fonctionnel
		// dans le pipeline de declarer_tables_interfaces
		include_spip('public/interfaces');
		foreach(array_keys($infos_tables) as $t) {
			$infos_tables[$t] = renseigner_table_objet_interfaces($t,$infos_tables[$t]);
		}

		$deja_la = false;
		// signature
		$md5 = md5(serialize($infos_tables));
	}
	if ($table_sql==="::md5")
		return $md5;
	if ($table_sql AND !isset($infos_tables[$table_sql])){
		#$desc = renseigner_table_objet_sql($table_sql,$desc);
		$desc = renseigner_table_objet_interfaces($table_sql,$desc);
		return $desc;
	}
	if ($table_sql)
		return isset($infos_tables[$table_sql])?$infos_tables[$table_sql]:array();

	return $infos_tables;
}


/**
 * Déclare les tables principales du Core
 *
 * Tables principales, hors objets éditoriaux.
 *
 * @param array $tables_principales
 *     Description des tables principales déjà déclarées
 * @return void
**/
function base_serial(&$tables_principales){

	$spip_jobs = array(
		"id_job" 	=> "bigint(21) NOT NULL",
		"descriptif"	=> "text DEFAULT '' NOT NULL",
		"fonction" 	=> "varchar(255) NOT NULL", //nom de la fonction
		"args"=> "longblob DEFAULT '' NOT NULL", // arguments
		"md5args"=> "char(32) NOT NULL default ''", // signature des arguments
		"inclure" => "varchar(255) NOT NULL", // fichier a inclure ou path/ pour charger_fonction
		"priorite" 	=> "smallint(6) NOT NULL default 0",
		"date" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL", // date au plus tot
		"status" => "tinyint NOT NULL default 1",
		);

	$spip_jobs_key = array(
		"PRIMARY KEY" 	=> "id_job",
		"KEY date" => "date",
		"KEY status" => "status",
	);

	/// Attention: mes_fonctions peut avoir deja defini cette variable
	/// il faut donc rajouter, mais pas reinitialiser
	$tables_principales['spip_jobs'] = array('field' => &$spip_jobs, 'key' => &$spip_jobs_key);
}


/**
 * Déclare les tables auxiliaires du Core
 *
 * @param array $tables_auxiliaires
 *     Description des tables auxiliaires déjà déclarées
 * @return void
**/
function base_auxiliaires(&$tables_auxiliaires){
$spip_resultats = array(
 		"recherche"	=> "char(16) DEFAULT '' NOT NULL",
		"id"	=> "INT UNSIGNED NOT NULL",
 		"points"	=> "INT UNSIGNED DEFAULT '0' NOT NULL",
		"table_objet"	=> "varchar(30) DEFAULT '' NOT NULL",
		"serveur"	=> "char(16) DEFAULT '' NOT NULL", // hash md5 partiel du serveur de base ('' pour le serveur principal)
		"maj"	=> "TIMESTAMP" );

$spip_resultats_key = array(
// pas de cle ni index, ca fait des insertions plus rapides et les requetes jointes utilisees en recheche ne sont pas plus lentes ...
);

$spip_auteurs_liens = array(
		"id_auteur"	=> "bigint(21) DEFAULT '0' NOT NULL",
		"id_objet"	=> "bigint(21) DEFAULT '0' NOT NULL",
		"objet"	=> "VARCHAR (25) DEFAULT '' NOT NULL",
		"vu"	=> "VARCHAR(6) DEFAULT 'non' NOT NULL");

$spip_auteurs_liens_key = array(
		"PRIMARY KEY"		=> "id_auteur,id_objet,objet",
		"KEY id_auteur"	=> "id_auteur",
		"KEY id_objet"	=> "id_objet",
		"KEY objet"	=> "objet",
);

$spip_meta = array(
		"nom"	=> "VARCHAR (255) NOT NULL",
		"valeur"	=> "text DEFAULT ''",
		"impt"	=> "ENUM('non', 'oui') DEFAULT 'oui' NOT NULL",
		"maj"	=> "TIMESTAMP");

$spip_meta_key = array(
		"PRIMARY KEY"	=> "nom");

$spip_jobs_liens = array(
	"id_job"	=> "bigint(21) DEFAULT '0' NOT NULL",
	"id_objet"	=> "bigint(21) DEFAULT '0' NOT NULL",
	"objet"	=> "VARCHAR (25) DEFAULT '' NOT NULL",
);

$spip_jobs_liens_key = array(
		"PRIMARY KEY"		=> "id_job,id_objet,objet",
		"KEY id_job"	=> "id_job");

$tables_auxiliaires['spip_auteurs_liens'] = array(
	'field' => &$spip_auteurs_liens,
	'key' => &$spip_auteurs_liens_key);

$tables_auxiliaires['spip_meta'] = array(
	'field' => &$spip_meta,
	'key' => &$spip_meta_key);
$tables_auxiliaires['spip_resultats'] = array(
	'field' => &$spip_resultats,
	'key' => &$spip_resultats_key);
$tables_auxiliaires['spip_jobs_liens'] = array(
	'field' => &$spip_jobs_liens,
	'key' => &$spip_jobs_liens_key);

}


/**
 * Auto remplissage des informations non explicites
 * sur un objet d'une table sql
 *
 * - table_objet
 * - table_objet_surnoms
 * - type
 * - type_surnoms
 * - url_voir
 * - url_edit
 * - icone_objet
 *
 * - texte_retour
 * - texte_modifier
 * - texte_creer
 * - texte_creer_associer
 * - texte_ajouter
 * - texte_objets
 * - texte_objet
 *
 * - info_aucun_objet
 * - info_1_objet
 * - info_nb_objets
 *
 * - texte_logo_objet
 * - texte_langue_objet
 * - texte_definir_comme_traduction_objet
 *
 * - principale
 * - champs_contenu : utlisé pour générer l'affichage par défaut du contenu
 * - editable
 * - champs_editables : utilisé pour prendre en compte le post lors de l'édition
 * 
 * - champs_versionnes
 *
 * statut
 * statut_images
 * statut_titres
 * statut_textes_instituer
 * texte_changer_statut
 * aide_changer_statut
 *
 * - modeles : permet de declarer les modeles associes a cet objet
 * 
 * Les infos non renseignées sont auto-déduites par conventions
 * ou laissées vides
 *
 * @param string $table_sql
 * @param array $infos
 * @return array
 */
function renseigner_table_objet_sql($table_sql,&$infos){
	if (!isset($infos['type'])){
		// si on arrive de base/trouver_table, on a la cle primaire :
		// s'en servir pour extrapoler le type
		if (isset($infos['key']["PRIMARY KEY"])){
			$primary = $infos['key']["PRIMARY KEY"];
			$primary = explode(',',$primary);
			$primary = reset($primary);
			$infos['type'] = preg_replace(',^spip_|^id_|s$,', '', $primary);
		}
		else
			$infos['type'] = preg_replace(',^spip_|s$,', '', $table_sql);
	}
	if (!isset($infos['type_surnoms']))
		$infos['type_surnoms'] = array();

	if (!isset($infos['table_objet']))
		$infos['table_objet'] = preg_replace(',^spip_,', '', $table_sql);
	if (!isset($infos['table_objet_surnoms']))
		$infos['table_objet_surnoms'] = array();

	if (!isset($infos['principale']))
		$infos['principale'] = (isset($GLOBALS['tables_principales'][$table_sql])?'oui':false);

	// normaliser pour pouvoir tester en php $infos['principale']?
	// et dans une boucle {principale=oui}
	$infos['principale'] = (($infos['principale'] AND $infos['principale']!='non')?'oui':false);

	// declarer et normaliser pour pouvoir tester en php $infos['editable']?
	// et dans une boucle {editable=oui}
	if (!isset($infos['editable'])) $infos['editable'] = 'oui';
	$infos['editable'] = (($infos['editable'] AND $infos['editable']!='non')?'oui':false);

	// les urls publiques sont par defaut page=type pour les tables principales, et rien pour les autres
	// seules les exceptions sont donc a declarer
	if (!isset($infos['page']))
		$infos['page'] = ($infos['principale']?$infos['type']:'');

	if (!isset($infos['url_voir']))
		$infos['url_voir'] = $infos['type'];
	if (!isset($infos['url_edit']))
		$infos['url_edit'] = $infos['url_voir'].($infos['editable']?"_edit":'');
	if (!isset($infos['icone_objet']))
		$infos['icone_objet'] = $infos['type'];

	// chaines de langue
	// par defaut : objet:icone_xxx_objet
	if (!isset($infos['texte_retour']))
		$infos['texte_retour'] = 'icone_retour';
	if (!isset($infos['texte_modifier']))
		$infos['texte_modifier'] = $infos['type'].':'.'icone_modifier_'.$infos['type'];
	if (!isset($infos['texte_creer']))
		$infos['texte_creer'] = $infos['type'].':'.'icone_creer_'.$infos['type'];
	if (!isset($infos['texte_creer_associer']))
		$infos['texte_creer_associer'] = $infos['type'].':'.'texte_creer_associer_'.$infos['type'];
	if (!isset($infos['texte_ajouter'])) // Ajouter un X
		$infos['texte_ajouter'] = $infos['type'].':'.'texte_ajouter_'.$infos['type'];
	if (!isset($infos['texte_objets']))
		$infos['texte_objets'] = $infos['type'].':'.'titre_'.$infos['table_objet'];
	if (!isset($infos['texte_objet']))
		$infos['texte_objet'] = $infos['type'].':'.'titre_'.$infos['type'];
	if (!isset($infos['texte_logo_objet']))  // objet:titre_logo_objet "Logo de ce X"
		$infos['texte_logo_objet'] = $infos['type'].':'.'titre_logo_'.$infos['type'];
	if (!isset($infos['texte_langue_objet']))  // objet:texte_langue_objet "Langue de ce X"
		$infos['texte_langue_objet'] = $infos['type'].':'.'titre_langue_'.$infos['type'];
	if (!isset($infos['texte_definir_comme_traduction_objet']))  // "Ce X est une traduction du X numéro :"
		$infos['texte_definir_comme_traduction_objet'] = $infos['type'].':'.'texte_definir_comme_traduction_'.$infos['type'];


	// objet:info_aucun_objet
	if (!isset($infos['info_aucun_objet']))
		$infos['info_aucun_objet'] = $infos['type'].':'.'info_aucun_'.$infos['type'];
	// objet:info_1_objet
	if (!isset($infos['info_1_objet']))
		$infos['info_1_objet'] = $infos['type'].':'.'info_1_'.$infos['type'];
	// objet:info_nb_objets
	if (!isset($infos['info_nb_objets']))
		$infos['info_nb_objets'] = $infos['type'].':'.'info_nb_'.$infos['table_objet'];


	if (!isset($infos['champs_editables']))
		$infos['champs_editables'] = array();
	if (!isset($infos['champs_versionnes']))
		$infos['champs_versionnes'] = array();
	if (!isset($infos['rechercher_champs']))
		$infos['rechercher_champs'] = array();
	if (!isset($infos['rechercher_jointures']))
		$infos['rechercher_jointures'] = array();

	if (!isset($infos['modeles']))
		$infos['modeles'] = array($infos['type']);

	return $infos;
}

/**
 * Renseigner les infos d'interface compilateur pour les tables objets
 * complete la declaration precedente
 * 
 * titre
 * date
 * statut
 * tables_jointures
 *
 * @param $table_sql
 * @param $infos
 * @return array
 */
function renseigner_table_objet_interfaces($table_sql,&$infos){
	if (!isset($infos['titre'])){
		if (isset($infos['table_objet']) AND isset($GLOBALS['table_titre'][$infos['table_objet']]))
			$infos['titre'] = $GLOBALS['table_titre'][$infos['table_objet']];
		else {
			$infos['titre'] = ((isset($infos['field']['titre']))?"titre,":"'' as titre,");
			$infos['titre'] .= ((isset($infos['field']['lang']))?"lang":"'' as lang");
		}
	}
	if (!isset($infos['date'])){
		if (isset($infos['table_objet']) and isset($GLOBALS['table_date'][$infos['table_objet']]))
			$infos['date'] = $GLOBALS['table_date'][$infos['table_objet']];
		else
			$infos['date'] = ((isset($infos['field']['date']))?"date":'');
	}
	if (!isset($infos['statut']))
		$infos['statut'] = isset($GLOBALS['table_statut'][$table_sql]) ? $GLOBALS['table_statut'][$table_sql] : '';
	if (!isset($infos['tables_jointures']))
		$infos['tables_jointures'] = array();
	if (isset($GLOBALS['tables_jointures'][$table_sql]))
		$infos['tables_jointures'] = array_merge($infos['tables_jointures'],$GLOBALS['tables_jointures'][$table_sql]);
	return $infos;
}

/**
 * Retourne la liste des tables principales et leurs descriptions 
 *
 * @api
 * @return array
 *     Liste et descriptions des tables principales
**/
function lister_tables_principales(){
	static $done = false;
	if (!$done OR !count($GLOBALS['tables_principales'])){
		lister_tables_objets_sql();
		$done = true;
	}
	return $GLOBALS['tables_principales'];
}

/**
 * Retourne la liste des tables auxiliaires et leurs descriptions 
 *
 * @api
 * @return array
 *     Liste et descriptions des tables auxiliaires
**/
function lister_tables_auxiliaires(){
	static $done = false;
	if (!$done OR !count($GLOBALS['tables_auxiliaires'])){
		lister_tables_objets_sql();
		$done = true;
	}
	return $GLOBALS['tables_auxiliaires'];
}

/**
 * Recenser les surnoms de table_objet
 * @return array
 */
function lister_tables_objets_surnoms(){
	static $surnoms = null;
	static $md5 = null;
	if (!$surnoms
	  OR $md5 != lister_tables_objets_sql('::md5')){
		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
		// pour compatibilite, car il faut dorenavent utiliser
		// declarer_table_objets_sql
		$surnoms = pipeline('declarer_tables_objets_surnoms',
			array(
				# pour les modeles
				# a enlever ?
				'doc' => 'documents',
				'img' => 'documents',
				'emb' => 'documents',
			));
		$infos_tables = lister_tables_objets_sql();
		foreach($infos_tables as $t=>$infos){
			// cas de base type=>table
			// et preg_replace(',^spip_|^id_|s$,',table)=>table
			if ($infos['table_objet']){ // securite, si la fonction est appelee trop tot, c'est vide
				// optimisations pour table_objet
				//$surnoms[$infos['type']] = $infos['table_objet'];
				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['table_objet'];
				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['table_objet'];
				if (is_array($infos['table_objet_surnoms']) AND count($infos['table_objet_surnoms']))
					foreach($infos['table_objet_surnoms'] as $surnom)
						$surnoms[$surnom] = $infos['table_objet'];
			}
		}
		$md5 = lister_tables_objets_sql('::md5');
	}
	return $surnoms;
}

/**
 * Recenser les surnoms de table_objet
 * @return array
 */
function lister_types_surnoms(){
	static $surnoms = null;
	static $md5 = null;
	if (!$surnoms
	  OR $md5 != lister_tables_objets_sql('::md5')){
		// passer dans un pipeline qui permet aux plugins de declarer leurs exceptions
		// pour compatibilite, car il faut dorenavent utiliser
		// declarer_table_objets_sql
		$surnoms = pipeline('declarer_type_surnoms', array('racine-site'=>'site'));
		$infos_tables = lister_tables_objets_sql();
		foreach($infos_tables as $t=>$infos){
			if ($infos['type']){ // securite, si la fonction est appelee trop tot, c'est vide
				// optimisations pour objet_type
				//$surnoms[$infos['type']] = $infos['type'];
				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['table_objet'])] = $infos['type'];
				$surnoms[preg_replace(',^spip_|^id_|s$,', '', $infos['type'])] = $infos['type'];
				// surnoms declares
				if (is_array($infos['type_surnoms']) AND count($infos['type_surnoms']))
					foreach($infos['type_surnoms'] as $surnom)
						$surnoms[$surnom] = $infos['type'];
			}
		}
		$md5 = lister_tables_objets_sql('::md5');
	}
	return $surnoms;
}

function lister_tables_spip($serveur=''){
	static $tables = array();
	if (!isset($tables[$serveur])){
		$tables[$serveur] = array();
		if (!function_exists("sql_alltable"))
			include_spip("base/abstract_sql");
		$ts = sql_alltable(null,$serveur); // toutes les tables "spip_" (ou prefixe perso)
		$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0];
		$spip = $connexion['prefixe'] . '_';
		foreach ($ts as $t){
			$t = substr($t,strlen($spip));
			$tables[$serveur]["spip_$t"] = $t;
		}
	}
	return $tables[$serveur];
}

function lister_toutes_tables($serveur){
	static $tables = array();
	if (!isset($tables[$serveur])){
		$tables[$serveur] = array();
		if (!function_exists("sql_alltable"))
			include_spip("base/abstract_sql");
		$ts = sql_alltable('%',$serveur); // toutes les tables
		foreach ($ts as $t){
			$tables[$serveur][$t] = $t;
		}
	}
	return $tables[$serveur];
}
 
/**
 * Retrouve le nom d'objet à partir de la table
 * 
 * - spip_articles -> articles
 * - id_article    -> articles
 * - article       -> articles
 *
 * @api
 * @param string $type
 *     Nom de la table SQL (le plus souvent)
 *     Tolère un nom de clé primaire.
 * @param string $serveur
 *     Nom du connecteur
 * @return string
 *     Nom de l'objet
**/
function table_objet($type,$serveur='') {
	$surnoms = lister_tables_objets_surnoms();
	$type = preg_replace(',^spip_|^id_|s$,', '', $type);
	if (!$type) return;
	if (isset($surnoms[$type]))
		return $surnoms[$type];

	if ($serveur!==false){
		$t=lister_tables_spip($serveur);
		$trouver_table = charger_fonction('trouver_table', 'base');
		$typetrim = rtrim($type,'s')."s";
		if (
		  (isset($t[$typetrim]) OR in_array($typetrim,$t))
		  AND ($desc = $trouver_table(rtrim($type,'s')."s",$serveur))
		  )
			return $desc['id_table'];
		elseif (
			(isset($t[$type]) OR in_array($type,$t))
			AND ($desc = $trouver_table($type,$serveur))
		  )
			return $desc['id_table'];

		spip_log( 'table_objet('.$type.') calculee sans verification');
	}

	return rtrim($type,'s')."s"; # cas historique ne devant plus servir, sauf si $serveur=false
}

/**
 * Retrouve la table sql à partir de l'objet ou du type
 *
 * - articles    -> spip_articles
 * - article     -> spip_articles
 * - id_article  -> spip_articles
 *
 * @api
 * @param string $type
 *     Nom ou type de l'objet
 *     Tolère un nom de clé primaire.
 * @param string $serveur
 *     Nom du connecteur
 * @return string
 *     Nom de la table SQL
**/
function table_objet_sql($type,$serveur='') {
	global $table_des_tables;
	$nom = table_objet($type, $serveur);
	if (!isset($table_des_tables['articles'])) // eviter de multiples inclusions
		include_spip('public/interfaces');
	if (isset($table_des_tables[$nom])) {
		$nom = $table_des_tables[$nom];
		$nom = "spip_$nom";
	}
	else {
		$infos_tables = lister_tables_objets_sql();
		if (isset($infos_tables["spip_$nom"]))
			$nom = "spip_$nom";
		elseif($serveur!==false) {
			$t=lister_tables_spip($serveur);
			if (isset($t[$nom]) OR in_array($nom,$t)){
				$trouver_table = charger_fonction('trouver_table', 'base');
				if ($desc = $trouver_table($nom,$serveur))
					return $desc['table_sql'];
			}
		}
	}

	return $nom ;
}

/**
 * Retrouve la clé primaire à partir du nom d'objet ou de table
 * 
 * - articles      -> id_article
 * - article       -> id_article
 * - spip_articles -> id_article
 *
 * @api
 * @param string $type
 *     Nom de la table SQL ou de l'objet
 * @param string $serveur
 *     Nom du connecteur
 * @return string
 *     Nom de la clé primaire
**/
function id_table_objet($type,$serveur='') {
	static $trouver_table = null;
	$type = objet_type($type,$serveur);
	if (!$type) return;
	$t = table_objet($type);
	if (!$trouver_table)
		$trouver_table = charger_fonction('trouver_table', 'base');

	$ts=lister_tables_spip($serveur);
	if (in_array($t,$ts)
	  OR in_array($t,lister_toutes_tables($serveur))){
		$desc = $trouver_table($t,$serveur);
		if (isset($desc['key']['PRIMARY KEY']))
			return $desc['key']['PRIMARY KEY'];
		if (!$desc OR isset($desc['field']["id_$type"]))
			return "id_$type";
		// sinon renvoyer le premier champ de la table...
		$keys = array_keys($desc['field']);
		return array_shift($keys);
	}
	return "id_$type";
}

/**
 * Retrouve le type d'objet à partir du nom d'objet ou de table
 * 
 * - articles      -> article
 * - spip_articles -> article
 * - id_article    -> article
 *
 * @api
 * @param string $table_objet
 *     Nom de l'objet ou de la table SQL
 * @param string $serveur
 *     Nom du connecteur
 * @return string
 *     Type de l'objet
**/
function objet_type($table_objet, $serveur=''){
	if (!$table_objet) return;
	$surnoms = lister_types_surnoms();

	// scenario de base
	// le type est decline a partir du nom de la table en enlevant le prefixe eventuel
	// et la marque du pluriel
	// on accepte id_xx en entree aussi
	$type = preg_replace(',^spip_|^id_|s$,', '', $table_objet);
	if (isset($surnoms[$type]))
		return $surnoms[$type];

	// securite : eliminer les caracteres non \w
	$type = preg_replace(',[^\w-],','',$type);

	// si le type redonne bien la table c'est bon
	// oui si table_objet ressemblait deja a un type
	if ( $type==$table_objet
		OR (table_objet($type,$serveur)==$table_objet)
	  OR (table_objet_sql($type,$serveur)==$table_objet))
	  return $type;

	// si on ne veut pas chercher en base
	if ($serveur===false)
		return $type;

	// sinon on passe par la cle primaire id_xx pour trouver le type
	// car le s a la fin est incertain
	// notamment en cas de pluriel derogatoire
	// id_jeu/spip_jeux id_journal/spip_journaux qui necessitent tout deux
	// une declaration jeu => jeux, journal => journaux
	// dans le pipeline declarer_tables_objets_surnoms
	$trouver_table = charger_fonction('trouver_table', 'base');
	$ts=lister_tables_spip($serveur);
	if (in_array($table_objet,$ts))
		$desc = $trouver_table($table_objet);
	if (!$desc AND in_array($table_objet=table_objet($type,$serveur),$ts))
		$desc = $trouver_table($table_objet,$serveur);
	// si le type est declare : bingo !
	if ($desc AND isset($desc['type']))
			return $desc['type'];

	// on a fait ce qu'on a pu
	return $type;
}

/**
 * Determininer si un objet est publie ou non
 * 
 * On se base pour cela sur sa declaration de statut
 * pour des cas particuliers non declarables, on permet de fournir une fonction
 * base_xxxx_test_si_publie qui sera appele par la fonction
 *
 * @param string $objet
 * @param int $id_objet
 * @param string $serveur
 * @return bool
 */
function objet_test_si_publie($objet,$id_objet, $serveur=''){
	// voir si une fonction est definie pour faire le boulot
	// elle a la priorite dans ce cas
	if ($f = charger_fonction($objet."_test_si_publie","base",true))
		return $f($objet,$id_objet, $serveur);

	// sinon on se fie a la declaration de l'objet si presente
	$id_table = $table_objet = table_objet($objet);
	$id_table_objet = id_table_objet($objet, $serveur);
	$trouver_table = charger_fonction('trouver_table', 'base');
	if ($desc = $trouver_table($table_objet, $serveur)
		AND isset($desc['statut'])
	  AND $desc['statut']){
		$boucle = new Boucle();
		$boucle->show = $desc;
		$boucle->nom = 'objet_test_si_publie';
		$boucle->id_boucle = $id_table;
		$boucle->id_table = $id_table;
		$boucle->sql_serveur = $serveur;
		$boucle->select[] = $id_table_objet;
		$boucle->from[$table_objet] = table_objet_sql($objet, $serveur);
		$boucle->where[] = $id_table.".".$id_table_objet.'='.intval($id_objet);

		include_spip('public/compiler');
		include_spip('public/composer');
		instituer_boucle($boucle, false, true);
		$res = calculer_select($boucle->select,$boucle->from,$boucle->from_type,$boucle->where,$boucle->join,$boucle->group,$boucle->order,$boucle->limit,$boucle->having,$table_objet,$id_table,$serveur);
		if (sql_fetch($res))
			return true;
		return false;
	}

	// si pas d'info statut ni de fonction : l'objet est publie
	return true;
}
trouver_table.php000066600000015131152502550120010134 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

/**
 * Gestion de l'obtention des descriptions de tables SQL
 *
 * @package SPIP\SQL\Tables
**/
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('base/objets');

/**
 * Retourne la description d'une table SQL
 *
 * Cela sert notamment au moment de la compilation des boucles, critères et balise.
 * 
 * Les champs et clés de la tables sont retrouvés prioritairement via le
 * gestionnaire de base de données. Les descriptions sont complétées,
 * pour les tables éditoriales, des informations déclarées ou construites
 * par la déclaration des objets éditoriaux.
 *  
 * @example
 *     $trouver_table = charger_fonction('trouver_table', 'base');
 *     $desc = $trouver_table('spip_groupes_mots');
 * 
 * Cette fonction intervient à la compilation, mais aussi pour la balise
 * contextuelle EXPOSE ou certains critères.
 * 
 * L'ensemble des descriptions de table d'un serveur est stocké dans un
 * fichier cache/sql_desc.txt par soucis de performance. Un appel
 * avec $nom vide est une demande explicite de vidange de ce cache
 *
 * @see lister_tables_objets_sql()
 * 
 * @api
 * @param string $nom
 *     Nom de la table
 *     Vide '' demande de vider le cache des discriptions
 * @param string $serveur
 *     Nom du connecteur
 * @param bool $table_spip
 *     Indique s'il faut transformer le préfixe de table
 * @return array|bool
 *     false si table introuvable
 *     tableau de description de la table sinon, en particulier :
 *     - field : tableau des colonnes SQL et leur description (comme dans serial.php ou objets.php)
 *     - key   : tableau des KEY (comme dans serial.php ou objets.php)
 *     - table et table_sql : nom de la table (avec spip_ en préfixe)
 *     - id_table : nom SPIP de la table (type de boucle)
 *                  le compilateur produit  FROM $r['table'] AS $r['id_table']
 *     - Toutes les autres informations des objets éditoriaux si la table est l'un d'eux.
 *     
 *
**/
function base_trouver_table_dist($nom, $serveur='', $table_spip = true){
	static $nom_cache_desc_sql=array();
	global $tables_principales, $tables_auxiliaires, $table_des_tables;

	if (!spip_connect($serveur)
	OR !preg_match('/^[a-zA-Z0-9._-]*/',$nom))
		return null;

	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
	$objets_sql = lister_tables_objets_sql("::md5");

	// le nom du cache depend du serveur mais aussi du nom de la db et du prefixe
	// ce qui permet une auto invalidation en cas de modif manuelle du fichier
	// de connexion, et tout risque d'ambiguite
	if (!isset($nom_cache_desc_sql[$serveur][$objets_sql])){
		$nom_cache_desc_sql[$serveur][$objets_sql] =
		  _DIR_CACHE . 'sql_desc_'
		  . ($serveur ? "{$serveur}_":"")
		  . substr(md5($connexion['db'].":".$connexion['prefixe'].":$objets_sql"),0,8)
			.'.txt';
		// nouveau nom de cache = nouvelle version en memoire
		unset($connexion['tables']);
	}

	// un appel avec $nom vide est une demande explicite de vidange du cache des descriptions
	if (!$nom){
		spip_unlink($nom_cache_desc_sql[$serveur][$objets_sql]);
		$connexion['tables'] = array();
		return null;
	}

	$nom_sql = $nom;
	if (preg_match('/\.(.*)$/', $nom, $s))
		$nom_sql = $s[1];
	else
		$nom_sql = $nom;

	$fdesc = $desc = '';
	$connexion = &$GLOBALS['connexions'][$serveur ? $serveur : 0];

	// base sous SPIP: gerer les abreviations explicites des noms de table
	if ($connexion['spip_connect_version']) {
		if ($table_spip AND isset($table_des_tables[$nom])) {
			$nom = $table_des_tables[$nom];
			$nom_sql = 'spip_' . $nom;
		}
	}

	// si c'est la premiere table qu'on cherche
	// et si on est pas explicitement en recalcul
	// on essaye de recharger le cache des decriptions de ce serveur
	// dans le fichier cache
	if (!isset($connexion['tables'][$nom_sql])
	  AND defined('_VAR_MODE') AND _VAR_MODE!=='recalcul'
	  AND (!isset($connexion['tables']) OR !$connexion['tables'])) {
		if (lire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],$desc_cache)
		  AND $desc_cache=unserialize($desc_cache))
		  $connexion['tables'] = $desc_cache;
	}
	if ($table_spip AND !isset($connexion['tables'][$nom_sql])) {

		if (isset($tables_principales[$nom_sql]))
			$fdesc = $tables_principales[$nom_sql];
		// meme si pas d'abreviation declaree, trouver la table spip_$nom
		// si c'est une table principale,
		// puisqu'on le fait aussi pour les tables auxiliaires
		elseif ($nom_sql==$nom AND isset($tables_principales['spip_' .$nom])){
			$nom_sql = 'spip_' . $nom;
			$fdesc = &$tables_principales[$nom_sql];
		}
		elseif (isset($tables_auxiliaires[$n=$nom])
		  OR isset($tables_auxiliaires[$n='spip_'.$nom])) {
			$nom_sql = $n;
			$fdesc = &$tables_auxiliaires[$n];
		}  # table locale a cote de SPIP, comme non SPIP:
	}
	if (!isset($connexion['tables'][$nom_sql])) {

		// La *vraie* base a la priorite
		$desc = sql_showtable($nom_sql, $table_spip, $serveur);
		if (!$desc OR !$desc['field']) {
			if (!$fdesc) {
				spip_log("trouver_table: table inconnue '$serveur' '$nom'",_LOG_INFO_IMPORTANTE);
				return null;
			}
			// on ne sait pas lire la structure de la table :
			// on retombe sur la description donnee dans les fichiers spip
			$desc = $fdesc;
		}
		else {
			$desc['exist'] = true;
		}

		$desc['table'] = $desc['table_sql'] = $nom_sql;
		$desc['connexion']= $serveur;

		// charger les infos declarees pour cette table
		// en lui passant les infos connues
		// $desc est prioritaire pour la description de la table
		$desc = array_merge(lister_tables_objets_sql($nom_sql,$desc),$desc);

		// si tables_objets_sql est bien fini d'init, on peut cacher
		$connexion['tables'][$nom_sql] = $desc;
		$res = &$connexion['tables'][$nom_sql];
		// une nouvelle table a ete decrite
		// mettons donc a jour le cache des descriptions de ce serveur
		if (is_writeable(_DIR_CACHE))
			ecrire_fichier($nom_cache_desc_sql[$serveur][$objets_sql],serialize($connexion['tables']),true);
	}
	else
		$res = &$connexion['tables'][$nom_sql];

	// toujours retourner $nom dans id_table
	$res['id_table']=$nom;

	return $res;
}
?>
restaurer.php000066600000006467152503073450007316 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined("_ECRIRE_INC_VERSION")) return;

include_spip('inc/dump');
include_spip('inc/actions');

function base_restaurer_dist($titre='', $reprise=false) {
	$status_file = _DUMP_STATUS_FILE;
	$status_file = _DIR_TMP.basename($status_file).".txt";
	if (!lire_fichier($status_file, $status)
		OR !$status = unserialize($status)) {
	}
	else {
		$redirect = parametre_url(generer_action_auteur('restaurer',_DUMP_STATUS_FILE),"step",intval(_request('step')+1),'&');

		$timeout = ini_get('max_execution_time');
		// valeur conservatrice si on a pas reussi a lire le max_execution_time
		if (!$timeout) $timeout=30; // parions sur une valeur tellement courante ...
		$max_time = time()+$timeout/2;
		
		include_spip('inc/minipres');
		@ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure

		$titre = _T('dump:restauration_en_cours') . " (".count($status['tables']).") ";
		$balise_img = chercher_filtre('balise_img');
		$titre .= $balise_img(chemin_image('searching.gif'));
		echo ( install_debut_html($titre));
		// script de rechargement auto sur timeout
		echo http_script("window.setTimeout('location.href=\"".$redirect."\";',".($timeout*1000).")");
		echo "<div style='text-align: left'>\n";

		dump_serveur($status['connect']);
		spip_connect('dump');

		// au premier coup on ne fait rien sauf afficher l'ecran de sauvegarde
		if (_request('step')) {
			$options = array(
				'callback_progression' => 'dump_afficher_progres',
				'max_time' => $max_time,
				'no_erase_dest' => lister_tables_noerase(),
				'where' => $status['where']?$status['where']:array(),
				'desc_tables_dest' => array()
			);
			if ($desc = sql_getfetsel('valeur','spip_meta',"nom='dump_structure_temp'",'','','','','dump')
				AND $desc = unserialize($desc))
				$options['desc_tables_dest'] = $desc;
			#var_dump(sql_allfetsel('nom,valeur','spip_meta',"",'','','','','dump'));
			#die();
			$res = base_copier_tables($status_file, $status['tables'], 'dump', '', $options);
		}
		else {
			// mais on en profite pour reparer les version base pour etre sur de ne pas les perdre
			sql_updateq("spip_meta",array('impt'=>'oui'),"nom='version_installee'",'','dump');
			sql_updateq("spip_meta",array('impt'=>'oui'),"nom LIKE '%_base_version'",'','dump');
		}
		
		echo ( "</div>\n");

		if (!$res)
			echo dump_relance($redirect);
		
		echo (install_fin_html());
		ob_end_flush();
		flush();

		if (!$res)
			exit;
		
		// quand on sort de $export avec true c'est qu'on a fini
		dump_end(_DUMP_STATUS_FILE,'restaurer');
		include_spip('inc/headers');
		echo redirige_formulaire(generer_url_ecrire("restaurer",'status='._DUMP_STATUS_FILE,'',true, true));

	}
}


?>
forum.php000066600000012607152503076340006424 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Interfaces de la table forum pour le compilateur
 *
 * @param array $interfaces
 * @return array $interfaces
 */
function forum_declarer_tables_interfaces($interfaces){

	$interfaces['table_des_tables']['forums']='forum';

	$interfaces['exceptions_des_tables']['forums']['date']='date_heure';
	$interfaces['exceptions_des_tables']['forums']['nom']='auteur';
	$interfaces['exceptions_des_tables']['forums']['email']='email_auteur';

	// il ne faut pas essayer de chercher le forum du mot cle, mais bien le mot cle associe au forum
	$interfaces['exceptions_des_jointures']['spip_forum']['id_secteur'] = array('spip_articles','id_secteur');
	$interfaces['exceptions_des_jointures']['spip_forum']['id_mot'] = array('spip_mots','id_mot');
	$interfaces['exceptions_des_jointures']['spip_forum']['titre_mot'] = array('spip_mots','titre');
	$interfaces['exceptions_des_jointures']['spip_forum']['type_mot'] = array('spip_mots','type');
	$interfaces['exceptions_des_jointures']['spip_forum']['id_groupe'] = array('spip_mots','id_groupe');

	
	#$interfaces['table_titre']['forums']= "titre, '' AS lang";
	#$interfaces['table_date']['forums']='date_heure';

	$interfaces['table_statut']['spip_forum'][] = array('champ'=>'statut','publie'=>'publie','previsu'=>'publie,prop','exception'=>'statut');

	$interfaces['table_des_traitements']['PARAMETRES_FORUM'][]= 'spip_htmlspecialchars(%s)';
	$interfaces['table_des_traitements']['TEXTE']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_RACCOURCIS)."))";
	$interfaces['table_des_traitements']['TITRE']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_TYPO)."))";
	$interfaces['table_des_traitements']['NOTES']['forums']= "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_RACCOURCIS)."))";
	$interfaces['table_des_traitements']['NOM_SITE']['forums']=  "liens_nofollow(safehtml(".str_replace("%s","interdit_html(%s)",_TRAITEMENT_TYPO)."))";
	$interfaces['table_des_traitements']['URL_SITE']['forums']= 'safehtml(vider_url(%s))';
	$interfaces['table_des_traitements']['AUTEUR']['forums']= 'liens_nofollow(safehtml(vider_url(%s)))';
	$interfaces['table_des_traitements']['EMAIL_AUTEUR']['forums']= 'safehtml(vider_url(%s))';

	return $interfaces;
}

/**
 * Déclaration de la table spip_forum et de l'objet forum
 *
 * @param array $tables Tableau des objets déclarés
 * @return array $tables Tableau des objets complété
 */
function forum_declarer_tables_objets_sql($tables){
	$tables['spip_forum'] = array(
		'table_objet'=>'forums', # ??? hum hum redevient spip_forum par table_objet_sql mais casse par un bete "spip_".table_objet()
		'type'=>'forum',
		'url_voir'=>'controler_forum',
		'url_edit'=>'controler_forum',
		'editable'=>'non',
		'principale' => 'oui',
		'page'=>'', // pas de page editoriale pour un forum

		'texte_retour' => 'icone_retour',
		'texte_objets' => 'forum:forum',
		'texte_objet' => 'forum:forum',
		'info_aucun_objet'=> 'forum:aucun_message_forum',
		'info_1_objet' => 'forum:info_1_message_forum',
		'info_nb_objets' => 'forum:info_nb_messages_forum',
		'titre' => "titre, '' AS lang",
		'date' => 'date_heure',

		'champs_editables' => array('titre', 'texte', 'nom_site', 'url_site'),

		'field'=> array(
			"id_forum"	=> "bigint(21) NOT NULL",
			"id_objet"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"objet"		=> "VARCHAR (25) DEFAULT '' NOT NULL",
			"id_parent"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"id_thread"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"date_heure"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
			"date_thread"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
			"titre"	=> "text DEFAULT '' NOT NULL",
			"texte"	=> "mediumtext DEFAULT '' NOT NULL",
			"auteur"	=> "text DEFAULT '' NOT NULL",
			"email_auteur"	=> "text DEFAULT '' NOT NULL",
			"nom_site"	=> "text DEFAULT '' NOT NULL",
			"url_site"	=> "text DEFAULT '' NOT NULL",
			"statut"	=> "varchar(8) DEFAULT '0' NOT NULL",
			"ip"	=> "varchar(40) DEFAULT '' NOT NULL",
			"maj"	=> "TIMESTAMP",
			"id_auteur"	=> "bigint DEFAULT '0' NOT NULL"
		),
		'key' => array(
			"PRIMARY KEY"	=> "id_forum",
			"KEY id_auteur"	=> "id_auteur",
			"KEY id_parent"	=> "id_parent",
			"KEY id_thread"	=> "id_thread",
			"KEY optimal" => "statut,id_parent,id_objet,objet,date_heure"
		),
		'join' => array(
			"id_forum"=>"id_forum",
			"id_parent"=>"id_parent",
			"id_objet"=>"id_objet",
			"objet"=>"objet",
			"id_auteur"=>"id_auteur",
		),
		'rechercher_champs' => array(
	    	'titre' => 3, 'texte' => 1, 'auteur' => 2, 'email_auteur' => 2, 'nom_site' => 1, 'url_site' => 1
		),
	);

	// jointures sur les forum pour tous les objets
	$tables[]['tables_jointures'][]= 'forums';

	return $tables;
}

?>
medias.php000066600000022552152503076400006533 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Interfaces des tables breves pour le compilateur
 *
 * @param array $interfaces
 * @return array
 */
function medias_declarer_tables_interfaces($interfaces) {
	$interfaces['table_des_tables']['documents']='documents';
	$interfaces['table_des_tables']['types_documents']='types_documents';

	$interfaces['exceptions_des_tables']['documents']['type_document']=array('types_documents', 'titre');
	$interfaces['exceptions_des_tables']['documents']['extension_document']=array('types_documents', 'extension');
	$interfaces['exceptions_des_tables']['documents']['mime_type']=array('types_documents', 'mime_type');
	$interfaces['exceptions_des_tables']['documents']['media_document']=array('types_documents', 'media');

	$interfaces['exceptions_des_jointures']['spip_documents']['id_forum']=array('spip_documents_liens','id_forum');
	$interfaces['exceptions_des_jointures']['spip_documents']['vu']=array('spip_documents_liens', 'vu');
	$interfaces['table_date']['types_documents']='date';

	$interfaces['table_des_traitements']['FICHIER']['documents']= 'get_spip_doc(%s)';

	return $interfaces;
}


/**
 * Table principale spip_documents et spip_types_documents
 *
 * @param array $tables_principales
 * @return array
 */
function medias_declarer_tables_principales($tables_principales) {

	$spip_types_documents = array(
			"extension"	=> "varchar(10) DEFAULT '' NOT NULL",
			"titre"	=> "text DEFAULT '' NOT NULL",
			"descriptif"	=> "text DEFAULT '' NOT NULL",
			"mime_type"	=> "varchar(100) DEFAULT '' NOT NULL",
			"inclus"	=> "ENUM('non', 'image', 'embed') DEFAULT 'non'  NOT NULL",
			"upload"	=> "ENUM('oui', 'non') DEFAULT 'oui'  NOT NULL",
			"media_defaut" => "varchar(10) DEFAULT 'file' NOT NULL",
			"maj"	=> "TIMESTAMP");

	$spip_types_documents_key = array(
			"PRIMARY KEY"	=> "extension",
			"KEY inclus"	=> "inclus");

	$tables_principales['spip_types_documents']	=
		array('field' => &$spip_types_documents, 'key' => &$spip_types_documents_key);

	return $tables_principales;
}

/**
 * Table des liens documents-objets spip_documents_liens
 * @param array $tables_auxiliaires
 * @return array
 */
function medias_declarer_tables_auxiliaires($tables_auxiliaires) {

	$spip_documents_liens = array(
			"id_document"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"id_objet"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"objet"	=> "VARCHAR (25) DEFAULT '' NOT NULL",
			"vu"	=> "ENUM('non', 'oui') DEFAULT 'non' NOT NULL");

	$spip_documents_liens_key = array(
			"PRIMARY KEY"		=> "id_document,id_objet,objet",
			"KEY id_document"	=> "id_document",
			"KEY id_objet"	=> "id_objet",
			"KEY objet"	=> "objet",
	);

	$tables_auxiliaires['spip_documents_liens'] = array(
		'field' => &$spip_documents_liens,
		'key' => &$spip_documents_liens_key);

	return $tables_auxiliaires;
}

/**
 * Declarer le surnom des breves
 *
 * @param array $surnoms
 * @return array
 */
function medias_declarer_tables_objets_surnoms($surnoms) {
	$surnoms['type_document'] = "types_documents"; # hum
	#$surnoms['extension'] = "types_documents"; # hum
	#$surnoms['type'] = "types_documents"; # a ajouter pour id_table_objet('type')=='extension' ?
	return $surnoms;
}

function medias_declarer_tables_objets_sql($tables){
	$tables['spip_articles']['champs_versionnes'][] = 'jointure_documents';
	$tables['spip_documents'] = array(
		'table_objet_surnoms'=>array('doc','img','emb'),
		'type_surnoms' => array(),
		'url_voir' => 'document_edit',
		'url_edit' => 'document_edit',
		'page'=>'',
		'texte_retour' => 'icone_retour',
		'texte_objets' => 'medias:objet_documents',
		'texte_objet' => 'medias:objet_document',
		'texte_modifier' => 'medias:info_modifier_document',
		'info_aucun_objet'=> 'medias:aucun_document',
		'info_1_objet' => 'medias:un_document',
		'info_nb_objets' => 'medias:des_documents',
		'titre' => "CASE WHEN length(titre)>0 THEN titre ELSE fichier END as titre, '' AS lang",
		'date' => 'date',
		'principale'=>'oui',
		'field' => array(
			"id_document"	=> "bigint(21) NOT NULL",
			"id_vignette"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"extension"	=> "VARCHAR(10) DEFAULT '' NOT NULL",
			"titre"	=> "text DEFAULT '' NOT NULL",
			"date"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
			"descriptif"	=> "text DEFAULT '' NOT NULL",
			"fichier"	=> "text NOT NULL DEFAULT ''",
			"taille"	=> "bigint",
			"largeur"	=> "integer",
			"hauteur"	=> "integer",
			"media" => "varchar(10) DEFAULT 'file' NOT NULL",
			"mode"	=> "varchar(10) DEFAULT 'document' NOT NULL",
			"distant"	=> "VARCHAR(3) DEFAULT 'non'",
			"statut" => "varchar(10) DEFAULT '0' NOT NULL",
			"credits" => "varchar(255) DEFAULT '' NOT NULL",
			"date_publication" => "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
			"brise" => "tinyint DEFAULT 0",
			"maj"	=> "TIMESTAMP"
		),
		'key' => array(
			"PRIMARY KEY"	=> "id_document",
			"KEY id_vignette"	=> "id_vignette",
			"KEY mode"	=> "mode",
			"KEY extension"	=> "extension"
		),
		'join' => array(
			"id_document"=>"id_document",
			"extension"=>"extension"
		),
		'statut'=> array(
			array(
				'champ' => 'statut',
				'publie' => 'publie',
				'previsu' => 'publie,prop,prepa',
				'post_date' => 'date_publication',
				'exception' => array('statut','tout')
			)
		),
		'tables_jointures' => array('types_documents'),
		'rechercher_champs' => array(
			'titre' => 3, 'descriptif' => 1, 'fichier' => 1, 'credits' => 1,
		),
		'champs_editables' => array('titre', 'descriptif', 'date', 'taille', 'largeur','hauteur','mode','credits','fichier','distant','extension', 'id_vignette', 'media'),
		'champs_versionnes' => array('id_vignette', 'titre', 'descriptif', 'hauteur', 'largeur', 'mode','credits','distant'),
		'modeles' => array('document','doc','img','emb','image','video','text','audio','application'),
	);

	// jointures sur les forum pour tous les objets
	$tables[]['tables_jointures'][]= 'documents_liens';

	// recherche jointe sur les documents pour les articles et rubriques
	$tables['spip_articles']['rechercher_jointures']['document'] = array('titre' => 2, 'descriptif' => 1);
	$tables['spip_rubriques']['rechercher_jointures']['document'] = array('titre' => 2, 'descriptif' => 1);
	return $tables;
}

/**
 * Creer la table des types de document
 *
 * http://code.spip.net/@creer_base_types_doc
 *
 * @param string $serveur
 * @return void
 */
function creer_base_types_doc($serveur='', $champ_media="media_defaut") {
	global $tables_images, $tables_sequences, $tables_documents, $tables_mime;
	include_spip('base/typedoc');
	include_spip('base/abstract_sql');

	// charger en memoire tous les types deja definis pour limiter les requettes
	$rows = sql_allfetsel('mime_type,titre,inclus,extension,'.$champ_media.',upload,descriptif','spip_types_documents','','','','','',$serveur);
	$deja = array();
	foreach ($rows as $k=>$row){
		$deja[$row['extension']] = &$rows[$k];
	}

	$insertions = array();
	$updates = array();

	foreach ($tables_mime as $extension => $type_mime) {
		if (isset($tables_images[$extension])) {
			$titre = $tables_images[$extension];
			$inclus='image';
		}
		else if (isset($tables_sequences[$extension])) {
			$titre = $tables_sequences[$extension];
			$inclus='embed';
		}
		else {
			$inclus='non';
			if (isset($tables_documents[$extension]))
				$titre = $tables_documents[$extension];
			else
				$titre = '';
		}

		// type de media
	  $media = "file";
	  if (preg_match(",^image/,",$type_mime) OR in_array($type_mime,array('application/illustrator')))
		  $media = "image";
	  elseif (preg_match(",^audio/,",$type_mime))
		  $media = "audio";
	  elseif (preg_match(",^video/,",$type_mime) OR in_array($type_mime,array('application/ogg','application/x-shockwave-flash','application/mp4')))
		  $media = "video";

		$set = array(
		        'mime_type' => $type_mime,
		        'titre' => $titre,
		        'inclus' => $inclus,
		        'extension' => $extension,
		        $champ_media => $media,
		        'upload' => 'oui',
		        'descriptif' => '',
					);
		if (!isset($deja[$extension])){
			$insertions[] = $set;
		}
		elseif (array_diff($deja[$extension],$set)){
			$updates[$extension] = $set;
		}
	}

	if (count($updates)){
		foreach ($updates as $extension=>$set){
			sql_updateq('spip_types_documents',$set,'extension='.sql_quote($extension));
		}
	}

	if ($insertions)
		sql_insertq_multi('spip_types_documents', $insertions, '', $serveur);

}



/**
 * Optimiser la base de donnee en supprimant les liens orphelins
 *
 * @param int $n
 * @return int
 */
function medias_optimiser_base_disparus($flux){

	include_spip('action/editer_liens');
	// optimiser les liens morts :
	// entre documents vers des objets effaces
	// depuis des documents effaces
	$flux['data'] += objet_optimiser_liens(array('document'=>'*'),'*');
	// on ne nettoie volontairement pas automatiquement les documents orphelins

	return $flux;
}

?>typedoc.php000066600000032457152503076400006745 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

global $tables_images, $tables_sequences, $tables_documents, $tables_mime, $mime_alias;

$tables_images = array(
			// Images reconnues par PHP
			'jpg' => 'JPEG',
			'png' => 'PNG',
			'gif' => 'GIF',

			// Autres images (peuvent utiliser le tag <img>)
			'bmp' => 'BMP',
			);

// Multimedia (peuvent utiliser le tag <embed>)

$tables_sequences = array(
			'aac' => 'Advanced Audio Coding',
			'ac3' => 'AC-3 Compressed Audio',
			'aifc' => 'Compressed AIFF Audio',
			'aiff' => 'AIFF',
			'amr' => 'Adaptive Multi-Rate Audio',
			'anx' => 'Annodex',
			'ape' => 'Monkey\'s Audio File',
			'axa' => 'Annodex Audio',
			'axv' => 'Annodex Video',
			'asf' => 'Windows Media',
			'avi' => 'AVI',
			'dv'	=> 'Digital Video',
			'f4a' => 'Audio for Adobe Flash Player',
			'f4b' => 'Audio Book for Adobe Flash Player',
			'f4p' => 'Protected Video for Adobe Flash Player',
			'f4v' => 'Video for Adobe Flash Player',
			'flac' => 'Free Lossless Audio Codec',
			'flv' => 'Flash Video',
			'm2p' => 'MPEG-PS',
			'm2ts' => 'BDAV MPEG-2 Transport Stream',
			'm4a' => 'MPEG4 Audio',
			'm4b' => 'MPEG4 Audio',
			'm4p' => 'MPEG4 Audio',
			'm4r' => 'iPhone Ringtone',
			'm4v' => 'MPEG4 Video',
			'mid' => 'Midi',
			'mng' => 'MNG',
			'mka' => 'Matroska Audio',
			'mkv' => 'Matroska Video',
			'mov' => 'QuickTime',
			'mp3' => 'MP3',
			'mp4' => 'MPEG4',
			'mpc' => 'Musepack',
			'mpg' => 'MPEG',
			'mts' => 'AVCHD MPEG-2 transport stream',
			'oga' => 'Ogg Audio',
			'ogg' => 'Ogg Vorbis',
			'ogv' => 'Ogg Video',
			'ogx' => 'Ogg Multiplex',
			'qt' => 'QuickTime',
			'ra' => 'RealAudio',
			'ram' => 'RealAudio',
			'rm' => 'RealAudio',
			'spx' => 'Ogg Speex',
			'svg' => 'Scalable Vector Graphics',
			'svgz' => 'Compressed Scalable Vector Graphic',
			'swf' => 'Flash',
			'tif' => 'TIFF',
			'ts' => 'MPEG transport stream',
			'wav' => 'WAV',
			'webm' => 'WebM',
			'wma' => 'Windows Media Audio',
			'wmv' => 'Windows Media Video',
			'y4m' => 'YUV4MPEG2',
			'3ga' => '3GP Audio File',
			'3gp' => '3rd Generation Partnership Project'
		);

// Documents varies
$tables_documents = array(
			'7z' => '7 Zip',
			'abw' => 'Abiword',
			'ai' => 'Adobe Illustrator',
			'asx' => 'Advanced Stream Redirector',
			'bib' => 'BibTeX',
			'bz2' => 'BZip',
			'bin' => 'Binary Data',
			'blend' => 'Blender',
			'c' => 'C source',
			'cls' => 'LaTeX Class',
			'csl' => 'Citation Style Language',
			'css' => 'Cascading Style Sheet',
			'csv' => 'Comma Separated Values',
			'deb' => 'Debian',
			'doc' => 'Word',
			'dot' => 'Word Template',
			'djvu' => 'DjVu',
			'dvi' => 'LaTeX DVI',
			'emf' => 'Enhanced Metafile',
			'enl' => 'EndNote Library',
			'ens' => 'EndNote Style',
			'epub' => 'EPUB',
			'eps' => 'PostScript',
			'gpx' => 'GPS eXchange Format',
			'gz' => 'GZ',
			'h' => 'C header',
			'html' => 'HTML',
			'jar' => 'Java Archive',
			'json' => 'JSON',
			'kml' => 'Keyhole Markup Language',
			'kmz' => 'Google Earth Placemark File',
			'lyx' => 'Lyx file',
			'mathml' => 'MathML',
			'mbtiles' => 'MBTiles',
			'm3u' => 'M3U Playlist',
			'm3u8' => 'M3U8 Playlist',
			'm4u' => 'MPEG4 Playlist',
			'pas' => 'Pascal',
			'pdf' => 'PDF',
			'pgn' => 'Portable Game Notation',
			'pls' => 'Playlist',
			'pot' => 'PowerPoint Template',
			'ppt' => 'PowerPoint',
			'ps' => 'PostScript',
			'psd' => 'Photoshop',
			'rar' => 'WinRAR',
			'rdf' => 'Resource Description Framework',
			'ris' => 'RIS',
			'rpm' => 'RedHat/Mandrake/SuSE',
			'rtf' => 'RTF',
			'sdc' => 'StarOffice Spreadsheet',
			'sdd' => 'StarOffice Presentation',
			'sdw' => 'StarOffice Writer document',
			'sit' => 'Stuffit',
			'sla' => 'Scribus',
			'srt' => 'SubRip Subtitle',
			'ssa' => 'SubStation Alpha Subtitle',
			'sty' => 'LaTeX Style Sheet',
			'sxc' => 'OpenOffice.org Calc',
			'sxi' => 'OpenOffice.org Impress',
			'sxw' => 'OpenOffice.org',
			'tar' => 'Tar',
			'tex' => 'LaTeX',
			'tgz' => 'TGZ',
			'torrent' => 'BitTorrent',
			'ttf' => 'TTF Font',
			'txt' => 'Texte',
			'usf' => 'Universal Subtitle Format',
			'wmf' => 'Windows Metafile',
			'wpl' => 'Windows Media Player Playlist',
			'xcf' => 'GIMP multi-layer',
			'xspf' => 'XSPF',
			'xls' => 'Excel',
			'xlt' => 'Excel Template',
			'xml' => 'XML',
			'y4m' => 'YUV4MPEG2',
			'yaml' => 'YAML',
			'zip' => 'Zip',

			// open document format
			
			'odb' => 'OpenDocument Database',
			'odc' => 'OpenDocument Chart',
			'odf' => 'OpenDocument Formula',
			'odg' => 'OpenDocument Graphics',
			'odi' => 'OpenDocument Image',
			'odm' => 'OpenDocument Text-master',
			'odp' => 'OpenDocument Presentation',
			'ods' => 'OpenDocument Spreadsheet',
			'odt' => 'OpenDocument Text',
			'otg' => 'OpenDocument Graphics-template',
			'otp' => 'OpenDocument Presentation-template',
			'ots' => 'OpenDocument Spreadsheet-template',
			'ott' => 'OpenDocument Text-template',


			// Open XML File Formats
			'docm' => 'Word',
			'docx' => 'Word',
			'dotm' => 'Word template',
			'dotx' => 'Word template',

			'potm' => 'Powerpoint template',
			'potx' => 'Powerpoint template',
			'ppam' => 'Powerpoint addin',
			'ppsm' => 'Powerpoint slideshow',
			'ppsx' => 'Powerpoint slideshow',
			'pptm' => 'Powerpoint',
			'pptx' => 'Powerpoint',

			'xlam' => 'Excel',
			'xlsb' => 'Excel binary',
			'xlsm' => 'Excel',
			'xlsx' => 'Excel',
			'xltm' => 'Excel template',
			'xltx' => 'Excel template'
		);

$tables_mime = array(
		// Images reconnues par PHP
		'jpg' => 'image/jpeg',
		'png' => 'image/png',
		'gif' => 'image/gif',

		// Autres images (peuvent utiliser le tag <img>)
		'bmp' => 'image/x-ms-bmp', // pas enregistre par IANA, variante: image/bmp
		'tif' => 'image/tiff',
		
		// Multimedia (peuvent utiliser le tag <embed>)
		'aac' => 'audio/mp4a-latm',
		'ac3' => 'audio/x-aac',
		'aifc' => 'audio/x-aifc',
		'aiff' => 'audio/x-aiff',
		'amr' => 'audio/amr',
		'ape' => 'audio/x-monkeys-audio',
		'asf' => 'video/x-ms-asf',
		'avi' => 'video/x-msvideo',
		'anx' => 'application/annodex',
		'axa' => 'audio/annodex',
		'axv' => 'video/annodex',
		'dv' => 'video/x-dv',
		'f4a' => 'audio/mp4',
		'f4b' => 'audio/mp4',
		'f4p' => 'video/mp4',
		'f4v' => 'video/mp4',
		'flac' => 'audio/x-flac',
		'flv' => 'video/x-flv',
		'm2p' => 'video/MP2P',
		'm2ts' => 'video/MP2T',
		'm4a' => 'audio/mp4a-latm',
		'm4b' => 'audio/mp4a-latm',
		'm4p' => 'audio/mp4a-latm',
		'm4r' => 'audio/aac',
		'm4u' => 'video/vnd.mpegurl',
		'm4v' => 'video/x-m4v',
		'mid' => 'audio/midi',
		'mka' => 'audio/mka',
		'mkv' => 'video/mkv',
		'mng' => 'video/x-mng',
		'mov' => 'video/quicktime',
		'mp3' => 'audio/mpeg',
		'mp4' => 'application/mp4',
		'mpc' => 'audio/x-musepack',
		'mpg' => 'video/mpeg',
		'mts' => 'video/MP2T',
		'oga' => 'audio/ogg',
		'ogg' => 'audio/ogg',
		'ogv' => 'video/ogg',
		'ogx' => 'application/ogg',
		'qt' => 'video/quicktime',
		'ra' => 'audio/x-pn-realaudio',
		'ram' => 'audio/x-pn-realaudio',
		'rm' => 'audio/x-pn-realaudio',
		'spx' => 'audio/ogg',
		'svg' => 'image/svg+xml',
		'svgz' => 'image/svg+xml',
		'swf' => 'application/x-shockwave-flash',
		'ts' => 'video/MP2T',
		'wav' => 'audio/x-wav',
		'webm' => 'video/webm',
		'wma' => 'audio/x-ms-wma',
		'wmv' => 'video/x-ms-wmv',
		'y4m' => 'video/x-raw-yuv',
		'3gp' => 'video/3gpp',
		'3ga' => 'audio/3ga',

		// Documents varies
		'7z' => 'application/x-7z-compressed',
		'ai' => 'application/illustrator',
		'abw' => 'application/abiword',
		'asx' => 'video/x-ms-asf',
		'bib' => 'application/x-bibtex',
		'bin' => 'application/octet-stream', # le tout-venant
		'blend' => 'application/x-blender',
		'bz2' => 'application/x-bzip2',
		'c'  => 'text/x-csrc',
		'csl' => 'application/xml',
		'css' => 'text/css',
		'csv' => 'text/csv',
		'deb' => 'application/x-debian-package',
		'doc' => 'application/msword',
		'dot' => 'application/msword',
		'djvu' => 'image/vnd.djvu',
		'dvi' => 'application/x-dvi',
		'emf' => 'image/x-emf',
		'enl' => 'application/octet-stream',
		'ens' => 'application/octet-stream',
		'eps' => 'application/postscript',
		'epub' => 'application/epub+zip', // pas enregistre par IANA
		'gpx' => 'application/gpx+xml', // pas enregistre par IANA
		'gz' => 'application/x-gzip',
		'h'  => 'text/x-chdr',
		'html' => 'text/html',
		'jar' => 'application/java-archive',
		'json' => 'application/json',
		'kml' => 'application/vnd.google-earth.kml+xml',
		'kmz' => 'application/vnd.google-earth.kmz',
		'lyx' => 'application/x-lyx',
		'm3u' => 'text/plain',
		'm3u8' => 'text/plain',
		'mathml' => 'application/mathml+xml',
		'mbtiles' => 'application/x-sqlite3',
		'pas' => 'text/x-pascal',
		'pdf' => 'application/pdf',
		'pgn' => 'application/x-chess-pgn',
		'pls' => 'text/plain',
		'ppt' => 'application/vnd.ms-powerpoint',
		'pot' => 'application/vnd.ms-powerpoint',
		'ps' => 'application/postscript',
		'psd' => 'image/x-photoshop', // pas enregistre par IANA
		'rar' => 'application/x-rar-compressed',
		'rdf' => 'application/rdf+xml',
		'ris' => 'application/x-research-info-systems',
		'rpm' => 'application/x-redhat-package-manager',
		'rtf' => 'application/rtf',
		'sdc' => 'application/vnd.stardivision.calc',
		'sdd' => 'application/vnd.stardivision.impress',
		'sdw' => 'application/vnd.stardivision.writer',
		'sit' => 'application/x-stuffit',
		'sla' => 'application/x-scribus',
		'srt' => 'text/plain',
		'ssa' => 'text/plain',
		'sxc' => 'application/vnd.sun.xml.calc',
		'sxi' => 'application/vnd.sun.xml.impress',
		'sxw' => 'application/vnd.sun.xml.writer',
		'tar' => 'application/x-tar',
		'tex' => 'text/x-tex',
		'tgz' => 'application/x-gtar',
		'torrent' => 'application/x-bittorrent',
		'ttf' => 'application/x-font-ttf',
		'txt' => 'text/plain',
		'usf' => 'application/xml',
		'xcf' => 'application/x-xcf',
		'xls' => 'application/vnd.ms-excel',
		'xlt' => 'application/vnd.ms-excel',
		'wmf' => 'image/x-emf',
		'wpl' => 'application/vnd.ms-wpl',
		'xspf' => 'application/xspf+xml',
		'xml' => 'application/xml',
		'yaml' => 'text/yaml',
		'zip' => 'application/zip',

		// Open Document format
		'odt' => 'application/vnd.oasis.opendocument.text',
		'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
		'odp' => 'application/vnd.oasis.opendocument.presentation',
		'odg' => 'application/vnd.oasis.opendocument.graphics',
		'odc' => 'application/vnd.oasis.opendocument.chart',
		'odf' => 'application/vnd.oasis.opendocument.formula',
		'odb' => 'application/vnd.oasis.opendocument.database',
		'odi' => 'application/vnd.oasis.opendocument.image',
		'odm' => 'application/vnd.oasis.opendocument.text-master',
		'ott' => 'application/vnd.oasis.opendocument.text-template',
		'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
		'otp' => 'application/vnd.oasis.opendocument.presentation-template',
		'otg' => 'application/vnd.oasis.opendocument.graphics-template',

		'cls' => 'text/x-tex',
		'sty' => 'text/x-tex',

		// Open XML File Formats
		'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
		'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
		'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
		'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',

		'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
		'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
		'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
		'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
		'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
		'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
		'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',

		'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
		'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
		'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
		'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
		'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
		'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template'
	);


	$mime_alias = array (
		'application/x-ogg' => 'application/ogg',
		'audio/3gpp' => 'video/3gpp',
		'audio/x-mpeg' => 'audio/mpeg',
		'audio/x-musepack' => 'audio/musepack',
		'audio/webm' => 'video/webm',
		'video/flv' => 'video/x-flv',
		'video/mp4' => 'application/mp4',
		'image/jpg' => 'image/jpeg'
	);

?>
stats.php000066600000004754152503077120006433 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined("_ECRIRE_INC_VERSION")) return;

function stats_declarer_tables_auxiliaires($tables_auxiliaires){

	$spip_visites = array(
			"date"	=> "DATE NOT NULL",
			"visites"	=> "int UNSIGNED DEFAULT '0' NOT NULL",
			"maj"	=> "TIMESTAMP");

	$spip_visites_key = array(
			"PRIMARY KEY"	=> "date");

	$spip_visites_articles = array(
			"date"	=> "DATE NOT NULL",
			"id_article"	=> "int UNSIGNED NOT NULL",
			"visites"	=> "int UNSIGNED DEFAULT '0' NOT NULL",
			"maj"	=> "TIMESTAMP");

	$spip_visites_articles_key = array(
			"PRIMARY KEY"	=> "date, id_article");	



	$spip_referers = array(
			"referer_md5"	=> "bigint UNSIGNED NOT NULL",
			"date"		=> "DATE NOT NULL",
			"referer"	=> "VARCHAR (255)",
			"visites"	=> "int UNSIGNED NOT NULL",
			"visites_jour"	=> "int UNSIGNED NOT NULL",
			"visites_veille"=> "int UNSIGNED NOT NULL",
			"maj"		=> "TIMESTAMP");

	$spip_referers_key = array(
			"PRIMARY KEY"	=> "referer_md5");

	$spip_referers_articles = array(
			"id_article"	=> "int UNSIGNED NOT NULL",
			"referer_md5"	=> "bigint UNSIGNED NOT NULL",
			"referer"	=> "VARCHAR (255) DEFAULT '' NOT NULL",
			"visites"	=> "int UNSIGNED NOT NULL",
			"maj"		=> "TIMESTAMP");

	$spip_referers_articles_key = array(
			"PRIMARY KEY"	=> "id_article, referer_md5",
			"KEY referer_md5"	=> "referer_md5");

	$tables_auxiliaires['spip_visites'] = array(
		'field' => &$spip_visites,
		'key' => &$spip_visites_key);
	$tables_auxiliaires['spip_visites_articles'] = array(
		'field' => &$spip_visites_articles,
		'key' => &$spip_visites_articles_key);
	$tables_auxiliaires['spip_referers'] = array(
		'field' => &$spip_referers,
		'key' => &$spip_referers_key);
	$tables_auxiliaires['spip_referers_articles'] = array(
		'field' => &$spip_referers_articles,
		'key' => &$spip_referers_articles_key);	

	return $tables_auxiliaires;
}

?>
delete_referers.php000066600000002771152503077120010431 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined("_ECRIRE_INC_VERSION")) return; // securiser

// faudrait plutot recuperer dans inc_serialbase et inc_auxbase
// mais il faudra prevenir ceux qui affectent les globales qui s'y trouvent
// Afficher la liste de ce qu'on va detruire et demander confirmation 
// ca vaudrait mieux

/**
 * Supprimer les referers
 * @param strinf $titre
 * @param bool $reprise
 * @return string
 */
function base_delete_referers_dist($titre='', $reprise='')
{
	if (!$titre) return; // anti-testeur automatique
	sql_delete("spip_referers");
	sql_delete("spip_referers_articles");
	sql_update("spip_articles", array('referers'=>0));

	// un pipeline pour detruire les tables de referers installees par les plugins ?
	//pipeline('delete_referers', '');
	
	spip_log("raz des referers operee redirige vers " . _request('redirect'));
}
?>
delete_stats.php000066600000003115152503077120007743 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined("_ECRIRE_INC_VERSION")) return; // securiser

// faudrait plutot recuperer dans inc_serialbase et inc_auxbase
// mais il faudra prevenir ceux qui affectent les globales qui s'y trouvent
// Afficher la liste de ce qu'on va detruire et demander confirmation 
// ca vaudrait mieux

/**
 * Supprimer les stats
 * @param strinf $titre
 * @param bool $reprise
 * @return string
 */
function base_delete_stats_dist($titre='', $reprise='')
{
	if (!$titre) return; // anti-testeur automatique
	sql_delete("spip_visites");
	sql_delete("spip_visites_articles");
	sql_delete("spip_referers");
	sql_delete("spip_referers_articles");
	sql_update("spip_articles", array('visites'=>0, 'referers'=>0, 'popularite'=>0));

	// un pipeline pour detruire les tables de stats installees par les plugins
	pipeline('delete_statistiques', '');
	spip_log("raz des stats operee redirige vers " . _request('redirect'));
}
?>
petitions.php000066600000012204152503077710007305 0ustar00<?php

/***************************************************************************\
 *  SPIP, Systeme de publication pour l'internet                           *
 *                                                                         *
 *  Copyright (c) 2001-2014                                                *
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
 *                                                                         *
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
\***************************************************************************/

if (!defined('_ECRIRE_INC_VERSION')) return;

/**
 * Interfaces des tables petitions et signatures pour le compilateur
 *
 * @param array $interfaces
 * @return array
 */
function petitions_declarer_tables_interfaces($interfaces){

	$interfaces['table_des_tables']['petitions']='petitions';
	$interfaces['table_des_tables']['signatures']='signatures';
	
	$interfaces['exceptions_des_tables']['signatures']['date']='date_time';
	$interfaces['exceptions_des_tables']['signatures']['nom']='nom_email';
	$interfaces['exceptions_des_tables']['signatures']['email']='ad_email';
	
	$interfaces['tables_jointures']['spip_articles'][]= 'petitions';
	$interfaces['tables_jointures']['spip_articles'][]= 'signatures';

	$interfaces['exceptions_des_jointures']['petition'] = array('spip_petitions', 'texte');
	$interfaces['exceptions_des_jointures']['id_signature']= array('spip_signatures', 'id_signature');

	$interfaces['table_des_traitements']['MESSAGE'][]= _TRAITEMENT_RACCOURCIS;

	// Signatures : passage des donnees telles quelles, sans traitement typo
	// la securite et conformite XHTML de ces champs est assuree par safehtml()
	foreach(array('NOM_EMAIL','AD_EMAIL','NOM_SITE','URL_SITE','MESSAGE') as $balise)
		if (!isset($interfaces['table_des_traitements'][$balise]['signatures']))
			$interfaces['table_des_traitements'][$balise]['signatures'] = 'liens_nofollow(safehtml(%s))';
		else
			if (strpos($interfaces['table_des_traitements'][$balise]['signatures'],'safehtml')==false)
				$interfaces['table_des_traitements'][$balise]['signatures'] = 'liens_nofollow(safehtml('.$interfaces['table_des_traitements'][$balise]['signatures'].'))';

	return $interfaces;
}

function petitions_declarer_tables_objets_sql($tables){
	$tables['spip_petitions'] = array(
	  'url_voir'=>'controler_petition',
	  'url_edit'=>'controler_petition',
	  'editable'=>'non',
	  'principale' => 'oui',
		'page'=>'', // pas de page editoriale pour une petition

		'texte_retour' => 'icone_retour',
		'texte_objets' => 'petitions:titre_petitions',
		'texte_objet'  => 'petitions:titre_petition',
		
		'titre' => "texte as titre, '' AS lang",

		'field'=> array(
			"id_petition"	=> "bigint(21) NOT NULL",
			"id_article"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"email_unique"	=> "CHAR (3) DEFAULT '' NOT NULL",
			"site_obli"	=> "CHAR (3) DEFAULT '' NOT NULL",
			"site_unique"	=> "CHAR (3) DEFAULT '' NOT NULL",
			"message"	=> "CHAR (3) DEFAULT '' NOT NULL",
			"texte"	=> "LONGTEXT DEFAULT '' NOT NULL",
			"statut"	=> "VARCHAR (10) DEFAULT 'publie' NOT NULL",
			"maj"	=> "TIMESTAMP"
		),
		'key' => array(
			"PRIMARY KEY"	=> "id_petition",
			"UNIQUE id_article"	=> "id_article"
		),
		'statut' => array(
			array('champ'=>'statut','publie'=>'publie,off','previsu'=>'publie,off','exception'=>array('statut')),
		),
	);

	$tables['spip_signatures'] = array(
	  'url_voir'=>'controler_petition',
	  'url_edit'=>'controler_petition',
	  'editable'=>'non',
	  'principale' => 'oui',
		'page'=>'', // pas de page editoriale pour une signature

		'texte_retour' => 'icone_retour',
		'texte_objets' => 'public:signatures_petition',
		'texte_objet' => 'entree_signature',
		'info_aucun_objet'=> 'petitions:aucune_signature',
		'info_1_objet' => 'petitions:une_signature',
		'info_nb_objets' => 'petitions:nombre_signatures',
		'titre' => "nom_email as titre, '' AS lang",
		'date' => 'date_time',

		'field'=> array(
			"id_signature"	=> "bigint(21) NOT NULL",
			"id_petition"	=> "bigint(21) DEFAULT '0' NOT NULL",
#			"id_article"	=> "bigint(21) DEFAULT '0' NOT NULL",
			"date_time"	=> "datetime DEFAULT '0000-00-00 00:00:00' NOT NULL",
			"nom_email"	=> "text DEFAULT '' NOT NULL",
			"ad_email"	=> "text DEFAULT '' NOT NULL",
			"nom_site"	=> "text DEFAULT '' NOT NULL",
			"url_site"	=> "text DEFAULT '' NOT NULL",
			"message"	=> "mediumtext DEFAULT '' NOT NULL",
			"statut"	=> "varchar(10) DEFAULT '0' NOT NULL",
			"maj"	=> "TIMESTAMP"
		),
		'key' => array(
			"PRIMARY KEY"	=> "id_signature",
			"KEY id_petition"	=> "id_petition",
#			"KEY id_article"	=> "id_article",
			"KEY statut" => "statut"
		),
		'join' => array(
			"id_signature"=>"id_signature",
			"id_petition"=>"id_petition"
		),
		'tables_jointures'=> array(
			'petitions'
		),
		'statut' => array(
			array('champ'=>'statut','publie'=>'publie','previsu'=>'publie','exception'=>array('statut','tout')),
		),
		'rechercher_champs' => array(
			'nom_email' => 2, 'ad_email' => 4,
			'nom_site' => 2, 'url_site' => 4,
			'message' => 1
		),
		'icone_objet' => 'petition',
	);

	return $tables;
}
?>