Overview
Comment: | Débuts upload fichier |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
00cedbfb6a0044a3a2ef4520a9f273a6 |
User & Date: | bohwaz on 2015-02-04 06:29:22 |
Other Links: | manifest | tags |
Context
2015-02-04
| ||
06:44 | Renommage/déplacement du JS et utilisation de l'objet Garradin check-in: 5bd2724e7e user: bohwaz tags: trunk | |
06:29 | Débuts upload fichier check-in: 00cedbfb6a user: bohwaz tags: trunk | |
06:28 | Unification/simplification du Javascript check-in: 9c55662f07 user: bohwaz tags: trunk | |
Changes
Added doc/dev/fichiers.skriv version [1dfce7dbea].
> > > > > > > > > | 1 2 3 4 5 6 7 8 9 | = Les fichiers dans le code de Garradin = == Stockage == Pour minimiser les ressources (espace disque, temps processeur), le contenu du fichier est stocké séparé des méta-données du fichier. Ainsi un fichier peut être uploadé plusieurs fois, à plusieurs endroits différents, et n'être stocké qu'une seule fois. De même le cache ne stocke qu'une seule fois le fichier, quel que soit le nombre d'occurrences. == Upload == L'envoi de fichier utilise l'API javascript File pour lire les données du fichier avant envoi. Cela permet de vérifier que la taille du fichier rentre dans les clous. Mais on fait aussi un appel XHR avec le SHA1 du fichier (on utilise https://github.com/srijs/rusha pour ça) pour savoir s'il n'est pas déjà stocké. S'il est déjà stocké ça ne sert à rien de l'envoyer et gaspiller de la bande passante ou du processeur. |
Modified src/include/data/0.7.0.sql from [17a1af7af0] to [cbca4aa3a3].
︙ | ︙ | |||
12 13 14 15 16 17 18 | ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier | < | < | > > > > | 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 | ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ); 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, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB ); CREATE UNIQUE INDEX fichiers_hash ON fichiers_contenu (hash); 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), PRIMARY KEY(fichier, id) |
︙ | ︙ |
Modified src/include/data/schema.sql from [55e42ab66a] to [52605cc884].
︙ | ︙ | |||
329 330 331 332 333 334 335 | ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier | < | < | > > > > | 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 | ( id INTEGER NOT NULL PRIMARY KEY, nom TEXT NOT NULL, -- nom de fichier (par exemple image1234.jpeg) type TEXT NOT NULL, -- Type MIME image INTEGER NOT NULL DEFAULT 0, -- 1 = image reconnue titre TEXT NOT NULL, -- Titre/description date TEXT NOT NULL DEFAULT CURRENT_DATE, -- Date d'ajout ou mise à jour du fichier id_contenu INTEGER NOT NULL REFERENCES fichiers_contenu (id) ); 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, hash TEXT NOT NULL, -- Hash SHA1 du contenu du fichier taille INTEGER NOT NULL, -- Taille en octets contenu BLOB ); CREATE UNIQUE INDEX fichiers_hash ON fichiers_contenu (hash); 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), PRIMARY KEY(fichier, id) |
︙ | ︙ |
Modified src/include/lib/Garradin/Fichiers.php from [c00d51886f] to [9f13370bd2].
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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) | > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public $type; public $titre; public $nom; public $date; public $hash; public $taille; public $id; const LIEN_COMPTA = 'compta_journal'; const LIEN_WIKI = 'wiki_pages'; const LIEN_MEMBRES = 'membres'; 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) |
︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 | * @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) { } /** | > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > | | | 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 | * @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) { } public function linkTo($type, $foreign_id) { $db = DB::getInstance(); $check = [self::LIEN_MEMBRES, self::LIEN_WIKI, self::LIEN_COMPTA]; if (!in_array($type, $check)) { throw new \LogicException('Type de lien de fichier inconnu.'); } unset($check[array_search($type, $check)]); foreach ($check as $check_type) { if ($db->simpleQuerySingle('SELECT 1 FROM fichiers_' . $check_type . ' WHERE fichier = ?;', false, (int)$this->id)) { throw new \LogicException('Ce fichier est déjà lié à un autre contenu : ' . $check_type); } } return $db->simpleExec('INSERT OR IGNORE INTO fichiers_' . $type . ' (fichier, id) VALUES (?, ?);', (int)$this->id, (int)$foreign_id); } /** * Supprime le fichier * @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); // Suppression du contenu s'il n'est pas utilisé par un autre fichier if (!($id_contenu = $db->simpleQuerySingle('SELECT id_contenu FROM fichiers AS f1 INNER JOIN fichiers AS f2 ON f1.id_contenu = f2.id_contenu AND f1.id != f2.id WHERE f2.id = ?;', false, (int)$this->id))) { $db->simpleExec('DELETE FROM fichiers_contenu WHERE id = ?;', (int)$id_contenu); } $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() { // Le cache est géré par ID contenu, pas ID fichier, pour minimiser l'espace disque utilisé $cache_id = 'fichiers.' . $this->id_contenu; // 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_contenu); Static_Cache::storeFromPointer($cache_id, $blob); fclose($blob); } $path = Static_Cache::getPath($cache_id); // Désactiver le cache |
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 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 */ | > > > > > > > > > > > > > > > | | | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | ob_clean(); flush(); // Sinon on envoie le fichier à la mano readfile($path); } /** * Vérifie si le hash fourni n'est pas déjà stocké * Utile pour par exemple reconnaître un ficher dont le contenu est déjà stocké, et éviter un nouvel upload * @param string $hash Hash SHA1 * @return boolean TRUE si le hash est déjà présent dans fichiers_contenu, FALSE sinon */ static public function checkHash($hash) { return (boolean) DB::getInstance()->simpleQuerySingle( 'SELECT 1 FROM fichiers_contenu WHERE hash = ?;', false, trim(strtolower($hash)) ); } /** * 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, $allow_anything = false) { // FIXME traiter les images envoyées redimensionnées par javascript (base64) $name = '...'; // FIXME name sanitization if (!$allow_anything && 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 (!$allow_anything && !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 (!$allow_anything && !$type) { throw new UserException('Type de fichier inconnu.'); } } } |
Modified src/include/lib/Garradin/Static_Cache.php from [5fabb1fda6] to [80b1dfbb7b].
︙ | ︙ | |||
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 | 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) { |
︙ | ︙ |
Modified src/include/lib/Garradin/Template.php from [3482f439eb] to [31d36787f2].
︙ | ︙ | |||
602 603 604 605 606 607 608 | $tpl->register_modifier('format_bytes', function ($size) { if ($size > (1024 * 1024)) return round($size / 1024 / 1024, 2) . ' Mo'; elseif ($size > 1024) return round($size / 1024, 2) . ' Ko'; else | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 | $tpl->register_modifier('format_bytes', function ($size) { if ($size > (1024 * 1024)) return round($size / 1024 / 1024, 2) . ' Mo'; elseif ($size > 1024) return round($size / 1024, 2) . ' Ko'; else return $size . ' o'; }); $tpl->register_modifier('strftime_fr', 'Garradin\tpl_strftime_fr'); $tpl->register_modifier('date_fr', 'Garradin\tpl_date_fr'); ?> |
Added src/templates/admin/wiki/_fichiers.tpl version [67e6c5be20].
> > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | {include file="admin/_head.tpl" title="Inclure un fichier" current="wiki" body_id="popup" is_popup=true js=1} <form method="post" enctype="multipart/form-data" action="{$self_url|escape}" id="f_upload"> <fieldset> <legend>Téléverser un fichier</legend> <input type="hidden" name="MAX_FILE_SIZE" value="{$max_size|escape}" id="f_maxsize" /> <dl> <dt><label for="f_fichier">Sélectionner un fichier</label></dt> <dd class="help">Taille maximale : {$max_size|format_bytes}</dd> <dd><input type="file" name="fichier" id="f_fichier" /></dd> <dt><label for="f_titre">Titre du fichier (description)</label></dt> <dd><input type="text" name="titre" id="f_titre" /></dd> </dl> <p class="submit"> <input type="submit" id="f_submit" value="Envoyer le fichier" /> </p> </fieldset> </form> {include file="admin/_foot.tpl"} |
Added src/www/admin/static/scripts/file_upload.js version [8d3bcfe5d7].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | (function () { if (!FileReader || !File) return false; var uploadHelper = function () { var rusha = new Rusha(); var form = $('#f_upload'); var max_size = $('#f_maxsize').value; var admin_url = document.body.getAttribute('data-url'); form.onsubmit = function () { return true; }; $('#f_fichier').onchange = function () { if (this.files.length < 1) return false; if (this.files.length > 1) return !alert("Vous ne pouvez sélectionner qu'un seul fichier."); var file = this.files[0]; if (file.size > max_size) { this.value = ''; return !alert("Ce fichier de " + getByteSize(file.size) + " dépasse la taille autorisée de " + getByteSize(max_size) + ".\nEnvoi impossible !"); } var name = file.name.replace(/\.[^.]+/g, ''); name = name.replace(/[_.-]+/g, ' '); name = name.replace(/\w/, function (match) { return match.toUpperCase(); }); document.getElementById('f_titre').value = name; // Vérification de l'existence du fichier var fr = new FileReader; fr.onloadend = function () { if (this.error) return false; var hash = rusha.digestFromArrayBuffer(fr.result); garradin.load('admin/_upload_check.php?hash=' + hash, function (data) { if (parseInt(data, 10) == 1) { alert('ok'); } }) }; fr.readAsArrayBuffer(file); }; }; function getByteSize(size) { if (size < 1024) return size + ' octets'; else if (size < 1024*1024) return Math.round(size / 1024) + ' Ko'; else return (Math.round(size / 1024 / 1024 * 100) / 100) + ' Mo'; } garradin.onload(uploadHelper); }()); /*! rusha 2015-01-11 */ !function(){function a(a){"use strict";var d={fill:0},f=function(a){for(a+=9;a%64>0;a+=1);return a},g=function(a,b){for(var c=b>>2;c<a.length;c++)a[c]=0},h=function(a,b,c){a[b>>2]|=128<<24-(b%4<<3),a[((b>>2)+2&-16)+15]=c<<3},i=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g.charCodeAt(c);case 1:a[e+2|0]=g.charCodeAt(c+1);case 2:a[e+1|0]=g.charCodeAt(c+2);case 3:a[0|e]=g.charCodeAt(c+3)}for(f=h;j>f;f=f+4|0)b[e+f>>2]=g.charCodeAt(c+f)<<24|g.charCodeAt(c+f+1)<<16|g.charCodeAt(c+f+2)<<8|g.charCodeAt(c+f+3);switch(i){case 3:a[e+j+1|0]=g.charCodeAt(c+j+2);case 2:a[e+j+2|0]=g.charCodeAt(c+j+1);case 1:a[e+j+3|0]=g.charCodeAt(c+j)}},j=function(a,b,c,d,e){var f,g=this,h=e%4,i=d%4,j=d-i;if(j>0)switch(h){case 0:a[e+3|0]=g[c];case 1:a[e+2|0]=g[c+1];case 2:a[e+1|0]=g[c+2];case 3:a[0|e]=g[c+3]}for(f=4-h;j>f;f=f+=4)b[e+f>>2]=g[c+f]<<24|g[c+f+1]<<16|g[c+f+2]<<8|g[c+f+3];switch(i){case 3:a[e+j+1|0]=g[c+j+2];case 2:a[e+j+2|0]=g[c+j+1];case 1:a[e+j+3|0]=g[c+j]}},k=function(a,b,d,e,f){var g,h=this,i=f%4,j=e%4,k=e-j,l=new Uint8Array(c.readAsArrayBuffer(h.slice(d,d+e)));if(k>0)switch(i){case 0:a[f+3|0]=l[0];case 1:a[f+2|0]=l[1];case 2:a[f+1|0]=l[2];case 3:a[0|f]=l[3]}for(g=4-i;k>g;g=g+=4)b[f+g>>2]=l[g]<<24|l[g+1]<<16|l[g+2]<<8|l[g+3];switch(j){case 3:a[f+k+1|0]=l[k+2];case 2:a[f+k+2|0]=l[k+1];case 1:a[f+k+3|0]=l[k]}},l=function(a){switch(e.getDataType(a)){case"string":return i.bind(a);case"array":return j.bind(a);case"buffer":return j.bind(a);case"arraybuffer":return j.bind(new Uint8Array(a));case"view":return j.bind(new Uint8Array(a.buffer,a.byteOffset,a.byteLength));case"blob":return k.bind(a)}},m=function(a){var b,c,d="0123456789abcdef",e=[],f=new Uint8Array(a);for(b=0;b<f.length;b++)c=f[b],e[b]=d.charAt(c>>4&15)+d.charAt(c>>0&15);return e.join("")},n=function(a){var b;if(65536>=a)return 65536;if(16777216>a)for(b=1;a>b;b<<=1);else for(b=16777216;a>b;b+=16777216);return b},o=function(a){if(a%64>0)throw new Error("Chunk size must be a multiple of 128 bit");d.maxChunkLen=a,d.padMaxChunkLen=f(a),d.heap=new ArrayBuffer(n(d.padMaxChunkLen+320+20)),d.h32=new Int32Array(d.heap),d.h8=new Int8Array(d.heap),d.core=b({Int32Array:Int32Array,DataView:DataView},{},d.heap),d.buffer=null};o(a||65536);var p=function(a,b){var c=new Int32Array(a,b+320,5);c[0]=1732584193,c[1]=-271733879,c[2]=-1732584194,c[3]=271733878,c[4]=-1009589776},q=function(a,b){var c=f(a),e=new Int32Array(d.heap,0,c>>2);return g(e,a),h(e,a,b),c},r=function(a,b,c){l(a)(d.h8,d.h32,b,c,0)},s=function(a,b,c,e,f){var g=c;f&&(g=q(c,e)),r(a,b,c),d.core.hash(g,d.padMaxChunkLen)},t=function(a,b){var c=new Int32Array(a,b+320,5),d=new Int32Array(5),e=new DataView(d.buffer);return e.setInt32(0,c[0],!1),e.setInt32(4,c[1],!1),e.setInt32(8,c[2],!1),e.setInt32(12,c[3],!1),e.setInt32(16,c[4],!1),d},u=this.rawDigest=function(a){var b=a.byteLength||a.length||a.size;p(d.heap,d.padMaxChunkLen);var c=0,e=d.maxChunkLen;for(c=0;b>c+e;c+=e)s(a,c,e,b,!1);return s(a,c,b-c,b,!0),t(d.heap,d.padMaxChunkLen)};this.digest=this.digestFromString=this.digestFromBuffer=this.digestFromArrayBuffer=function(a){return m(u(a).buffer)}}function b(a,b,c){"use asm";function d(a,b){a|=0,b|=0;var c=0,d=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;for(f=e[b+320>>2]|0,h=e[b+324>>2]|0,j=e[b+328>>2]|0,l=e[b+332>>2]|0,n=e[b+336>>2]|0,c=0;(c|0)<(a|0);c=c+64|0){for(g=f,i=h,k=j,m=l,o=n,d=0;(d|0)<64;d=d+4|0)q=e[c+d>>2]|0,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[a+d>>2]=q;for(d=a+64|0;(d|0)<(a+80|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|~h&l)|0)+((q+n|0)+1518500249|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+80|0;(d|0)<(a+160|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)+1859775393|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+160|0;(d|0)<(a+240|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h&j|h&l|j&l)|0)+((q+n|0)-1894007588|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;for(d=a+240|0;(d|0)<(a+320|0);d=d+4|0)q=(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])<<1|(e[d-12>>2]^e[d-32>>2]^e[d-56>>2]^e[d-64>>2])>>>31,p=((f<<5|f>>>27)+(h^j^l)|0)+((q+n|0)-899497514|0)|0,n=l,l=j,j=h<<30|h>>>2,h=f,f=p,e[d>>2]=q;f=f+g|0,h=h+i|0,j=j+k|0,l=l+m|0,n=n+o|0}e[b+320>>2]=f,e[b+324>>2]=h,e[b+328>>2]=j,e[b+332>>2]=l,e[b+336>>2]=n}var e=new a.Int32Array(c);return{hash:d}}if("undefined"!=typeof module?module.exports=a:"undefined"!=typeof window&&(window.Rusha=a),"undefined"!=typeof FileReaderSync){var c=new FileReaderSync,d=new a(4194304);self.onmessage=function(a){var b,c=a.data.data;try{b=d.digest(c),self.postMessage({id:a.data.id,hash:b})}catch(e){self.postMessage({id:a.data.id,error:e.name})}}}var e={getDataType:function(a){if("string"==typeof a)return"string";if(a instanceof Array)return"array";if("undefined"!=typeof global&&global.Buffer&&global.Buffer.isBuffer(a))return"buffer";if(a instanceof ArrayBuffer)return"arraybuffer";if(a.buffer instanceof ArrayBuffer)return"view";if(a instanceof Blob)return"blob";throw new Error("Unsupported data type.")}}}(); |
Added src/www/admin/wiki/_fichiers.php version [219fbf114c].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; if ((trim(Utils::get('page')) == '') || !is_numeric(Utils::get('page'))) { throw new UserException('Numéro de page invalide.'); } $page = $wiki->getById(Utils::get('page')); $error = false; if (!$page) { throw new UserException('Page introuvable.'); } if (Utils::post('submit')) { if (!Utils::CSRF_check('file_upload_'.$page['id'])) { $error = 'Une erreur est survenue, merci de renvoyer le formulaire.'; } else { try { $fichier = Fichiers::upload($_FILES['fichier'], Utils::post('titre')); $fichier->link(Fichiers::LIEN_WIKI, $page['id']); Utils::redirect('/admin/wiki/_fichiers.php?ok'); } catch (UserException $e) { $error = $e->getMessage(); } } } $tpl->assign('max_size', Utils::getMaxUploadSize()); $tpl->assign('error', $error); $tpl->assign('sent', isset($_GET['sent']) ? true : false); $tpl->assign('custom_js', ['scripts/file_upload.js']); $tpl->display('admin/wiki/_fichiers.tpl'); |