Example #1
0
/**
 * Pré-traitement du fichier $nom
 *
 * @param  string $nom
 * @param  Object $cfg
 * @return Object
 */
function cfg_pre_traiter_cfg_fichier($nom, &$cfg){
	include_spip('inc/flock');
	
	// enlever <OLD>
	$cfg->val[$nom] = str_replace('<OLD>','', $cfg->val[$nom]);
	
	// effacement
	if (_request('_cfg_delete')){
		$supprimer_fichier = _COMPAT_CFG_192 ? 'cfg_supprimer_fichier' : 'supprimer_fichier';
		if (!$supprimer_fichier(get_spip_doc($cfg->val[$nom]))) {
			$cfg->messages['erreurs'][$nom] = _T('cfg:erreur_suppression_fichier', array('fichier'=>get_spip_doc($cfg->val[$nom])));		
		}
	// ajout ou modification
	} else {
		$f = cfg_get_info_fichier_upload($nom);
		if ($f['tmp_name']) {
			// suppression de l'ancien fichier
			$supprimer_fichier = _COMPAT_CFG_192 ? 'cfg_supprimer_fichier' : 'supprimer_fichier';
			if ($cfg->val[$nom] && !$supprimer_fichier(get_spip_doc($cfg->val[$nom]))) {
				$cfg->messages['erreurs'][$nom] = _T('cfg:erreur_suppression_fichier', array('fichier'=>get_spip_doc($cfg->val[$nom])));	
			} else {
				if (!$fichier = cfg_ajoute_un_document($f['tmp_name'],$f['name'],$nom, 'config/'.$cfg->vue)){
					$cfg->messages['erreurs'][$nom] = _T('cfg:erreur_copie_fichier', array('fichier'=>'config/'.$cfg->vue . '/' . $f['name']));	
				} else {
					$cfg->val[$nom] = set_spip_doc($fichier);
				}
			}
		}
	}

	return $cfg;
}
Example #2
0
function action_copier_local_post($id_document) {

	// Il faut la source du document pour le copier
	$row = sql_fetsel("fichier, descriptif", "spip_documents", "id_document=$id_document");
	$source = $row['fichier'];

	include_spip('inc/distant'); // pour 'copie_locale'
	include_spip('inc/documents'); // pour 'set_spip_doc'
	$fichier = copie_locale($source);
	if ($fichier) {
		$fichier = _DIR_RACINE . $fichier;
		$taille = filesize($fichier);
		// On le sort du repertoire IMG/distant/
		$dest = preg_replace(',^.*/distant/[^/_]+[/_],', '', $fichier);
		$dest = sous_repertoire(_DIR_IMG, preg_replace(',^.*\.,', '', $fichier)) . $dest;
		if ($dest != $fichier
		AND @rename($fichier, $dest))
			$fichier = $dest;

		// On indique l'ancien URL dans le descriptif (pis-aller)
		$row['descriptif'] .= ($row['descriptif'] ? "\n\n":'') . "[->$source]";

		// $fichier contient IMG/distant/...
		// or, dans la table documents, IMG doit etre exclu.
		$fichier = set_spip_doc($fichier);
		spip_log("convertit doc $id_document en local: $source => $fichier");
		sql_updateq('spip_documents', array('fichier' =>$fichier, 'distant'=>'non', 'taille'=>$taille, 'descriptif'=> $row['descriptif']),"id_document=".$id_document);
		
	} else {
		spip_log("echec copie locale $source");
	}
}
Example #3
0
/**
 * 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;
}
Example #4
0
/**
 * Tourner un document
 *
 * http://doc.spip.org/@action_tourner_post
 *
 * @param int $id_document
 * @param int $angle
 *   angle de rotation en degre>0
 * @return
 */
function action_tourner_post($id_document, $angle)
{
    $row = sql_fetsel("fichier,extension", "spip_documents", "id_document=" . intval($id_document));
    if (!$row) {
        return;
    }
    include_spip('inc/charsets');
    # pour le nom de fichier
    include_spip('inc/documents');
    // Fichier destination : on essaie toujours de repartir de l'original
    $var_rot = $angle;
    include_spip('inc/distant');
    # pour copie_locale
    $src = _DIR_RACINE . copie_locale(get_spip_doc($row['fichier']));
    if (preg_match(',^(.*)-r(90|180|270)\\.([^.]+)$,', $src, $match)) {
        $effacer = $src;
        $src = $match[1] . '.' . $match[3];
        $var_rot += intval($match[2]);
    }
    $var_rot = (360 + $var_rot) % 360;
    // 0, 90, 180 ou 270
    if ($var_rot > 0) {
        $dest = preg_replace(',\\.[^.]+$,', '-r' . $var_rot . '$0', $src);
        spip_log("rotation {$var_rot} {$src} : {$dest}");
        include_spip('inc/filtres');
        include_spip('public/parametrer');
        // charger les fichiers fonctions #bugfix spip 2.1.0
        $res = filtrer('image_rotation', $src, $var_rot);
        $res = filtrer('image_format', $res, $row['extension']);
        list($hauteur, $largeur) = taille_image($res);
        $res = extraire_attribut($res, 'src');
        include_spip('inc/getdocument');
        deplacer_fichier_upload($res, $dest);
    } else {
        $dest = $src;
        $size_image = @getimagesize($dest);
        $largeur = $size_image[0];
        $hauteur = $size_image[1];
    }
    // succes !
    if ($largeur > 0 and $hauteur > 0) {
        $set = array('fichier' => set_spip_doc($dest), 'largeur' => $largeur, 'hauteur' => $hauteur, 'distant' => 'non');
        if ($taille = @filesize($dest)) {
            $set['taille'] = $taille;
        }
        sql_updateq('spip_documents', $set, "id_document=" . intval($id_document));
        if ($effacer) {
            spip_log("rotation : j'efface {$effacer}");
            spip_unlink($effacer);
        }
        // pipeline pour les plugins
        pipeline('post_edition', array('args' => array('table' => 'spip_documents', 'table_objet' => 'documents', 'spip_table_objet' => 'spip_documents', 'type' => 'document', 'id_objet' => $id_document, 'champs' => array('rotation' => $angle, 'orientation' => $var_rot, 'fichier' => $row['fichier']), 'serveur' => $serveur, 'action' => 'tourner'), 'data' => $set));
    }
}
Example #5
0
function action_acceder_document_dist() {
	include_spip('inc/documents');

	// $file exige pour eviter le scan id_document par id_document
	$f = rawurldecode(_request('file'));
	$file = get_spip_doc($f);
	$arg = rawurldecode(_request('arg'));

	$status = $dcc = false;
	if (strpos($f,'../') !== false
	OR preg_match(',^\w+://,', $f)) {
		$status = 403;
	}
	else if (!file_exists($file) OR !is_readable($file)) {
		$status = 404;
	} else {
		$where = "documents.fichier=".sql_quote(set_spip_doc($file))
		. ($arg ? " AND documents.id_document=".intval($arg): '');

		$doc = sql_fetsel("documents.id_document, documents.titre, documents.fichier, types.mime_type, types.inclus, documents.extension", "spip_documents AS documents LEFT JOIN spip_types_documents AS types ON documents.extension=types.extension",$where);
		if (!$doc) {
			$status = 404;
		} else {

			// ETag pour gerer le status 304
			$ETag = md5($file . ': '. filemtime($file));
			if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
			AND $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag) {
				http_status(304); // Not modified
				exit;
			} else {
				header('ETag: '.$ETag);
			}

			//
			// Verifier les droits de lecture du document
			// en controlant la cle passee en argument
			//
			include_spip('inc/securiser_action');
			$cle = _request('cle');
			if (!verifier_cle_action($doc['id_document'].','.$f, $cle)) {
				spip_log("acces interdit $cle erronee");
				$status = 403;
			}
		}
	}

	switch($status) {

	case 403:
		include_spip('inc/minipres');
		echo minipres();
		break;

	case 404:
		http_status(404);
		include_spip('inc/minipres');
		echo minipres(_T('erreur').' 404',
			_T('info_document_indisponible'));
		break;

	default:
		header("Content-Type: ". $doc['mime_type']);

		// pour les images ne pas passer en attachment
		// sinon, lorsqu'on pointe directement sur leur adresse,
		// le navigateur les downloade au lieu de les afficher

		if ($doc['inclus']=='non') {

			$f = basename($file);
			// ce content-type est necessaire pour eviter des corruptions de zip dans ie6
			header('Content-Type: application/octet-stream');

			header("Content-Disposition: attachment; filename=\"$f\";");
			header("Content-Transfer-Encoding: binary");

			// fix for IE catching or PHP bug issue
			header("Pragma: public");
			header("Expires: 0"); // set expiration time
			header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

		}

		if ($cl = filesize($file))
			header("Content-Length: ". $cl);

		readfile($file);
		break;
	}

}
/**
 * Massicoter un document
 *
 * À utiliser comme filtre sur les balises #FICHIER ou #URL_DOCUMENT
 *
 * @param string $fichier : Le fichier du document
 *
 * @return string : Un fichier massicoté
 */
function massicoter_document($fichier = false)
{
    if (!$fichier) {
        return;
    }
    include_spip('base/abstract_sql');
    include_spip('inc/documents');
    $parametres = sql_getfetsel('traitements', 'spip_massicotages as M' . ' INNER JOIN spip_massicotages_liens as L ON L.id_massicotage = M.id_massicotage' . ' INNER JOIN spip_documents as D ON (D.id_document = L.id_objet AND L.objet="document")', 'D.fichier=' . sql_quote(set_spip_doc($fichier)));
    return massicoter_fichier($fichier, unserialize($parametres));
}
/**
 * Ajouter un document (au format $_FILES)
 *
 * @param int $id_document
 *   Document à remplacer, ou pour une vignette, l'id_document de maman
 *   0 ou 'new' pour une insertion
 * @param array $file
 *   Propriétes au format $_FILE étendu :
 *
 *   - string tmp_name : source sur le serveur
 *   - string name : nom du fichier envoye
 *   - bool titrer : donner ou non un titre a partir du nom du fichier
 *   - bool distant : pour utiliser une source distante sur internet
 *   - string mode : vignette|image|documents|choix
 * @param string $objet
 *   Objet auquel associer le document
 * @param int $id_objet
 *   id_objet
 * @param string $mode
 *   Mode par défaut si pas precisé pour le document
 * @return array|bool|int|mixed|string|unknown
 *
 *   - int : l'id_document ajouté (opération réussie)
 *   - string : une erreur s'est produit, la chaine est le message d'erreur
 *
 */
function action_ajouter_un_document_dist($id_document, $file, $objet, $id_objet, $mode)
{
    $source = $file['tmp_name'];
    $nom_envoye = $file['name'];
    // passer en minuscules le nom du fichier, pour eviter les collisions
    // si le file system fait la difference entre les deux il ne detectera
    // pas que Toto.pdf et toto.pdf
    // et on aura une collision en cas de changement de file system
    $file['name'] = strtolower(translitteration($file['name']));
    // Pouvoir definir dans mes_options.php que l'on veut titrer tous les documents par d?faut
    if (!defined('_TITRER_DOCUMENTS')) {
        define('_TITRER_DOCUMENTS', false);
    }
    $titrer = isset($file['titrer']) ? $file['titrer'] : _TITRER_DOCUMENTS;
    $mode = (isset($file['mode']) and $file['mode']) ? $file['mode'] : $mode;
    include_spip('inc/modifier');
    if (isset($file['distant']) and $file['distant'] and !in_array($mode, array('choix', 'auto', 'image', 'document'))) {
        spip_log("document distant {$source} accepte sans verification, mode={$mode}", "medias" . _LOG_INFO_IMPORTANTE);
        include_spip('inc/distant');
        $file['tmp_name'] = _DIR_RACINE . copie_locale($source);
        $source = $file['tmp_name'];
        unset($file['distant']);
    }
    // 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 (isset($file['distant']) and $file['distant']) {
        if (!tester_url_absolue($source)) {
            return _T('medias:erreur_chemin_distant', array('nom' => $source));
        }
        include_spip('inc/distant');
        if (is_array($a = renseigner_source_distante($source))) {
            $champs = $a;
            # NB: dans les bonnes conditions (fichier autorise et pas trop gros)
            # $a['fichier'] est une copie locale du fichier
            $infos = renseigner_taille_dimension_image($champs['fichier'], $champs['extension'], true);
            // on ignore erreur eventuelle sur $infos car on est distant, ca ne marche pas forcement
            if (is_array($infos)) {
                $champs = array_merge($champs, $infos);
            }
            unset($champs['type_image']);
        } else {
            spip_log("Echec du lien vers le document {$source}, abandon");
            return $a;
            // message d'erreur
        }
    } else {
        // pas distant
        $champs = array('distant' => 'non');
        $type_image = '';
        // au pire
        $champs['titre'] = '';
        if ($titrer) {
            $titre = substr($nom_envoye, 0, strrpos($nom_envoye, "."));
            // Enlever l'extension du nom du fichier
            $titre = preg_replace(',[[:punct:][:space:]]+,u', ' ', $titre);
            $champs['titre'] = preg_replace(',\\.([^.]+)$,', '', $titre);
        }
        if (!is_array($fichier = fixer_fichier_upload($file, $mode))) {
            return is_string($fichier) ? $fichier : _T("medias:erreur_upload_type_interdit", array('nom' => $file['name']));
        }
        $champs['inclus'] = $fichier['inclus'];
        $champs['extension'] = $fichier['extension'];
        $champs['fichier'] = $fichier['fichier'];
        /**
         * Récupère les informations du fichier
         * -* largeur
         * -* hauteur
         * -* type_image
         * -* taille
         * -* ses metadonnées si une fonction de metadatas/ est présente
         */
        $infos = renseigner_taille_dimension_image($champs['fichier'], $champs['extension']);
        if (is_string($infos)) {
            return $infos;
        }
        // c'est un message d'erreur !
        $champs = array_merge($champs, $infos);
        // Si mode == 'choix', fixer le mode image/document
        if (in_array($mode, array('choix', 'auto'))) {
            $choisir_mode_document = charger_fonction('choisir_mode_document', 'inc');
            $mode = $choisir_mode_document($champs, $champs['inclus'] == 'image', $objet);
        }
        $champs['mode'] = $mode;
        if (($test = verifier_taille_document_acceptable($champs)) !== true) {
            spip_unlink($champs['fichier']);
            return $test;
            // erreur sur les dimensions du fichier
        }
        unset($champs['type_image']);
        unset($champs['inclus']);
        $champs['fichier'] = set_spip_doc($champs['fichier']);
    }
    // si le media est pas renseigne, le faire, en fonction de l'extension
    if (!isset($champs['media'])) {
        $champs['media'] = sql_getfetsel('media_defaut', 'spip_types_documents', 'extension=' . sql_quote($champs['extension']));
    }
    // lier le parent si necessaire
    if ($id_objet = intval($id_objet) and $objet) {
        $champs['parents'][] = "{$objet}|{$id_objet}";
    }
    // "mettre a jour un document" si on lui
    // passe un id_document
    if ($id_document = intval($id_document)) {
        unset($champs['titre']);
        // garder le titre d'origine
        unset($champs['date']);
        // garder la date d'origine
        unset($champs['descriptif']);
        // garder la desc d'origine
        // unset($a['distant']); # on peut remplacer un doc statique par un doc distant
        // unset($a['mode']); # on peut remplacer une image par un document ?
    }
    include_spip('action/editer_document');
    // Installer le document dans la base
    if (!$id_document) {
        if ($id_document = document_inserer()) {
            spip_log("ajout du document " . $file['tmp_name'] . " " . $file['name'] . "  (M '{$mode}' T '{$objet}' L '{$id_objet}' D '{$id_document}')", 'medias');
        } else {
            spip_log("Echec insert_document() du document " . $file['tmp_name'] . " " . $file['name'] . "  (M '{$mode}' T '{$objet}' L '{$id_objet}' D '{$id_document}')", 'medias' . _LOG_ERREUR);
        }
    }
    if (!$id_document) {
        return _T('medias:erreur_insertion_document_base', array('fichier' => "<em>" . $file['name'] . "</em>"));
    }
    document_modifier($id_document, $champs);
    // permettre aux plugins de faire des modifs a l'ajout initial
    // ex EXIF qui tourne les images si necessaire
    // Ce plugin ferait quand même mieux de se placer dans metadata/jpg.php
    pipeline('post_edition', array('args' => array('table' => 'spip_documents', 'table_objet' => 'documents', 'spip_table_objet' => 'spip_documents', 'type' => 'document', 'id_objet' => $id_document, 'champs' => array_keys($champs), 'serveur' => '', 'action' => 'ajouter_document', 'operation' => 'ajouter_document'), 'data' => $champs));
    return $id_document;
}
Example #8
0
/**
 * acces aux documents joints securise
 * verifie soit que le demandeur est authentifie
 * soit que le document est publie, c'est-a-dire
 * joint a au moins 1 article, breve ou rubrique publie
 *
 * URLs de la forme :
 * docrestreint.api/id/cle/file
 *
 * @param null $arg
 */
function action_api_docrestreint_dist($arg = null)
{
    $status = 404;
    if (is_null($arg)) {
        $arg = _request('arg');
    }
    $arg = explode("/", $arg);
    // supprimer et vider les buffers qui posent des problemes de memory limit
    // http://www.php.net/manual/en/function.readfile.php#81032
    @ini_set("zlib.output_compression", "0");
    // pour permettre l'affichage au fur et a mesure
    @ini_set("output_buffering", "off");
    @ini_set('implicit_flush', 1);
    @ob_implicit_flush(1);
    $level = ob_get_level();
    while ($level--) {
        @ob_end_clean();
    }
    if (count($arg) >= 3) {
        $id_document = intval(array_shift($arg));
        $cle = array_shift($arg);
        // file exige pour eviter le scan id_document par id_document
        $f = implode("/", $arg);
        if ($id_document == 0 and $cle == 1 and $f == "test/.test") {
            echo "OK";
            return;
        }
        include_spip('inc/documents');
        $file = get_spip_doc($f);
        spip_log($file, 'dbg');
        $status = $dcc = false;
        $dossiers_a_exclure = array('nl');
        // securite : on refuse tout ../ ou url absolue
        if (strpos($f, '../') !== false or preg_match(',^\\w+://,', $f)) {
            $status = 403;
        } else {
            if (!file_exists($file) or !is_readable($file)) {
                $status = 404;
            } elseif (preg_match('%^(' . join('|', $dossiers_a_exclure) . ')/%', $f)) {
                $status = 200;
            } else {
                $where = "documents.fichier=" . sql_quote(set_spip_doc($file)) . ($id_document ? " AND documents.id_document=" . intval($id_document) : '');
                spip_log($where, 'dbg');
                $doc = sql_fetsel("documents.id_document, documents.titre, documents.fichier, types.mime_type, types.inclus, documents.extension", "spip_documents AS documents LEFT JOIN spip_types_documents AS types ON documents.extension=types.extension", $where);
                spip_log($doc, 'dbg');
                if (!$doc) {
                    $status = 404;
                } else {
                    // ETag pour gerer le status 304
                    $ETag = md5($file . ': ' . filemtime($file));
                    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) and $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag) {
                        http_status(304);
                        // Not modified
                        exit;
                    } else {
                        header('ETag: ' . $ETag);
                    }
                    //
                    // Verifier les droits de lecture du document
                    // en controlant la cle passee en argument si elle est dispo
                    // (perf issue : toutes les urls ont en principe cette cle fournie dans la page au moment du calcul de la page)
                    if ($cle) {
                        include_spip('inc/securiser_action');
                        if (!verifier_cle_action($doc['id_document'] . ',' . $f, $cle)) {
                            spip_log("acces interdit {$cle} erronee");
                            $status = 403;
                        }
                    } else {
                        if (!function_exists("autoriser")) {
                            include_spip("inc/autoriser");
                        }
                        if (!autoriser('voir', 'document', $doc['id_document'])) {
                            $status = 403;
                            spip_log("acces interdit {$cle} erronee");
                        }
                    }
                }
            }
        }
    }
    switch ($status) {
        case 403:
            include_spip('inc/minipres');
            echo minipres("", "", "", true);
            break;
        case 404:
            http_status(404);
            include_spip('inc/minipres');
            echo minipres(_T('erreur') . ' 404', _T('medias:info_document_indisponible'), "", true);
            break;
        default:
            header("Content-Type: " . $doc['mime_type']);
            // pour les images ne pas passer en attachment
            // sinon, lorsqu'on pointe directement sur leur adresse,
            // le navigateur les downloade au lieu de les afficher
            if ($doc['inclus'] == 'non') {
                $f = basename($file);
                // ce content-type est necessaire pour eviter des corruptions de zip dans ie6
                header('Content-Type: application/octet-stream');
                header("Content-Disposition: attachment; filename=\"{$f}\";");
                header("Content-Transfer-Encoding: binary");
                // fix for IE catching or PHP bug issue
                header("Pragma: public");
                header("Expires: 0");
                // set expiration time
                header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            } else {
                header("Expires: 3600");
                // set expiration time
            }
            if ($cl = filesize($file)) {
                header("Content-Length: " . $cl);
            }
            readfile($file);
            break;
    }
}
Example #9
0
function action_tourner_post($r)
{
	$arg = $r[1];
	$row = sql_fetsel("fichier", "spip_documents", "id_document=$arg");

	if (!$row) return;

	include_spip('inc/charsets');	# pour le nom de fichier
	include_spip('inc/documents');
	// Fichier destination : on essaie toujours de repartir de l'original
	$var_rot = $r[2];
	include_spip('inc/distant'); # pour copie_locale
	$src = _DIR_RACINE . copie_locale(get_spip_doc($row['fichier']));
	if (preg_match(',^(.*)-r(90|180|270)\.([^.]+)$,', $src, $match)) {
		$effacer = $src;
		$src = $match[1].'.'.$match[3];
		$var_rot += intval($match[2]);
	}
	$var_rot = ((360 + $var_rot) % 360); // 0, 90, 180 ou 270

	if ($var_rot > 0) {
		$dest = preg_replace(',\.[^.]+$,', '-r'.$var_rot.'$0', $src);
		spip_log("rotation $var_rot $src : $dest");

		$process = $GLOBALS['meta']['image_process'];

		// imagick (php4-imagemagick)
		if ($process == 'imagick') {
			$handle = imagick_readimage($src);
			imagick_rotate($handle, $var_rot);
			imagick_write($handle, $dest);
			if (!@file_exists($dest)) return;	// echec imagick
		}
		else if ($process == "gd2") { // theoriquement compatible gd1, mais trop forte degradation d'image
			gdRotate ($src, $dest, $var_rot);
		}
		else if ($process == "convert") {
			if (_CONVERT_COMMAND!='') {
				define ('_CONVERT_COMMAND', 'convert');
				define ('_ROTATE_COMMAND', _CONVERT_COMMAND.' -rotate %t %src %dest');
			} else
				define ('_ROTATE_COMMAND', '');
			if (_ROTATE_COMMAND!=='') {
				$commande = str_replace(
					array('%t', '%src', '%dest'),
					array(
						$var_rot,
						escapeshellcmd($src),
						escapeshellcmd($dest)
					),
					_ROTATE_COMMAND);
				spip_log($commande);
				exec($commande);
			} else
				$dest = $src;
		}
	}
	else
		$dest = $src;

	$size_image = @getimagesize($dest);
	$largeur = $size_image[0];
	$hauteur = $size_image[1];

	// succes !
	if ($largeur>0 AND $hauteur>0) {
		sql_updateq('spip_documents', array('fichier' => set_spip_doc($dest), 'largeur'=>$largeur, 'hauteur'=>$hauteur), "id_document=$arg");
		if ($effacer) {
			spip_log("j'efface $effacer");
			spip_unlink($effacer);
		}
		// pipeline pour les plugins
		pipeline('post_edition',
			array(
				'args' => array(
					'table' => 'spip_documents',
					'table_objet' => 'documents',
					'spip_table_objet' => 'spip_documents',
					'type' =>'document',
					'id_objet' => $arg,
					'champs' => array('rotation'=>$r[2],'orientation'=>$var_rot,'fichier'=>$row),
					'serveur' => $serveur,
					'action'=>'tourner',
				),
				'data' => array('fichier'=>$row)
			)
		);
	}

}
Example #10
0
function action_acceder_document_dist() {
	include_spip('inc/documents');

	// $file exige pour eviter le scan id_document par id_document
	$f = rawurldecode(_request('file'));
	$file = get_spip_doc($f);
	$arg = rawurldecode(_request('arg'));

	$status = $dcc = false;
	if (strpos($f,'../') !== false
	OR preg_match(',^\w+://,', $f)) {
		$status = 403;
	}
	else if (!file_exists($file) OR !is_readable($file)) {
		$status = 404;
	} else {
		$path = set_spip_doc($file);
		$path2 = generer_acceder_document($f, $arg);
		$where = "(documents.fichier=".sql_quote($path)
		  . ' OR documents.fichier=' . sql_quote($path2) . ')'
		  . ($arg ? (" AND documents.id_document=".intval($arg)) : '');

		$doc = sql_fetsel("documents.id_document, documents.titre, documents.fichier, types.mime_type, types.inclus, documents.extension", "spip_documents AS documents LEFT JOIN spip_types_documents AS types ON documents.extension=types.extension",$where);
		if (!$doc) {
			$status = 404;
		} else {

			// ETag pour gerer le status 304
			$ETag = md5($file . ': '. filemtime($file));
			if (isset($_SERVER['HTTP_IF_NONE_MATCH'])
			AND $_SERVER['HTTP_IF_NONE_MATCH'] == $ETag) {
				http_status(304); // Not modified
				exit;
			} else {
				header('ETag: '.$ETag);
			}

			//
			// Verifier les droits de lecture du document
			// en controlant la cle passee en argument
			//
			include_spip('inc/securiser_action');
			$cle = _request('cle');
			if (!verifier_cle_action($doc['id_document'].','.$f, $cle)) {
				spip_log("acces interdit $cle erronee");
				$status = 403;
			}
		}
	}

	switch($status) {

	case 403:
		include_spip('inc/minipres');
		echo minipres();
		break;

	case 404:
		http_status(404);
		include_spip('inc/minipres');
		echo minipres(_T('erreur').' 404',
			_T('info_document_indisponible'));
		break;

	default:
		header("Content-Type: ". $doc['mime_type']);

		// Si le fichier a un titre avec extension,
		// ou si c'est un nom bien connu d'Unix, le prendre
		// sinon l'ignorer car certains navigateurs pataugent

		$f = basename($file);
		if (isset($doc['titre'])
		AND (preg_match('/^\w+[.]\w+$/', $doc['titre']) OR $doc['titre'] == 'Makefile'))
				$f = $doc['titre'];

		$f = "filename=\"$f\"";

		// Pour les document affichables par les navigateurs,
		// ne pas envoyer "Content-Disposition: attachment" sinon 
		// le navigateur cree un fichier au lieu de l'afficher.
		// Mais la propriete "affichable" n'est pas toujours devinable,
		// il faut quand meme donner un nom au fichier eventuel. 
		// Celui-ci est malheureusement souvent ignore, cf
		// http://greenbytes.de/tech/tc2231/

		if ($doc['inclus']!=='non') {
			header("Content-Disposition: inline; $f");
		} else {

			header("Content-Disposition: attachment; $f;");

			// ce content-type est necessaire
			// pour eviter des corruptions de zip dans ie6
			header('Content-Type: application/octet-stream');
			header("Content-Transfer-Encoding: binary");

			// fix for IE catching or PHP bug issue
			header("Pragma: public");
			header("Expires: 0"); // set expiration time
			header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

		}

		if ($cl = filesize($file))
			header("Content-Length: ". $cl);

		readfile($file);
		break;
	}

}
Example #11
0
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 ;
}