/** * recuperer les infos distantes d'une url, * et renseigner pour une insertion en base * utilise une variable static car appellee plusieurs fois au cours du meme hit * (verification puis traitement) * * @param string $source * @return string */ function renseigner_source_distante($source) { static $infos = array(); if (isset($infos[$source])) { return $infos[$source]; } include_spip('inc/distant'); // on passe la source dans le pipeline, le premier plugin // qui est capable de renseigner complete // fichier et mode + tous les autres champs a son gout // ex : oembed $a = pipeline('renseigner_document_distant', array('source' => $source)); // si la source est encore la, en revenir a la // methode traditionnelle : chargement de l'url puis analyse if (!isset($a['fichier']) or !isset($a['mode'])) { if (!($a = recuperer_infos_distantes($a['source']))) { return _T('medias:erreur_chemin_distant', array('nom' => $source)); } # NB: dans les bonnes conditions (fichier autorise et pas trop gros) # $a['fichier'] est une copie locale du fichier unset($a['body']); $a['distant'] = 'oui'; $a['mode'] = 'document'; $a['fichier'] = set_spip_doc($source); } // stocker pour la seconde demande return $infos[$source] = $a; }
function recuperer_infos_distantes($source, $max = 0, $charger_si_petite_image = true) { # charger les alias des types mime include_spip('base/typedoc'); global $mime_alias; $a = array(); $mime_type = ''; // On va directement charger le debut des images et des fichiers html, // de maniere a attrapper le maximum d'infos (titre, taille, etc). Si // ca echoue l'utilisateur devra les entrer... if ($headers = recuperer_page($source, false, true, $max, '', '', true)) { list($headers, $a['body']) = preg_split(',\\n\\n,', $headers, 2); if (preg_match(",\nContent-Type: *([^[:space:];]*),i", "\n{$headers}", $regs)) { $mime_type = trim($regs[1]); } else { $mime_type = ''; } // inconnu // Appliquer les alias while (isset($mime_alias[$mime_type])) { $mime_type = $mime_alias[$mime_type]; } // Si on a un mime-type insignifiant // text/plain,application/octet-stream ou vide // c'est peut-etre que le serveur ne sait pas // ce qu'il sert ; on va tenter de detecter via l'extension de l'url // ou le Content-Disposition: attachment; filename=... $t = null; if (in_array($mime_type, array('text/plain', '', 'application/octet-stream'))) { if (!$t and preg_match(',\\.([a-z0-9]+)(\\?.*)?$,i', $source, $rext)) { $t = sql_fetsel("extension", "spip_types_documents", "extension=" . sql_quote($rext[1], '', 'text')); } if (!$t and preg_match(",^Content-Disposition:\\s*attachment;\\s*filename=(.*)\$,Uims", $headers, $m) and preg_match(',\\.([a-z0-9]+)(\\?.*)?$,i', $m[1], $rext)) { $t = sql_fetsel("extension", "spip_types_documents", "extension=" . sql_quote($rext[1], '', 'text')); } } // Autre mime/type (ou text/plain avec fichier d'extension inconnue) if (!$t) { $t = sql_fetsel("extension", "spip_types_documents", "mime_type=" . sql_quote($mime_type)); } // Toujours rien ? (ex: audio/x-ogg au lieu de application/ogg) // On essaie de nouveau avec l'extension if (!$t and $mime_type != 'text/plain' and preg_match(',\\.([a-z0-9]+)(\\?.*)?$,i', $source, $rext)) { $t = sql_fetsel("extension", "spip_types_documents", "extension=" . sql_quote($rext[1], '', 'text')); # eviter xxx.3 => 3gp (> SPIP 3) } if ($t) { spip_log("mime-type {$mime_type} ok, extension " . $t['extension']); $a['extension'] = $t['extension']; } else { # par defaut on retombe sur '.bin' si c'est autorise spip_log("mime-type {$mime_type} inconnu"); $t = sql_fetsel("extension", "spip_types_documents", "extension='bin'"); if (!$t) { return false; } $a['extension'] = $t['extension']; } if (preg_match(",\nContent-Length: *([^[:space:]]*),i", "\n{$headers}", $regs)) { $a['taille'] = intval($regs[1]); } } // Echec avec HEAD, on tente avec GET if (!$a and !$max) { spip_log("tenter GET {$source}"); $a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE); } // S'il s'agit d'une image pas trop grosse ou d'un fichier html, on va aller // recharger le document en GET et recuperer des donnees supplementaires... if (preg_match(',^image/(jpeg|gif|png|swf),', $mime_type)) { if ($max == 0 and $a['taille'] < _INC_DISTANT_MAX_SIZE and strpos($GLOBALS['meta']['formats_graphiques'], $a['extension']) !== false and $charger_si_petite_image) { $a = recuperer_infos_distantes($source, _INC_DISTANT_MAX_SIZE); } else { if ($a['body']) { $a['fichier'] = _DIR_RACINE . nom_fichier_copie_locale($source, $a['extension']); ecrire_fichier($a['fichier'], $a['body']); $size_image = @getimagesize($a['fichier']); $a['largeur'] = intval($size_image[0]); $a['hauteur'] = intval($size_image[1]); $a['type_image'] = true; } } } // Fichier swf, si on n'a pas la taille, on va mettre 425x350 par defaut // ce sera mieux que 0x0 if ($a and $a['extension'] == 'swf' and !$a['largeur']) { $a['largeur'] = 425; $a['hauteur'] = 350; } if ($mime_type == 'text/html') { include_spip('inc/filtres'); $page = recuperer_page($source, true, false, _INC_DISTANT_MAX_SIZE); if (preg_match(',<title>(.*?)</title>,ims', $page, $regs)) { $a['titre'] = corriger_caracteres(trim($regs[1])); } if (!$a['taille']) { $a['taille'] = strlen($page); } # a peu pres } return $a; }
/** * Analyser une URL de site distant, qui peut être une syndication. * * @param string $url * URL du site à analyser * @return array|bool * - array : informations du site * - false : site impossible à récupérer **/ function analyser_site($url) { include_spip('inc/filtres'); include_spip('inc/distant'); // Accepter les URLs au format feed:// ou qui ont oublie le http:// $url = preg_replace(',^feed://,i', 'http://', $url); if (!preg_match(',^[a-z]+://,i', $url)) { $url = 'http://' . $url; } $texte = recuperer_page($url, true); if (!$texte) { return false; } include_spip('inc/syndic'); cdata_echappe($texte, $echappe_cdata); if (preg_match(',<(channel|feed)([\\:[:space:]][^>]*)?' . '>(.*)</\\1>,ims', $texte, $regs)) { $result['syndication'] = 'oui'; $result['url_syndic'] = $url; $channel = $regs[3]; // Pour recuperer l'entete, on supprime tous les items $b = array_merge(extraire_balises($channel, 'item'), extraire_balises($channel, 'entry')); $header = str_replace($b, array(), $channel); if ($t = extraire_balise($header, 'title')) { cdata_echappe_retour($t, $echappe_cdata); $result['nom_site'] = filtrer_entites(supprimer_tags($t)); } if ($t = extraire_balises($header, 'link')) { cdata_echappe_retour($t, $echappe_cdata); foreach ($t as $link) { $u = supprimer_tags(filtrer_entites($link)); if (!strlen($u)) { $u = extraire_attribut($link, 'href'); } if (strlen($u)) { // on installe l'url comme url du site // si c'est non vide, en donnant la priorite a rel=alternate if (preg_match(',\\balternate\\b,', extraire_attribut($link, 'rel')) or !isset($result['url_site'])) { $result['url_site'] = filtrer_entites($u); } } } } $result['url_site'] = url_absolue($result['url_site'], $url); if ($a = extraire_balise($header, 'description') or $a = extraire_balise($header, 'tagline')) { cdata_echappe_retour($a, $echappe_cdata); $result['descriptif'] = filtrer_entites(supprimer_tags($a)); } if (preg_match(',<image.*<url.*>(.*)</url>.*</image>,Uims', $header, $r) and preg_match(',(https?://.*/.*(gif|png|jpg)),ims', $r[1], $r) and $image = recuperer_infos_distantes($r[1])) { if (in_array($image['extension'], array('gif', 'jpg', 'png'))) { $result['format_logo'] = $image['extension']; $result['logo'] = $r[1]; } else { if ($image['fichier']) { spip_unlink($image['fichier']); } } } } else { $result['syndication'] = 'non'; $result['url_site'] = $url; if (preg_match(',<head>(.*(description|title).*)</head>,Uims', $texte, $regs)) { $head = filtrer_entites($regs[1]); } else { $head = $texte; } if (preg_match(',<title[^>]*>(.*),ims', $head, $regs)) { $titre = trim($regs[1]); if (!strlen($titre)) { $titre = substr($head, strpos($head, $regs[0])); } $result['nom_site'] = filtrer_entites(supprimer_tags(preg_replace(',</title>.*$,ims', '', $titre))); } if ($a = array_merge(extraire_balises($head, 'meta'), extraire_balises($head, 'http-equiv'))) { foreach ($a as $meta) { if (extraire_attribut($meta, 'name') == 'description') { $desc = trim(extraire_attribut($meta, 'content')); if (!strlen($desc)) { $desc = trim(extraire_attribut($meta, 'value')); } $result['descriptif'] = $desc; } } } // Cherchons quand meme un backend include_spip('inc/distant'); include_spip('inc/feedfinder'); $feeds = get_feed_from_url($url, $texte); // si on a a trouve un (ou plusieurs) on le note avec select: // ce qui constitue un signal pour exec=sites qui proposera de choisir // si on syndique, et quelle url. if (count($feeds) >= 1) { spip_log("feedfinder.php :\n" . join("\n", $feeds)); $result['url_syndic'] = "select: " . join(' ', $feeds); } } cdata_echappe_retour($result, $echappe_cdata); return $result; }
function genie_vacarme_numeros_import_dist($t) { spip_log("debut de la fonction d'importation", 'vacarme_numeros_cron'); include_spip('inc/distant'); include_spip('inc/yaml'); $url = 'http://www.vacarme.org/?page=export.yaml'; $page = recuperer_page($url); $f = yaml_decode($page); // le taux de TVA utilisé par le plugin Produits $tva = lire_config('produits/taxe'); $data = array(); $processus = false; // pour le dev on met en true // $processus = true; foreach ($f as $numeros) { foreach ($numeros as $numero) { if (is_array($numero['sommaire'])) { $s = array(); foreach ($numero['sommaire'] as $sommaire) { $s[] = serialize($sommaire); } $numero['sommaire'] = serialize($s); } if (isset($numero['id'])) { // Cette rubrique n'a pas déjà été importée ? $id = $numero['id']; if (!sql_countsel("spip_vacarme_numeros", array("id_rubrique_distante=" . sql_quote($id)))) { // traitement des données $titre = $numero['numero']; $saison = $numero['saison']; $annee = $numero['annee']; if ($numero['prix']) { $prix = round($numero['prix'] / (1 + $tva), 4); } $url = $numero['url']; $logo = $numero['logo']; $sommaire = $numero['sommaire']; // insertion sql_insertq("spip_vacarme_numeros", array('id_rubrique_distante' => $id, 'numero' => $titre, 'saison' => $saison, 'annee' => $annee, 'prix' => $prix, 'url' => $url, 'logo' => $logo, 'sommaire' => $sommaire, 'statut' => 'publie')); spip_log("La rubrique «" . $titre . "» a été importée", "vacarme_numeros_cron"); $processus = true; } } } } // une importation a été faite, les numéros sont enregistrés comme produits. if ($processus) { // les numeros importés en produits sont placés dans la rubrique 2/secteur 2 $id_rubrique = 2; $id_secteur = 2; $row = array(); // 1- on met les numeros en prop (ie qui viennent d'être importés) $result = sql_select("*", "spip_vacarme_numeros", "statut='publie'"); if ($result) { while ($row = sql_fetch($result)) { $id_numero = $row['id_numero']; $titre = $row['numero']; $prix = $row['prix']; $saison = $row['saison']; $annee = $row['annee']; $url = $row['url']; $logo = $row['logo']; // calcul de la référence du produit à ajouter $ref = preg_replace('/(vacarme\\s*)(\\d*)(\\/*)(\\d*)/i', 'v$2', $titre); // le sommaire $sommaire = unserialize($row['sommaire']); // 2- les numéros sont importés dans la table produits // test nécessaire (?) car sinon, un numéro est importé plusieurs fois de manière identique. Pas compris pourquoi. if (!($test = sql_fetsel("id_produit", "spip_produits", "titre=" . sql_quote($ref)))) { $ladate = date('Y-m-d H:i:s'); $id_produit = sql_insertq('spip_produits', array('titre' => $titre, 'id_rubrique' => $id_rubrique, 'id_secteur' => $id_secteur, 'prix_ht' => $prix, 'statut' => 'publie', 'lang' => 'fr', 'date' => $ladate, 'reference' => $ref)); if ($id_produit) { // 3- on importe le logo pour l'appliquer au produit if ($logo) { $infos = recuperer_infos_distantes($logo); if ($infos['extension']) { $ext = $infos['extension']; $taille = $infos['taille']; $fichier = $infos['fichier']; $largeur = $infos['largeur']; $hauteur = $infos['hauteur']; // extension autorisee ? $ext_autorisee = sql_fetsel("inclus", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"); if ($ext_autorisee) { $id_document = sql_insertq('spip_documents', array('extension' => $ext, 'date' => $ladate, 'fichier' => $fichier, 'taille' => $taille, 'largeur' => $largeur, 'hauteur' => $hauteur, 'mode' => 'document', 'distant' => 'oui', 'statut' => 'publie', 'date_publication' => $ladate)); sql_insertq('spip_documents_liens', array('id_document' => $id_document, 'id_objet' => $id_produit, 'objet' => 'produit', 'vu' => 'non')); // on applique éventuellement la fonction de copie locale // si l'url du fichier est relative ../IMG/distant $f = sql_fetsel("fichier", "spip_documents", "id_document={$id_document}"); $url_relative = strstr($f['fichier'], '../IMG/'); if ($url_relative) { include_spip('vacarme_numeros_fonctions'); $traitement = vacarme_numeros_copie_locale($id_document); } } } } // fin importation logo // 4- le sommaire détaillé d'un numéro sql_insertq('spip_vacarme_numeros_details', array('id_produit' => $id_produit, 'saison' => $saison, 'annee' => $annee, 'url' => $url)); if (is_array($sommaire)) { foreach ($sommaire as $data) { $data = unserialize($data); $data_titre = $data['titre']; $data_url = $data['url']; $resume = $data['resume']; sql_insertq('spip_vacarme_numeros_sommaires', array('id_produit' => $id_produit, 'titre' => $data_titre, 'url' => $data_url, 'resume' => $resume)); } } // fin sommaire } // fin test produit } // fin importation produit // on dépublie les numéros qui viennent d'être transformés en produits sql_updateq('spip_vacarme_numeros', array('statut' => "refuse"), 'id_numero=' . intval($id_numero)); } } } spip_log("fin de la fonction d'importation", 'vacarme_numeros_cron'); return 1; }
function ajouter_un_document($source, $nom_envoye, $type_lien, $id_lien, $mode, $id_document, &$documents_actifs, $titrer=false) { include_spip('inc/modifier'); // Documents distants : pas trop de verifications bloquantes, mais un test // via une requete HEAD pour savoir si la ressource existe (non 404), si le // content-type est connu, et si possible recuperer la taille, voire plus. if ($mode == 'distant') { include_spip('inc/distant'); if ($a = recuperer_infos_distantes($source)) { # NB: dans les bonnes conditions (fichier autorise et pas trop gros) # $a['fichier'] est une copie locale du fichier $type_image = $a['type_image']; unset($a['type_image']); unset($a['body']); $a['date'] = date('Y-m-d H:i:s'); $a['distant'] = 'oui'; $a['mode'] = 'document'; $a['fichier'] = set_spip_doc($source); } else { spip_log("Echec du lien vers le document $source, abandon"); return; } } else { // pas distant $type_image = ''; // au pire // tester le type de document : // - interdit a l'upload ? // - quelle extension dans spip_types_documents ? // - est-ce "inclus" comme une image ? list($nom_envoye, $ext, $titre, $inclus) = corriger_extension_et_nom($nom_envoye, $titrer); if ($inclus !== false) { $type_inclus_image = ($inclus == 'image'); $fichier = copier_document($ext, $nom_envoye, $source); } else { /* STOCKER LES DOCUMENTS INCONNUS AU FORMAT .ZIP */ $type_inclus_image = false; if (!sql_countsel("spip_types_documents", "extension='zip' AND upload='oui'")) { spip_log("Extension $ext interdite a l'upload"); return; } $ext = 'zip'; if (!$tmp_dir = tempnam(_DIR_TMP, 'tmp_upload')) return; spip_unlink($tmp_dir); @mkdir($tmp_dir); $tmp = $tmp_dir.'/'.translitteration($nom_envoye); $nom_envoye .= '.zip'; # conserver l'extension dans le nom de fichier, par exemple toto.js => toto.js.zip deplacer_fichier_upload($source, $tmp); include_spip('inc/pclzip'); $source = _DIR_TMP . 'archive.zip'; $archive = new PclZip($source); $v_list = $archive->create($tmp, PCLZIP_OPT_REMOVE_PATH, $tmp_dir, PCLZIP_OPT_ADD_PATH, ''); effacer_repertoire_temporaire($tmp_dir); if (!$v_list) { spip_log("Echec creation du zip "); return; } $fichier = copier_document($ext, $nom_envoye, $source); spip_unlink($source); } // Prevoir traitement specifique pour videos // (http://www.getid3.org/ peut-etre if ($ext == "mov") { $largeur = 0; $hauteur = 0; } else if ($ext == "svg") { // recuperer les dimensions et supprimer les scripts list($largeur,$hauteur)= traite_svg($fichier); } else { // image ? // Si c'est une image, recuperer sa taille et son type (detecte aussi swf) $size_image = @getimagesize($fichier); $largeur = intval($size_image[0]); $hauteur = intval($size_image[1]); $type_image = decoder_type_image($size_image[2]); } // Quelques infos sur le fichier if (!$fichier OR !@file_exists($fichier) OR !$taille = @intval(filesize($fichier))) { spip_log ("Echec copie du fichier $fichier"); return; } // _INTERFACE_DOCUMENTS // Si mode == 'choix', fixer le mode image/document if ($mode == 'choix') { $choisir_mode_document = charger_fonction('choisir_mode_document','inc'); $mode = $choisir_mode_document($fichier, $type_lien, $type_image, $largeur, $hauteur); } if (!$type_image) { if (_DOC_MAX_SIZE > 0 AND $taille > _DOC_MAX_SIZE*1024) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_poids', array('maxi' => taille_en_octets(_DOC_MAX_SIZE*1024), 'actuel' => taille_en_octets($taille)))); } if ($mode == 'image') { spip_log ("le format de $fichier ne convient pas pour une image"); spip_unlink($fichier); return; } } else { // image if (_IMG_MAX_SIZE > 0 AND $taille > _IMG_MAX_SIZE*1024) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_poids', array('maxi' => taille_en_octets(_IMG_MAX_SIZE*1024), 'actuel' => taille_en_octets($taille)))); } if (_IMG_MAX_WIDTH * _IMG_MAX_HEIGHT AND ($size_image[0] > _IMG_MAX_WIDTH OR $size_image[1] > _IMG_MAX_HEIGHT)) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_taille', array( 'maxi' => _T('info_largeur_vignette', array('largeur_vignette' => _IMG_MAX_WIDTH, 'hauteur_vignette' => _IMG_MAX_HEIGHT)), 'actuel' => _T('info_largeur_vignette', array('largeur_vignette' => $size_image[0], 'hauteur_vignette' => $size_image[1])) ))); } } // Si on veut uploader une vignette, il faut qu'elle ait ete bien lue if ($mode == 'vignette') { if (!$type_inclus_image) { spip_log ("le format de $fichier ne convient pas pour une image"); # SVG spip_unlink($fichier); return; } if (!($largeur OR $hauteur)) { spip_log('erreur upload vignette '.$fichier); spip_unlink($fichier); return; } } elseif (!in_array($mode, array('distant', 'image', 'document'))) { if ($type_image AND $type_inclus_image) $mode = 'image'; else $mode = 'document'; } $a = array( 'date' => date('Y-m-d H:i:s'), 'distant' => 'non', 'mode' => $mode, 'titre'=> $titre, 'largeur' => $largeur, 'hauteur' => $hauteur, 'taille' => $taille, 'extension'=> $ext, 'fichier' => set_spip_doc($fichier)); } if (($id_document=intval($id_document)) AND $mode!='vignette') { // Mise a jour des descripteurs d'un vieux doc unset($a['titre']); unset($a['date']); unset($a['distant']); unset($a['mode']); sql_updateq('spip_documents', $a, "id_document=$id_document"); $id = $id_document; } else { // Installer le document dans la base // attention piege semantique : les images s'installent en mode 'vignette' // note : la fonction peut "mettre a jour un document" si on lui // passe "mode=document" et "id_document=.." (pas utilise) // Envoyer aux plugins $a = pipeline('pre_insertion', array( 'args' => array( 'table' => 'spip_documents', ), 'data' => $a ) ); if (strlen($a['fichier']) > 255) { spip_log("Upload avec nom > 255 : " . $a['fichier']); return; } $id = sql_insertq("spip_documents", $a); pipeline('post_insertion', array( 'args' => array( 'table' => 'spip_documents', 'id_objet' => $id_document ), 'data' => $a ) ); spip_log ("ajout du document $source $nom_envoye (M '$mode' T '$type_lien' L '$id_lien' D '$id')"); if ($id_lien AND $id AND preg_match('/^[a-z0-9_]+$/i', $type_lien) # securite ) { sql_insertq('spip_documents_liens', array('id_document' => $id, 'id_objet' => $id_lien, 'objet' => $type_lien)); } else spip_log("Pb d'insertion $id_lien $type_lien"); if ($id_document) { sql_updateq("spip_documents", array("id_vignette" => $id, "mode" => 'document'), "id_document=$id_document"); } else $id_document = $id; // Appliquer l'exif orientation // http://trac.rezo.net/trac/spip/ticket/1494 define('_TOURNER_SELON_EXIF', false); # par defaut non, risque memoire if (defined('_TOURNER_SELON_EXIF') AND _TOURNER_SELON_EXIF AND $mode == 'document' AND $a['distant'] == 'non' AND $a['extension'] == 'jpg') { include_spip('action/tourner'); tourner_selon_exif_orientation($id_document, $fichier); } } // pour que le retour vers ecrire/ active le bon doc. $documents_actifs[$fichier] = $id_document; // Notifications, gestion des revisions, reindexation... pipeline('post_edition', array( 'args' => array( 'operation' => 'ajouter_document', 'table' => 'spip_documents', 'id_objet' => $id, 'type_image' => $type_image ), 'data' => null ) ); return $id ; }