Overview
Comment: | Débuts gestion de fichier, à partir d'un patch de @Got |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f387548bd8599442d93fd0ab431ecb15 |
User & Date: | bohwaz on 2015-01-23 04:28:36 |
Other Links: | manifest | tags |
Context
2015-01-26
| ||
00:16 | Libellés des comptes sont inversés [cc08c62119] check-in: 0e915476b1 user: bohwaz tags: trunk | |
2015-01-23
| ||
04:28 | Débuts gestion de fichier, à partir d'un patch de @Got check-in: f387548bd8 user: bohwaz tags: trunk | |
04:28 | Exclure les éléments des squelettes check-in: 7f3f931fc1 user: bohwaz tags: trunk | |
Changes
Modified src/config.dist.php from [d696b6ae5b] to [152c78f796].
︙ | ︙ | |||
57 58 59 60 61 62 63 | // Utilisation de cron pour les tâches automatiques // Si "true" on s'attend à ce qu'une tâche automatisée appelle // le script cron.php à la racine toutes les 24 heures. Sinon Garradin // effectuera les actions automatiques quand quelqu'un se connecte à // l'administration ou visite le site. // Défaut : false const USE_CRON = false; | > > > > > > > > > > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | // Utilisation de cron pour les tâches automatiques // Si "true" on s'attend à ce qu'une tâche automatisée appelle // le script cron.php à la racine toutes les 24 heures. Sinon Garradin // effectuera les actions automatiques quand quelqu'un se connecte à // l'administration ou visite le site. // Défaut : false const USE_CRON = false; // Activation de l'envoi de fichier directement par le serveur web. // Permet d'améliorer la rapidité d'envoi des fichiers. // Supporte les serveurs web suivants : // - Apache avec mod_xsendfile (paquet libapache2-mod-xsendfile) // - Lighttpd // N'activer que si vous êtes sûr que le module est installé et activé. // Nginx n'est PAS supporté, car X-Accel-Redirect ne peut gérer que des fichiers // qui sont *dans* le document root du vhost, ce qui n'est pas le cas ici. const ENABLE_XSENDFILE = false; |
Modified src/include/data/0.7.0.sql from [8c45d58f37] to [6994f75ee3].
1 2 3 4 5 6 7 8 | CREATE TABLE plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | CREATE TABLE plugins_signaux -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL -- Taille en octets ); CREATE UNIQUE INDEX fichiers_hash ON fichiers (hash); CREATE INDEX fichiers_titre ON fichiers (titre); CREATE INDEX fichiers_date ON fichiers (date); CREATE TABLE fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY REFERENCES fichiers (id), contenu BLOB ); CREATE TABLE fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id) ); CREATE TABLE fichiers_wiki_pages -- Associations entre fichiers et pages du wiki ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES wiki_pages (id) ); CREATE TABLE fichiers_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id) ); |
Modified src/include/data/schema.sql from [aeb1567568] to [290e3776d4].
︙ | ︙ | |||
319 320 321 322 323 324 325 | -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | -- Association entre plugins et signaux (hooks) ( signal TEXT NOT NULL, plugin TEXT NOT NULL REFERENCES plugins (id), callback TEXT NOT NULL, PRIMARY KEY (signal, plugin) ); CREATE TABLE fichiers -- Données sur les fichiers ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL -- Taille en octets ); CREATE UNIQUE INDEX fichiers_hash ON fichiers (hash); CREATE INDEX fichiers_titre ON fichiers (titre); CREATE INDEX fichiers_date ON fichiers (date); CREATE TABLE fichiers_contenu -- Contenu des fichiers ( id INTEGER NOT NULL PRIMARY KEY REFERENCES fichiers (id), contenu BLOB ); CREATE TABLE fichiers_membres -- Associations entre fichiers et membres (photo de profil par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES membres (id) ); CREATE TABLE fichiers_wiki_pages -- Associations entre fichiers et pages du wiki ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES wiki_pages (id) ); CREATE TABLE fichiers_compta_journal -- Associations entre fichiers et journal de compta (pièce comptable par exemple) ( fichier INTEGER NOT NULL REFERENCES fichiers (id), id INTEGER NOT NULL REFERENCES compta_journal (id) ); |
Modified src/include/init.php from [b9b3bbdd71] to [de2c349764].
︙ | ︙ | |||
117 118 119 120 121 122 123 124 125 126 127 128 129 130 | } // Utilisation de cron pour les tâches automatiques if (!defined('Garradin\USE_CRON')) { define('Garradin\USE_CRON', false); } define('Garradin\WEBSITE', 'http://garradin.eu/'); define('Garradin\PLUGINS_URL', 'https://garradin.eu/plugins/list.json'); // PHP devrait être assez intelligent pour chopper la TZ système mais nan // il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour // éviter le message d'erreur à la con on définit une timezone par défaut | > > > > > > | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | } // Utilisation de cron pour les tâches automatiques if (!defined('Garradin\USE_CRON')) { define('Garradin\USE_CRON', false); } // Activation de X-SendFile if (!defined('Garradin\ENABLE_XSENDFILE')) { define('Garradin\ENABLE_XSENDFILE', false); } define('Garradin\WEBSITE', 'http://garradin.eu/'); define('Garradin\PLUGINS_URL', 'https://garradin.eu/plugins/list.json'); // PHP devrait être assez intelligent pour chopper la TZ système mais nan // il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour // éviter le message d'erreur à la con on définit une timezone par défaut |
︙ | ︙ |
Added src/include/lib/Garradin/Fichiers.php version [c00d51886f].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | <?php namespace Garradin; class Fichiers { protected $allowed_files_extensions = [ 'jpeg', 'jpg', 'jpe', 'gif', 'png', 'svg', 'svgz', 'psd', 'bmp', 'ico', // Images 'pdf', 'txt', 'rtf', 'tex', 'lyx', 'html', 'epub', 'mobi', 'ps', 'xml', // Textes 'sxw', 'sxc', 'sxd', 'sxi', 'sxf', 'odt', 'odg', 'odp', 'ods', 'odc', 'odf', // Libre Office 'docx', 'xlsx', 'doc', 'xls', 'ppsx', 'pps', 'pptx', 'ppt', 'pub', // Microsoft 'webm', 'mp4', 'flv', 'mkv', 'avi', 'mov', // Vidéos 'mp3', 'm4a', 'aac', 'ogg', 'mid', // Audio 'zip', 'rar', '7z', 'gz', 'xz', 'bz2', 'bz', 'tar', // Archives 'sqlite', 'swf', // Divers ]; public $type; public $titre; public $nom; public $date; public $hash; public $taille; public $id; public function __construct($id) { $data = DB::getInstance()->simpleQuerySingle('SELECT *, strftime(\'%s\', date) AS date FROM fichiers WHERE id = ?;', true, (int)$id); foreach ($data as $key=>$value) { $this->$key = $value; } } /** * Envoie une miniature à la taille indiquée au client HTTP * @param integer $width Largeur * @param integer $height Hauteur * @param boolean $crop TRUE si on doit cropper aux dimensions indiquées * @return void */ public function getThumbnail($width, $height, $crop = false) { } /** * Supprime l'image * @return boolean TRUE en cas de succès */ public function remove() { $db = DB::getInstance(); $db->exec('BEGIN;'); $db->simpleExec('DELETE FROM fichiers_compta_journal WHERE fichier = ?;', (int)$this->id); $db->simpleExec('DELETE FROM fichiers_wiki_pages WHERE fichier = ?;', (int)$this->id); $db->simpleExec('DELETE FROM fichiers_membres WHERE fichier = ?;', (int)$this->id); $db->simpleExec('DELETE FROM fichiers_contenu WHERE id = ?;', (int)$this->id); $db->simpleExec('DELETE FROM fichiers WHERE id = ?;', (int)$this->id); return $db->exec('END;'); } /** * Modifie les informations du fichier * @param string $titre Le titre du fichier * @param string $nom Le nom du fichier (avec extension) * @return boolean TRUE en cas de succès */ public function edit($titre, $nom) { } /** * Envoie le fichier au client HTTP * @return void */ public function serve() { $cache_id = 'fichiers.' . $this->id; // Le fichier n'existe pas dans le cache statique, on l'enregistre if (!Static_Cache::exists($cache_id)) { $blob = DB::getInstance()->openBlob('fichiers_contenu', 'contenu', (int)$this->id); Static_Cache::storeFromPointer($cache_id, $blob); fclose($blob); } $path = Static_Cache::getPath($cache_id); // Désactiver le cache header('Pragma: public'); header('Expires: -1'); header('Cache-Control: public, must-revalidate, post-check=0, pre-check=0'); header('Content-Disposition: attachment; filename="' . $this->nom . '"'); // Utilisation de XSendFile si disponible if (ENABLE_XSENDFILE && isset($_SERVER['SERVER_SOFTWARE'])) { if (stristr($_SERVER['SERVER_SOFTWARE'], 'apache') && function_exists('apache_get_modules') && in_array('mod_xsendfile', apache_get_modules())) { header('X-Sendfile: ' . $path); return true; } else if (stristr($_SERVER['SERVER_SOFTWARE'], 'lighttpd')) { header('X-Sendfile: ' . $path); return true; } } // Désactiver gzip if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', 1); } @ini_set('zlib.output_compression', 'Off'); header('Content-Length: '. (int)$this->taille); ob_clean(); flush(); // Sinon on envoie le fichier à la mano readfile($path); } /** * Upload du fichier par POST * @param array $file Caractéristiques du fichier envoyé * @param string $titre Titre descriptif du fichier * @return boolean TRUE en cas de succès */ static public function upload($file, $titre) { // FIXME traiter les images envoyées redimensionnées par javascript (base64) $name = '...'; // FIXME name sanitization if (preg_match('/\.(?:php\d*|cgi|pl|perl|jsp|asp|py|exe|com|bat|vb[se]?|chm|pif|reg|ws[cfh]|scr|asp)$/i', $name)) { throw new UserException('Extension de fichier interdite.'); } $ext = substr($name, strrpos($name, '.')+1); $ext = strtolower($ext); if (!array_key_exists($ext, $this->allowed_files)) { throw new UserException('Ce type de fichier n\'est pas autorisé.'); } $bytes = file_get_contents($path, false, null, -1, 1024); $type = \KD2\FileInfo::guessMimeType($bytes); if (!$type) { throw new UserException('Type de fichier inconnu.'); } } } |
Modified src/include/lib/Garradin/Static_Cache.php from [f40cd20c85] to [5fabb1fda6].
︙ | ︙ | |||
8 9 10 11 12 13 14 | const CLEAN_EXPIRE = 86400; // 1 day protected static function _getCacheDir() { return CACHE_ROOT . '/static'; } | | > > > > > > > > > > > > > > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | const CLEAN_EXPIRE = 86400; // 1 day protected static function _getCacheDir() { return CACHE_ROOT . '/static'; } protected static function __getCachePath($id) { $id = 'cache_' . sha1($id); return self::_getCacheDir() . '/' . $id; } static public function store($id, $content) { $path = self::_getCachePath($id); return (bool) file_put_contents($path, $content); } static public function storeFromPointer($id, $pointer) { $path = self::_getCachePath($id); $fp = fopen($path, 'wb'); $ok = stream_copy_to_stream($pointer, $fp); fclose($fp); return $ok; } static public function storeFromUpload($id, $uploaded_file) { $path = self::_getCachePath($id); return (bool) move_uploaded_file($uploaded_file, $path); } static public function expired($id, $expire = self::EXPIRE) { $path = self::_getCachePath($id); $time = @filemtime($path); if (!$time) |
︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | return readfile($path); } static public function getPath($id) { return self::_getCachePath($id); } static public function remove($id) { $path = self::_getCachePath($id); return unlink($path); } | > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | return readfile($path); } static public function getPath($id) { return self::_getCachePath($id); } static public function exists($id) { return file_exists(self::_getCachePath($id)); } static public function remove($id) { $path = self::_getCachePath($id); return unlink($path); } |
︙ | ︙ |