@@ -17,13 +17,13 @@ discard block |
||
| 17 | 17 | **/ |
| 18 | 18 | |
| 19 | 19 | if (!defined('_ECRIRE_INC_VERSION')) { |
| 20 | - return; |
|
| 20 | + return; |
|
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | if (!defined('IMG_SVG')) { |
| 24 | - // complete IMG_BMP | IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP | IMG_XPM | IMG_WEBP |
|
| 25 | - define('IMG_SVG', 128); |
|
| 26 | - define('IMAGETYPE_SVG', 19); |
|
| 24 | + // complete IMG_BMP | IMG_GIF | IMG_JPG | IMG_PNG | IMG_WBMP | IMG_XPM | IMG_WEBP |
|
| 25 | + define('IMG_SVG', 128); |
|
| 26 | + define('IMAGETYPE_SVG', 19); |
|
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | /** |
@@ -39,39 +39,39 @@ discard block |
||
| 39 | 39 | * false si on a pas pu charger l'image |
| 40 | 40 | */ |
| 41 | 41 | function svg_charger($fichier, $maxlen = null) { |
| 42 | - if (strpos($fichier, 'data:image/svg+xml') === 0) { |
|
| 43 | - $image = explode(';', $fichier, 2); |
|
| 44 | - $image = end($image); |
|
| 45 | - if (strpos($image, 'base64,') === 0) { |
|
| 46 | - $image = base64_decode(substr($image, 7)); |
|
| 47 | - } |
|
| 48 | - if (strpos($image, '<svg') !== false) { |
|
| 49 | - return $image; |
|
| 50 | - } |
|
| 51 | - // encodage inconnu ou autre format d'image ? |
|
| 52 | - return false; |
|
| 53 | - } |
|
| 54 | - // c'est peut etre deja une image svg ? |
|
| 55 | - if (strpos($fichier, '<svg') !== false) { |
|
| 56 | - return $fichier; |
|
| 57 | - } |
|
| 58 | - if (!file_exists($fichier)) { |
|
| 59 | - $fichier = supprimer_timestamp($fichier); |
|
| 60 | - if (!file_exists($fichier)) { |
|
| 61 | - return false; |
|
| 62 | - } |
|
| 63 | - } |
|
| 64 | - if (is_null($maxlen)) { |
|
| 65 | - $image = file_get_contents($fichier); |
|
| 66 | - } |
|
| 67 | - else { |
|
| 68 | - $image = file_get_contents($fichier, false, null, 0, $maxlen); |
|
| 69 | - } |
|
| 70 | - // est-ce bien une image svg ? |
|
| 71 | - if (strpos($image, '<svg') !== false) { |
|
| 72 | - return $image; |
|
| 73 | - } |
|
| 74 | - return false; |
|
| 42 | + if (strpos($fichier, 'data:image/svg+xml') === 0) { |
|
| 43 | + $image = explode(';', $fichier, 2); |
|
| 44 | + $image = end($image); |
|
| 45 | + if (strpos($image, 'base64,') === 0) { |
|
| 46 | + $image = base64_decode(substr($image, 7)); |
|
| 47 | + } |
|
| 48 | + if (strpos($image, '<svg') !== false) { |
|
| 49 | + return $image; |
|
| 50 | + } |
|
| 51 | + // encodage inconnu ou autre format d'image ? |
|
| 52 | + return false; |
|
| 53 | + } |
|
| 54 | + // c'est peut etre deja une image svg ? |
|
| 55 | + if (strpos($fichier, '<svg') !== false) { |
|
| 56 | + return $fichier; |
|
| 57 | + } |
|
| 58 | + if (!file_exists($fichier)) { |
|
| 59 | + $fichier = supprimer_timestamp($fichier); |
|
| 60 | + if (!file_exists($fichier)) { |
|
| 61 | + return false; |
|
| 62 | + } |
|
| 63 | + } |
|
| 64 | + if (is_null($maxlen)) { |
|
| 65 | + $image = file_get_contents($fichier); |
|
| 66 | + } |
|
| 67 | + else { |
|
| 68 | + $image = file_get_contents($fichier, false, null, 0, $maxlen); |
|
| 69 | + } |
|
| 70 | + // est-ce bien une image svg ? |
|
| 71 | + if (strpos($image, '<svg') !== false) { |
|
| 72 | + return $image; |
|
| 73 | + } |
|
| 74 | + return false; |
|
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | /** |
@@ -80,28 +80,28 @@ discard block |
||
| 80 | 80 | * @return array|bool |
| 81 | 81 | */ |
| 82 | 82 | function svg_lire_balise_svg($fichier) { |
| 83 | - if (!$debut_fichier = svg_charger($fichier, 4096)) { |
|
| 84 | - return false; |
|
| 85 | - } |
|
| 86 | - |
|
| 87 | - if (($ps = stripos($debut_fichier, '<svg')) !== false) { |
|
| 88 | - $pe = stripos($debut_fichier, '>', $ps); |
|
| 89 | - $balise_svg = substr($debut_fichier, $ps, $pe - $ps + 1); |
|
| 90 | - |
|
| 91 | - if (preg_match_all(',([\w:\-]+)=,Uims', $balise_svg, $matches)) { |
|
| 92 | - if (!function_exists('extraire_attribut')) { |
|
| 93 | - include_spip('inc/filtres'); |
|
| 94 | - } |
|
| 95 | - $attributs = []; |
|
| 96 | - foreach ($matches[1] as $att) { |
|
| 97 | - $attributs[$att] = extraire_attribut($balise_svg, $att); |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - return [$balise_svg, $attributs]; |
|
| 101 | - } |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - return false; |
|
| 83 | + if (!$debut_fichier = svg_charger($fichier, 4096)) { |
|
| 84 | + return false; |
|
| 85 | + } |
|
| 86 | + |
|
| 87 | + if (($ps = stripos($debut_fichier, '<svg')) !== false) { |
|
| 88 | + $pe = stripos($debut_fichier, '>', $ps); |
|
| 89 | + $balise_svg = substr($debut_fichier, $ps, $pe - $ps + 1); |
|
| 90 | + |
|
| 91 | + if (preg_match_all(',([\w:\-]+)=,Uims', $balise_svg, $matches)) { |
|
| 92 | + if (!function_exists('extraire_attribut')) { |
|
| 93 | + include_spip('inc/filtres'); |
|
| 94 | + } |
|
| 95 | + $attributs = []; |
|
| 96 | + foreach ($matches[1] as $att) { |
|
| 97 | + $attributs[$att] = extraire_attribut($balise_svg, $att); |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + return [$balise_svg, $attributs]; |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + return false; |
|
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | /** |
@@ -111,12 +111,12 @@ discard block |
||
| 111 | 111 | */ |
| 112 | 112 | function svg_lire_attributs($img) { |
| 113 | 113 | |
| 114 | - if ($svg_infos = svg_lire_balise_svg($img)) { |
|
| 115 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 116 | - return $attributs; |
|
| 117 | - } |
|
| 114 | + if ($svg_infos = svg_lire_balise_svg($img)) { |
|
| 115 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 116 | + return $attributs; |
|
| 117 | + } |
|
| 118 | 118 | |
| 119 | - return false; |
|
| 119 | + return false; |
|
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | /** |
@@ -126,38 +126,38 @@ discard block |
||
| 126 | 126 | * @return bool|float|int |
| 127 | 127 | */ |
| 128 | 128 | function svg_dimension_to_pixels($dimension, $precision = 2) { |
| 129 | - if (preg_match(',^(-?\d+(\.\d+)?)([^\d]*),i', trim($dimension), $m)) { |
|
| 130 | - switch (strtolower($m[2])) { |
|
| 131 | - case '%': |
|
| 132 | - // on ne sait pas faire :( |
|
| 133 | - return false; |
|
| 134 | - break; |
|
| 135 | - case 'em': |
|
| 136 | - return round($m[1] * 16, $precision); // 16px font-size par defaut |
|
| 137 | - break; |
|
| 138 | - case 'ex': |
|
| 139 | - return round($m[1] * 16, $precision); // 16px font-size par defaut |
|
| 140 | - break; |
|
| 141 | - case 'pc': |
|
| 142 | - return round($m[1] * 16, $precision); // 1/6 inch = 96px/6 in CSS |
|
| 143 | - break; |
|
| 144 | - case 'cm': |
|
| 145 | - return round($m[1] * 96 / 2.54, $precision); // 96px / 2.54cm; |
|
| 146 | - break; |
|
| 147 | - case 'mm': |
|
| 148 | - return round($m[1] * 96 / 25.4, $precision); // 96px / 25.4mm; |
|
| 149 | - break; |
|
| 150 | - case 'in': |
|
| 151 | - return round($m[1] * 96, $precision); // 1 inch = 96px in CSS |
|
| 152 | - break; |
|
| 153 | - case 'px': |
|
| 154 | - case 'pt': |
|
| 155 | - default: |
|
| 156 | - return $m[1]; |
|
| 157 | - break; |
|
| 158 | - } |
|
| 159 | - } |
|
| 160 | - return false; |
|
| 129 | + if (preg_match(',^(-?\d+(\.\d+)?)([^\d]*),i', trim($dimension), $m)) { |
|
| 130 | + switch (strtolower($m[2])) { |
|
| 131 | + case '%': |
|
| 132 | + // on ne sait pas faire :( |
|
| 133 | + return false; |
|
| 134 | + break; |
|
| 135 | + case 'em': |
|
| 136 | + return round($m[1] * 16, $precision); // 16px font-size par defaut |
|
| 137 | + break; |
|
| 138 | + case 'ex': |
|
| 139 | + return round($m[1] * 16, $precision); // 16px font-size par defaut |
|
| 140 | + break; |
|
| 141 | + case 'pc': |
|
| 142 | + return round($m[1] * 16, $precision); // 1/6 inch = 96px/6 in CSS |
|
| 143 | + break; |
|
| 144 | + case 'cm': |
|
| 145 | + return round($m[1] * 96 / 2.54, $precision); // 96px / 2.54cm; |
|
| 146 | + break; |
|
| 147 | + case 'mm': |
|
| 148 | + return round($m[1] * 96 / 25.4, $precision); // 96px / 25.4mm; |
|
| 149 | + break; |
|
| 150 | + case 'in': |
|
| 151 | + return round($m[1] * 96, $precision); // 1 inch = 96px in CSS |
|
| 152 | + break; |
|
| 153 | + case 'px': |
|
| 154 | + case 'pt': |
|
| 155 | + default: |
|
| 156 | + return $m[1]; |
|
| 157 | + break; |
|
| 158 | + } |
|
| 159 | + } |
|
| 160 | + return false; |
|
| 161 | 161 | } |
| 162 | 162 | |
| 163 | 163 | /** |
@@ -168,15 +168,15 @@ discard block |
||
| 168 | 168 | * @return string |
| 169 | 169 | */ |
| 170 | 170 | function svg_change_balise_svg($svg, $old_balise_svg, $attributs) { |
| 171 | - $new_balise_svg = '<svg'; |
|
| 172 | - foreach ($attributs as $k => $v) { |
|
| 173 | - $new_balise_svg .= " $k=\"" . entites_html($v) . '"'; |
|
| 174 | - } |
|
| 175 | - $new_balise_svg .= '>'; |
|
| 176 | - |
|
| 177 | - $p = strpos($svg, $old_balise_svg); |
|
| 178 | - $svg = substr_replace($svg, $new_balise_svg, $p, strlen($old_balise_svg)); |
|
| 179 | - return $svg; |
|
| 171 | + $new_balise_svg = '<svg'; |
|
| 172 | + foreach ($attributs as $k => $v) { |
|
| 173 | + $new_balise_svg .= " $k=\"" . entites_html($v) . '"'; |
|
| 174 | + } |
|
| 175 | + $new_balise_svg .= '>'; |
|
| 176 | + |
|
| 177 | + $p = strpos($svg, $old_balise_svg); |
|
| 178 | + $svg = substr_replace($svg, $new_balise_svg, $p, strlen($old_balise_svg)); |
|
| 179 | + return $svg; |
|
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | /** |
@@ -188,15 +188,15 @@ discard block |
||
| 188 | 188 | */ |
| 189 | 189 | function svg_insert_shapes($svg, $shapes, $start = true) { |
| 190 | 190 | |
| 191 | - if ($start === false or $start === 'end') { |
|
| 192 | - $svg = str_replace('</svg>', $shapes . '</svg>', $svg); |
|
| 193 | - } |
|
| 194 | - else { |
|
| 195 | - $p = stripos($svg, '<svg'); |
|
| 196 | - $p = strpos($svg, '>', $p); |
|
| 197 | - $svg = substr_replace($svg, $shapes, $p + 1, 0); |
|
| 198 | - } |
|
| 199 | - return $svg; |
|
| 191 | + if ($start === false or $start === 'end') { |
|
| 192 | + $svg = str_replace('</svg>', $shapes . '</svg>', $svg); |
|
| 193 | + } |
|
| 194 | + else { |
|
| 195 | + $p = stripos($svg, '<svg'); |
|
| 196 | + $p = strpos($svg, '>', $p); |
|
| 197 | + $svg = substr_replace($svg, $shapes, $p + 1, 0); |
|
| 198 | + } |
|
| 199 | + return $svg; |
|
| 200 | 200 | } |
| 201 | 201 | |
| 202 | 202 | /** |
@@ -209,13 +209,13 @@ discard block |
||
| 209 | 209 | * @return string |
| 210 | 210 | */ |
| 211 | 211 | function svg_clip_in_box($svg, $x, $y, $width, $height) { |
| 212 | - $rect = "<rect x=\"$x\" y=\"$y\" width=\"$width\" height=\"$height\" />"; |
|
| 213 | - $id = 'clip-' . substr(md5($rect . strlen($svg)), 0, 8); |
|
| 214 | - $clippath = "<clipPath id=\"$id\">$rect</clipPath>"; |
|
| 215 | - $g = "<g clip-path=\"url(#$id)\">"; |
|
| 216 | - $svg = svg_insert_shapes($svg, $clippath . $g); |
|
| 217 | - $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 218 | - return $svg; |
|
| 212 | + $rect = "<rect x=\"$x\" y=\"$y\" width=\"$width\" height=\"$height\" />"; |
|
| 213 | + $id = 'clip-' . substr(md5($rect . strlen($svg)), 0, 8); |
|
| 214 | + $clippath = "<clipPath id=\"$id\">$rect</clipPath>"; |
|
| 215 | + $g = "<g clip-path=\"url(#$id)\">"; |
|
| 216 | + $svg = svg_insert_shapes($svg, $clippath . $g); |
|
| 217 | + $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 218 | + return $svg; |
|
| 219 | 219 | } |
| 220 | 220 | |
| 221 | 221 | /** |
@@ -226,22 +226,22 @@ discard block |
||
| 226 | 226 | * @return bool|string |
| 227 | 227 | */ |
| 228 | 228 | function svg_redimensionner($img, $new_width, $new_height) { |
| 229 | - if ( |
|
| 230 | - $svg = svg_charger($img) |
|
| 231 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 232 | - ) { |
|
| 233 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 234 | - if (!isset($attributs['viewBox'])) { |
|
| 235 | - $attributs['viewBox'] = '0 0 ' . $attributs['width'] . ' ' . $attributs['height']; |
|
| 236 | - } |
|
| 237 | - $attributs['width'] = strval($new_width); |
|
| 238 | - $attributs['height'] = strval($new_height); |
|
| 239 | - |
|
| 240 | - $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 241 | - return $svg; |
|
| 242 | - } |
|
| 243 | - |
|
| 244 | - return $img; |
|
| 229 | + if ( |
|
| 230 | + $svg = svg_charger($img) |
|
| 231 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 232 | + ) { |
|
| 233 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 234 | + if (!isset($attributs['viewBox'])) { |
|
| 235 | + $attributs['viewBox'] = '0 0 ' . $attributs['width'] . ' ' . $attributs['height']; |
|
| 236 | + } |
|
| 237 | + $attributs['width'] = strval($new_width); |
|
| 238 | + $attributs['height'] = strval($new_height); |
|
| 239 | + |
|
| 240 | + $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 241 | + return $svg; |
|
| 242 | + } |
|
| 243 | + |
|
| 244 | + return $img; |
|
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | /** |
@@ -250,15 +250,15 @@ discard block |
||
| 250 | 250 | * @return string |
| 251 | 251 | */ |
| 252 | 252 | function svg_couleur_to_hexa($couleur) { |
| 253 | - if (strpos($couleur, 'rgb(') === 0) { |
|
| 254 | - $c = explode(',', substr($couleur, 4)); |
|
| 255 | - $couleur = _couleur_dec_to_hex(intval($c[0]), intval($c[1]), intval($c[2])); |
|
| 256 | - } |
|
| 257 | - else { |
|
| 258 | - $couleur = couleur_html_to_hex($couleur); |
|
| 259 | - } |
|
| 260 | - $couleur = '#' . ltrim($couleur, '#'); |
|
| 261 | - return $couleur; |
|
| 253 | + if (strpos($couleur, 'rgb(') === 0) { |
|
| 254 | + $c = explode(',', substr($couleur, 4)); |
|
| 255 | + $couleur = _couleur_dec_to_hex(intval($c[0]), intval($c[1]), intval($c[2])); |
|
| 256 | + } |
|
| 257 | + else { |
|
| 258 | + $couleur = couleur_html_to_hex($couleur); |
|
| 259 | + } |
|
| 260 | + $couleur = '#' . ltrim($couleur, '#'); |
|
| 261 | + return $couleur; |
|
| 262 | 262 | } |
| 263 | 263 | |
| 264 | 264 | /** |
@@ -267,11 +267,11 @@ discard block |
||
| 267 | 267 | * @return array |
| 268 | 268 | */ |
| 269 | 269 | function svg_couleur_to_rgb($couleur) { |
| 270 | - if (strpos($couleur, 'rgb(') === 0) { |
|
| 271 | - $c = explode(',', substr($couleur, 4)); |
|
| 272 | - return ['red' => intval($c[0]),'green' => intval($c[1]),'blue' => intval($c[2])]; |
|
| 273 | - } |
|
| 274 | - return _couleur_hex_to_dec($couleur); |
|
| 270 | + if (strpos($couleur, 'rgb(') === 0) { |
|
| 271 | + $c = explode(',', substr($couleur, 4)); |
|
| 272 | + return ['red' => intval($c[0]),'green' => intval($c[1]),'blue' => intval($c[2])]; |
|
| 273 | + } |
|
| 274 | + return _couleur_hex_to_dec($couleur); |
|
| 275 | 275 | } |
| 276 | 276 | |
| 277 | 277 | |
@@ -281,80 +281,80 @@ discard block |
||
| 281 | 281 | * @return array |
| 282 | 282 | */ |
| 283 | 283 | function svg_getimagesize_from_attr($attributs) { |
| 284 | - $width = 350; // default width |
|
| 285 | - $height = 150; // default height |
|
| 286 | - |
|
| 287 | - $viewBox = "0 0 $width $height"; |
|
| 288 | - if (isset($attributs['viewBox'])) { |
|
| 289 | - $viewBox = $attributs['viewBox']; |
|
| 290 | - $viewBox = preg_replace(',\s+,', ' ', $viewBox); |
|
| 291 | - } |
|
| 292 | - // et on la convertit en px |
|
| 293 | - $viewBox = explode(' ', $viewBox); |
|
| 294 | - $viewBox = array_map('svg_dimension_to_pixels', $viewBox); |
|
| 295 | - if (!$viewBox[2]) { |
|
| 296 | - $viewBox[2] = $width; |
|
| 297 | - } |
|
| 298 | - if (!$viewBox[3]) { |
|
| 299 | - $viewBox[3] = $height; |
|
| 300 | - } |
|
| 301 | - |
|
| 302 | - $coeff = 1; |
|
| 303 | - if ( |
|
| 304 | - isset($attributs['width']) |
|
| 305 | - and $w = svg_dimension_to_pixels($attributs['width']) |
|
| 306 | - ) { |
|
| 307 | - $width = $w; |
|
| 308 | - // si on avait pas de viewBox, la construire a partir de ce width |
|
| 309 | - if (empty($attributs['viewBox'])) { |
|
| 310 | - $viewBox[2] = $width; |
|
| 311 | - // si pas de height valide, on suppose l'image carree |
|
| 312 | - $viewBox[3] = $width; |
|
| 313 | - } |
|
| 314 | - } |
|
| 315 | - else { |
|
| 316 | - // si on recupere la taille de la viewbox mais si la viewbox est petite on met un multiplicateur pour la taille finale |
|
| 317 | - $width = $viewBox[2]; |
|
| 318 | - if ($width < 1) { |
|
| 319 | - $coeff = max($coeff, 1000); |
|
| 320 | - } |
|
| 321 | - elseif ($width < 10) { |
|
| 322 | - $coeff = max($coeff, 100); |
|
| 323 | - } |
|
| 324 | - elseif ($width < 100) { |
|
| 325 | - $coeff = max($coeff, 10); |
|
| 326 | - } |
|
| 327 | - } |
|
| 328 | - if ( |
|
| 329 | - isset($attributs['height']) |
|
| 330 | - and $h = svg_dimension_to_pixels($attributs['height']) |
|
| 331 | - ) { |
|
| 332 | - $height = $h; |
|
| 333 | - // si on avait pas de viewBox, la construire a partir de ce height |
|
| 334 | - if (empty($attributs['viewBox'])) { |
|
| 335 | - $viewBox[3] = $height; |
|
| 336 | - } |
|
| 337 | - } |
|
| 338 | - else { |
|
| 339 | - $height = $viewBox[3]; |
|
| 340 | - if ($height < 1) { |
|
| 341 | - $coeff = max($coeff, 1000); |
|
| 342 | - } |
|
| 343 | - elseif ($height < 10) { |
|
| 344 | - $coeff = max($coeff, 100); |
|
| 345 | - } |
|
| 346 | - elseif ($height < 100) { |
|
| 347 | - $coeff = max($coeff, 10); |
|
| 348 | - } |
|
| 349 | - } |
|
| 350 | - |
|
| 351 | - // arrondir le width et height en pixel in fine |
|
| 352 | - $width = round($coeff * $width); |
|
| 353 | - $height = round($coeff * $height); |
|
| 354 | - |
|
| 355 | - $viewBox = implode(' ', $viewBox); |
|
| 356 | - |
|
| 357 | - return [$width, $height, $viewBox]; |
|
| 284 | + $width = 350; // default width |
|
| 285 | + $height = 150; // default height |
|
| 286 | + |
|
| 287 | + $viewBox = "0 0 $width $height"; |
|
| 288 | + if (isset($attributs['viewBox'])) { |
|
| 289 | + $viewBox = $attributs['viewBox']; |
|
| 290 | + $viewBox = preg_replace(',\s+,', ' ', $viewBox); |
|
| 291 | + } |
|
| 292 | + // et on la convertit en px |
|
| 293 | + $viewBox = explode(' ', $viewBox); |
|
| 294 | + $viewBox = array_map('svg_dimension_to_pixels', $viewBox); |
|
| 295 | + if (!$viewBox[2]) { |
|
| 296 | + $viewBox[2] = $width; |
|
| 297 | + } |
|
| 298 | + if (!$viewBox[3]) { |
|
| 299 | + $viewBox[3] = $height; |
|
| 300 | + } |
|
| 301 | + |
|
| 302 | + $coeff = 1; |
|
| 303 | + if ( |
|
| 304 | + isset($attributs['width']) |
|
| 305 | + and $w = svg_dimension_to_pixels($attributs['width']) |
|
| 306 | + ) { |
|
| 307 | + $width = $w; |
|
| 308 | + // si on avait pas de viewBox, la construire a partir de ce width |
|
| 309 | + if (empty($attributs['viewBox'])) { |
|
| 310 | + $viewBox[2] = $width; |
|
| 311 | + // si pas de height valide, on suppose l'image carree |
|
| 312 | + $viewBox[3] = $width; |
|
| 313 | + } |
|
| 314 | + } |
|
| 315 | + else { |
|
| 316 | + // si on recupere la taille de la viewbox mais si la viewbox est petite on met un multiplicateur pour la taille finale |
|
| 317 | + $width = $viewBox[2]; |
|
| 318 | + if ($width < 1) { |
|
| 319 | + $coeff = max($coeff, 1000); |
|
| 320 | + } |
|
| 321 | + elseif ($width < 10) { |
|
| 322 | + $coeff = max($coeff, 100); |
|
| 323 | + } |
|
| 324 | + elseif ($width < 100) { |
|
| 325 | + $coeff = max($coeff, 10); |
|
| 326 | + } |
|
| 327 | + } |
|
| 328 | + if ( |
|
| 329 | + isset($attributs['height']) |
|
| 330 | + and $h = svg_dimension_to_pixels($attributs['height']) |
|
| 331 | + ) { |
|
| 332 | + $height = $h; |
|
| 333 | + // si on avait pas de viewBox, la construire a partir de ce height |
|
| 334 | + if (empty($attributs['viewBox'])) { |
|
| 335 | + $viewBox[3] = $height; |
|
| 336 | + } |
|
| 337 | + } |
|
| 338 | + else { |
|
| 339 | + $height = $viewBox[3]; |
|
| 340 | + if ($height < 1) { |
|
| 341 | + $coeff = max($coeff, 1000); |
|
| 342 | + } |
|
| 343 | + elseif ($height < 10) { |
|
| 344 | + $coeff = max($coeff, 100); |
|
| 345 | + } |
|
| 346 | + elseif ($height < 100) { |
|
| 347 | + $coeff = max($coeff, 10); |
|
| 348 | + } |
|
| 349 | + } |
|
| 350 | + |
|
| 351 | + // arrondir le width et height en pixel in fine |
|
| 352 | + $width = round($coeff * $width); |
|
| 353 | + $height = round($coeff * $height); |
|
| 354 | + |
|
| 355 | + $viewBox = implode(' ', $viewBox); |
|
| 356 | + |
|
| 357 | + return [$width, $height, $viewBox]; |
|
| 358 | 358 | } |
| 359 | 359 | |
| 360 | 360 | /** |
@@ -370,25 +370,25 @@ discard block |
||
| 370 | 370 | * @return string |
| 371 | 371 | */ |
| 372 | 372 | function svg_force_viewBox_px($img, $force_width_and_height = false) { |
| 373 | - if ( |
|
| 374 | - $svg = svg_charger($img) |
|
| 375 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 376 | - ) { |
|
| 377 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 373 | + if ( |
|
| 374 | + $svg = svg_charger($img) |
|
| 375 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 376 | + ) { |
|
| 377 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 378 | 378 | |
| 379 | - [$width, $height, $viewBox] = svg_getimagesize_from_attr($attributs); |
|
| 379 | + [$width, $height, $viewBox] = svg_getimagesize_from_attr($attributs); |
|
| 380 | 380 | |
| 381 | - if ($force_width_and_height) { |
|
| 382 | - $attributs['width'] = $width; |
|
| 383 | - $attributs['height'] = $height; |
|
| 384 | - } |
|
| 381 | + if ($force_width_and_height) { |
|
| 382 | + $attributs['width'] = $width; |
|
| 383 | + $attributs['height'] = $height; |
|
| 384 | + } |
|
| 385 | 385 | |
| 386 | - $attributs['viewBox'] = $viewBox; |
|
| 386 | + $attributs['viewBox'] = $viewBox; |
|
| 387 | 387 | |
| 388 | - $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 389 | - return $svg; |
|
| 390 | - } |
|
| 391 | - return $img; |
|
| 388 | + $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 389 | + return $svg; |
|
| 390 | + } |
|
| 391 | + return $img; |
|
| 392 | 392 | } |
| 393 | 393 | |
| 394 | 394 | /** |
@@ -397,12 +397,12 @@ discard block |
||
| 397 | 397 | * @return array|mixed |
| 398 | 398 | */ |
| 399 | 399 | function svg_extract_couleurs($img) { |
| 400 | - if ($svg = svg_charger($img)) { |
|
| 401 | - if (preg_match_all('/(#[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])|(rgb\([\s\d]+,[\s\d]+,[\s\d]+\))|(#[0-9a-f][0-9a-f][0-9a-f])/imS', $svg, $matches)) { |
|
| 402 | - return $matches[0]; |
|
| 403 | - } |
|
| 404 | - } |
|
| 405 | - return []; |
|
| 400 | + if ($svg = svg_charger($img)) { |
|
| 401 | + if (preg_match_all('/(#[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])|(rgb\([\s\d]+,[\s\d]+,[\s\d]+\))|(#[0-9a-f][0-9a-f][0-9a-f])/imS', $svg, $matches)) { |
|
| 402 | + return $matches[0]; |
|
| 403 | + } |
|
| 404 | + } |
|
| 405 | + return []; |
|
| 406 | 406 | } |
| 407 | 407 | |
| 408 | 408 | /** |
@@ -413,58 +413,58 @@ discard block |
||
| 413 | 413 | * @return bool|string |
| 414 | 414 | */ |
| 415 | 415 | function svg_recadrer($img, $new_width, $new_height, $offset_width, $offset_height, $background_color = '') { |
| 416 | - if ( |
|
| 417 | - $svg = svg_force_viewBox_px($img) |
|
| 418 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 419 | - ) { |
|
| 420 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 421 | - $viewBox = explode(' ', $attributs['viewBox']); |
|
| 422 | - |
|
| 423 | - $viewport_w = $new_width; |
|
| 424 | - $viewport_h = $new_height; |
|
| 425 | - $viewport_ox = $offset_width; |
|
| 426 | - $viewport_oy = $offset_height; |
|
| 427 | - |
|
| 428 | - // si on a un width/height qui rescale, il faut rescaler |
|
| 429 | - if ( |
|
| 430 | - isset($attributs['width']) |
|
| 431 | - and $w = svg_dimension_to_pixels($attributs['width']) |
|
| 432 | - and isset($attributs['height']) |
|
| 433 | - and $h = svg_dimension_to_pixels($attributs['height']) |
|
| 434 | - ) { |
|
| 435 | - $xscale = $viewBox[2] / $w; |
|
| 436 | - $viewport_w = round($viewport_w * $xscale, 2); |
|
| 437 | - $viewport_ox = round($viewport_ox * $xscale, 2); |
|
| 438 | - $yscale = $viewBox[3] / $h; |
|
| 439 | - $viewport_h = round($viewport_h * $yscale, 2); |
|
| 440 | - $viewport_oy = round($viewport_oy * $yscale, 2); |
|
| 441 | - } |
|
| 442 | - |
|
| 443 | - if ($viewport_w > $viewBox[2] or $viewport_h > $viewBox[3]) { |
|
| 444 | - $svg = svg_clip_in_box($svg, $viewBox[0], $viewBox[1], $viewBox[2], $viewBox[3]); |
|
| 445 | - } |
|
| 446 | - |
|
| 447 | - // maintenant on redefinit la viewBox |
|
| 448 | - $viewBox[0] += $viewport_ox; |
|
| 449 | - $viewBox[1] += $viewport_oy; |
|
| 450 | - $viewBox[2] = $viewport_w; |
|
| 451 | - $viewBox[3] = $viewport_h; |
|
| 452 | - |
|
| 453 | - $attributs['viewBox'] = implode(' ', $viewBox); |
|
| 454 | - $attributs['width'] = strval($new_width); |
|
| 455 | - $attributs['height'] = strval($new_height); |
|
| 456 | - |
|
| 457 | - $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 458 | - |
|
| 459 | - // ajouter un background |
|
| 460 | - if ($background_color and $background_color !== 'transparent') { |
|
| 461 | - $svg = svg_ajouter_background($svg, $background_color); |
|
| 462 | - } |
|
| 463 | - |
|
| 464 | - return $svg; |
|
| 465 | - } |
|
| 466 | - |
|
| 467 | - return $img; |
|
| 416 | + if ( |
|
| 417 | + $svg = svg_force_viewBox_px($img) |
|
| 418 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 419 | + ) { |
|
| 420 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 421 | + $viewBox = explode(' ', $attributs['viewBox']); |
|
| 422 | + |
|
| 423 | + $viewport_w = $new_width; |
|
| 424 | + $viewport_h = $new_height; |
|
| 425 | + $viewport_ox = $offset_width; |
|
| 426 | + $viewport_oy = $offset_height; |
|
| 427 | + |
|
| 428 | + // si on a un width/height qui rescale, il faut rescaler |
|
| 429 | + if ( |
|
| 430 | + isset($attributs['width']) |
|
| 431 | + and $w = svg_dimension_to_pixels($attributs['width']) |
|
| 432 | + and isset($attributs['height']) |
|
| 433 | + and $h = svg_dimension_to_pixels($attributs['height']) |
|
| 434 | + ) { |
|
| 435 | + $xscale = $viewBox[2] / $w; |
|
| 436 | + $viewport_w = round($viewport_w * $xscale, 2); |
|
| 437 | + $viewport_ox = round($viewport_ox * $xscale, 2); |
|
| 438 | + $yscale = $viewBox[3] / $h; |
|
| 439 | + $viewport_h = round($viewport_h * $yscale, 2); |
|
| 440 | + $viewport_oy = round($viewport_oy * $yscale, 2); |
|
| 441 | + } |
|
| 442 | + |
|
| 443 | + if ($viewport_w > $viewBox[2] or $viewport_h > $viewBox[3]) { |
|
| 444 | + $svg = svg_clip_in_box($svg, $viewBox[0], $viewBox[1], $viewBox[2], $viewBox[3]); |
|
| 445 | + } |
|
| 446 | + |
|
| 447 | + // maintenant on redefinit la viewBox |
|
| 448 | + $viewBox[0] += $viewport_ox; |
|
| 449 | + $viewBox[1] += $viewport_oy; |
|
| 450 | + $viewBox[2] = $viewport_w; |
|
| 451 | + $viewBox[3] = $viewport_h; |
|
| 452 | + |
|
| 453 | + $attributs['viewBox'] = implode(' ', $viewBox); |
|
| 454 | + $attributs['width'] = strval($new_width); |
|
| 455 | + $attributs['height'] = strval($new_height); |
|
| 456 | + |
|
| 457 | + $svg = svg_change_balise_svg($svg, $balise_svg, $attributs); |
|
| 458 | + |
|
| 459 | + // ajouter un background |
|
| 460 | + if ($background_color and $background_color !== 'transparent') { |
|
| 461 | + $svg = svg_ajouter_background($svg, $background_color); |
|
| 462 | + } |
|
| 463 | + |
|
| 464 | + return $svg; |
|
| 465 | + } |
|
| 466 | + |
|
| 467 | + return $img; |
|
| 468 | 468 | } |
| 469 | 469 | |
| 470 | 470 | /** |
@@ -474,26 +474,26 @@ discard block |
||
| 474 | 474 | * @return bool|string |
| 475 | 475 | */ |
| 476 | 476 | function svg_ajouter_background($img, $background_color) { |
| 477 | - if ( |
|
| 478 | - $svg = svg_charger($img) |
|
| 479 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 480 | - ) { |
|
| 481 | - if ($background_color and $background_color !== 'transparent') { |
|
| 482 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 483 | - |
|
| 484 | - $background_color = svg_couleur_to_hexa($background_color); |
|
| 485 | - if (isset($attributs['viewBox'])) { |
|
| 486 | - $viewBox = explode(' ', $attributs['viewBox']); |
|
| 487 | - $rect = '<rect x="' . $viewBox[0] . '" y="' . $viewBox[1] . '" width="' . $viewBox[2] . '" height="' . $viewBox[3] . "\" fill=\"$background_color\"/>"; |
|
| 488 | - } |
|
| 489 | - else { |
|
| 490 | - $rect = "<rect width=\"100%\" height=\"100%\" fill=\"$background_color\"/>"; |
|
| 491 | - } |
|
| 492 | - $svg = svg_insert_shapes($svg, $rect); |
|
| 493 | - } |
|
| 494 | - return $svg; |
|
| 495 | - } |
|
| 496 | - return $img; |
|
| 477 | + if ( |
|
| 478 | + $svg = svg_charger($img) |
|
| 479 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 480 | + ) { |
|
| 481 | + if ($background_color and $background_color !== 'transparent') { |
|
| 482 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 483 | + |
|
| 484 | + $background_color = svg_couleur_to_hexa($background_color); |
|
| 485 | + if (isset($attributs['viewBox'])) { |
|
| 486 | + $viewBox = explode(' ', $attributs['viewBox']); |
|
| 487 | + $rect = '<rect x="' . $viewBox[0] . '" y="' . $viewBox[1] . '" width="' . $viewBox[2] . '" height="' . $viewBox[3] . "\" fill=\"$background_color\"/>"; |
|
| 488 | + } |
|
| 489 | + else { |
|
| 490 | + $rect = "<rect width=\"100%\" height=\"100%\" fill=\"$background_color\"/>"; |
|
| 491 | + } |
|
| 492 | + $svg = svg_insert_shapes($svg, $rect); |
|
| 493 | + } |
|
| 494 | + return $svg; |
|
| 495 | + } |
|
| 496 | + return $img; |
|
| 497 | 497 | } |
| 498 | 498 | |
| 499 | 499 | |
@@ -504,26 +504,26 @@ discard block |
||
| 504 | 504 | * @return bool|string |
| 505 | 505 | */ |
| 506 | 506 | function svg_ajouter_voile($img, $background_color, $opacity) { |
| 507 | - if ( |
|
| 508 | - $svg = svg_charger($img) |
|
| 509 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 510 | - ) { |
|
| 511 | - if ($background_color and $background_color !== 'transparent') { |
|
| 512 | - [$balise_svg, $attributs] = $svg_infos; |
|
| 513 | - |
|
| 514 | - $background_color = svg_couleur_to_hexa($background_color); |
|
| 515 | - if (isset($attributs['viewBox'])) { |
|
| 516 | - $viewBox = explode(' ', $attributs['viewBox']); |
|
| 517 | - $rect = '<rect x="' . $viewBox[0] . '" y="' . $viewBox[1] . '" width="' . $viewBox[2] . '" height="' . $viewBox[3] . "\" fill=\"$background_color\" opacity=\"$opacity\"/>"; |
|
| 518 | - } |
|
| 519 | - else { |
|
| 520 | - $rect = "<rect width=\"100%\" height=\"100%\" fill=\"$background_color\"/>"; |
|
| 521 | - } |
|
| 522 | - $svg = svg_insert_shapes($svg, $rect, false); |
|
| 523 | - } |
|
| 524 | - return $svg; |
|
| 525 | - } |
|
| 526 | - return $img; |
|
| 507 | + if ( |
|
| 508 | + $svg = svg_charger($img) |
|
| 509 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 510 | + ) { |
|
| 511 | + if ($background_color and $background_color !== 'transparent') { |
|
| 512 | + [$balise_svg, $attributs] = $svg_infos; |
|
| 513 | + |
|
| 514 | + $background_color = svg_couleur_to_hexa($background_color); |
|
| 515 | + if (isset($attributs['viewBox'])) { |
|
| 516 | + $viewBox = explode(' ', $attributs['viewBox']); |
|
| 517 | + $rect = '<rect x="' . $viewBox[0] . '" y="' . $viewBox[1] . '" width="' . $viewBox[2] . '" height="' . $viewBox[3] . "\" fill=\"$background_color\" opacity=\"$opacity\"/>"; |
|
| 518 | + } |
|
| 519 | + else { |
|
| 520 | + $rect = "<rect width=\"100%\" height=\"100%\" fill=\"$background_color\"/>"; |
|
| 521 | + } |
|
| 522 | + $svg = svg_insert_shapes($svg, $rect, false); |
|
| 523 | + } |
|
| 524 | + return $svg; |
|
| 525 | + } |
|
| 526 | + return $img; |
|
| 527 | 527 | } |
| 528 | 528 | |
| 529 | 529 | |
@@ -534,27 +534,27 @@ discard block |
||
| 534 | 534 | * @return bool|string |
| 535 | 535 | */ |
| 536 | 536 | function svg_transformer($img, $attributs) { |
| 537 | - if ( |
|
| 538 | - $svg = svg_charger($img) |
|
| 539 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 540 | - ) { |
|
| 541 | - if ($attributs) { |
|
| 542 | - [$balise_svg, ] = $svg_infos; |
|
| 543 | - $g = '<g'; |
|
| 544 | - foreach ($attributs as $k => $v) { |
|
| 545 | - if (strlen($v)) { |
|
| 546 | - $g .= " $k=\"" . attribut_html($v) . '"'; |
|
| 547 | - } |
|
| 548 | - } |
|
| 549 | - if (strlen($g) > 2) { |
|
| 550 | - $g .= '>'; |
|
| 551 | - $svg = svg_insert_shapes($svg, $g); |
|
| 552 | - $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 553 | - } |
|
| 554 | - } |
|
| 555 | - return $svg; |
|
| 556 | - } |
|
| 557 | - return $img; |
|
| 537 | + if ( |
|
| 538 | + $svg = svg_charger($img) |
|
| 539 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 540 | + ) { |
|
| 541 | + if ($attributs) { |
|
| 542 | + [$balise_svg, ] = $svg_infos; |
|
| 543 | + $g = '<g'; |
|
| 544 | + foreach ($attributs as $k => $v) { |
|
| 545 | + if (strlen($v)) { |
|
| 546 | + $g .= " $k=\"" . attribut_html($v) . '"'; |
|
| 547 | + } |
|
| 548 | + } |
|
| 549 | + if (strlen($g) > 2) { |
|
| 550 | + $g .= '>'; |
|
| 551 | + $svg = svg_insert_shapes($svg, $g); |
|
| 552 | + $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 553 | + } |
|
| 554 | + } |
|
| 555 | + return $svg; |
|
| 556 | + } |
|
| 557 | + return $img; |
|
| 558 | 558 | } |
| 559 | 559 | |
| 560 | 560 | /** |
@@ -565,21 +565,21 @@ discard block |
||
| 565 | 565 | * @return bool|string |
| 566 | 566 | */ |
| 567 | 567 | function svg_apply_filter($img, $filter_def) { |
| 568 | - if ( |
|
| 569 | - $svg = svg_charger($img) |
|
| 570 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 571 | - ) { |
|
| 572 | - if ($filter_def) { |
|
| 573 | - [$balise_svg, ] = $svg_infos; |
|
| 574 | - $filter_id = 'filter-' . substr(md5($filter_def . strlen($svg)), 0, 8); |
|
| 575 | - $filter = "<defs><filter id=\"$filter_id\">$filter_def</filter></defs>"; |
|
| 576 | - $g = "<g filter=\"url(#$filter_id)\">"; |
|
| 577 | - $svg = svg_insert_shapes($svg, $filter . $g); |
|
| 578 | - $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 579 | - } |
|
| 580 | - return $svg; |
|
| 581 | - } |
|
| 582 | - return $img; |
|
| 568 | + if ( |
|
| 569 | + $svg = svg_charger($img) |
|
| 570 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 571 | + ) { |
|
| 572 | + if ($filter_def) { |
|
| 573 | + [$balise_svg, ] = $svg_infos; |
|
| 574 | + $filter_id = 'filter-' . substr(md5($filter_def . strlen($svg)), 0, 8); |
|
| 575 | + $filter = "<defs><filter id=\"$filter_id\">$filter_def</filter></defs>"; |
|
| 576 | + $g = "<g filter=\"url(#$filter_id)\">"; |
|
| 577 | + $svg = svg_insert_shapes($svg, $filter . $g); |
|
| 578 | + $svg = svg_insert_shapes($svg, '</g>', false); |
|
| 579 | + } |
|
| 580 | + return $svg; |
|
| 581 | + } |
|
| 582 | + return $img; |
|
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 585 | /** |
@@ -589,8 +589,8 @@ discard block |
||
| 589 | 589 | * @return string |
| 590 | 590 | */ |
| 591 | 591 | function svg_filter_blur($img, $blur_width) { |
| 592 | - $blur_width = intval($blur_width); |
|
| 593 | - return svg_apply_filter($img, "<feGaussianBlur stdDeviation=\"$blur_width\"/>"); |
|
| 592 | + $blur_width = intval($blur_width); |
|
| 593 | + return svg_apply_filter($img, "<feGaussianBlur stdDeviation=\"$blur_width\"/>"); |
|
| 594 | 594 | } |
| 595 | 595 | |
| 596 | 596 | /** |
@@ -600,10 +600,10 @@ discard block |
||
| 600 | 600 | * @return bool|string |
| 601 | 601 | */ |
| 602 | 602 | function svg_filter_grayscale($img, $intensity) { |
| 603 | - $value = round(1.0 - $intensity, 2); |
|
| 604 | - //$filter = "<feColorMatrix type=\"matrix\" values=\"0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\"/>"; |
|
| 605 | - $filter = "<feColorMatrix type=\"saturate\" values=\"$value\"/>"; |
|
| 606 | - return svg_apply_filter($img, $filter); |
|
| 603 | + $value = round(1.0 - $intensity, 2); |
|
| 604 | + //$filter = "<feColorMatrix type=\"matrix\" values=\"0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\"/>"; |
|
| 605 | + $filter = "<feColorMatrix type=\"saturate\" values=\"$value\"/>"; |
|
| 606 | + return svg_apply_filter($img, $filter); |
|
| 607 | 607 | } |
| 608 | 608 | |
| 609 | 609 | /** |
@@ -613,8 +613,8 @@ discard block |
||
| 613 | 613 | * @return bool|string |
| 614 | 614 | */ |
| 615 | 615 | function svg_filter_sepia($img, $intensity) { |
| 616 | - $filter = '<feColorMatrix type="matrix" values="0.30 0.30 0.30 0.0 0 0.25 0.25 0.25 0.0 0 0.20 0.20 0.20 0.0 0 0.00 0.00 0.00 1 0"/>'; |
|
| 617 | - return svg_apply_filter($img, $filter); |
|
| 616 | + $filter = '<feColorMatrix type="matrix" values="0.30 0.30 0.30 0.0 0 0.25 0.25 0.25 0.0 0 0.20 0.20 0.20 0.0 0 0.00 0.00 0.00 1 0"/>'; |
|
| 617 | + return svg_apply_filter($img, $filter); |
|
| 618 | 618 | } |
| 619 | 619 | |
| 620 | 620 | /** |
@@ -624,31 +624,31 @@ discard block |
||
| 624 | 624 | * @return bool|string |
| 625 | 625 | */ |
| 626 | 626 | function svg_flip($img, $HorV) { |
| 627 | - if ( |
|
| 628 | - $svg = svg_force_viewBox_px($img) |
|
| 629 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 630 | - ) { |
|
| 631 | - [$balise_svg, $atts] = $svg_infos; |
|
| 632 | - $viewBox = explode(' ', $atts['viewBox']); |
|
| 633 | - |
|
| 634 | - if (!in_array($HorV, ['h', 'H'])) { |
|
| 635 | - $transform = 'scale(-1,1)'; |
|
| 636 | - |
|
| 637 | - $x = intval($viewBox[0]) + intval($viewBox[2] / 2); |
|
| 638 | - $mx = -$x; |
|
| 639 | - $transform = "translate($x, 0) $transform translate($mx, 0)"; |
|
| 640 | - } |
|
| 641 | - else { |
|
| 642 | - $transform = 'scale(1,-1)'; |
|
| 643 | - |
|
| 644 | - $y = intval($viewBox[1]) + intval($viewBox[3] / 2); |
|
| 645 | - $my = -$y; |
|
| 646 | - $transform = "translate(0, $y) $transform translate(0, $my)"; |
|
| 647 | - } |
|
| 648 | - $svg = svg_transformer($svg, ['transform' => $transform]); |
|
| 649 | - return $svg; |
|
| 650 | - } |
|
| 651 | - return $img; |
|
| 627 | + if ( |
|
| 628 | + $svg = svg_force_viewBox_px($img) |
|
| 629 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 630 | + ) { |
|
| 631 | + [$balise_svg, $atts] = $svg_infos; |
|
| 632 | + $viewBox = explode(' ', $atts['viewBox']); |
|
| 633 | + |
|
| 634 | + if (!in_array($HorV, ['h', 'H'])) { |
|
| 635 | + $transform = 'scale(-1,1)'; |
|
| 636 | + |
|
| 637 | + $x = intval($viewBox[0]) + intval($viewBox[2] / 2); |
|
| 638 | + $mx = -$x; |
|
| 639 | + $transform = "translate($x, 0) $transform translate($mx, 0)"; |
|
| 640 | + } |
|
| 641 | + else { |
|
| 642 | + $transform = 'scale(1,-1)'; |
|
| 643 | + |
|
| 644 | + $y = intval($viewBox[1]) + intval($viewBox[3] / 2); |
|
| 645 | + $my = -$y; |
|
| 646 | + $transform = "translate(0, $y) $transform translate(0, $my)"; |
|
| 647 | + } |
|
| 648 | + $svg = svg_transformer($svg, ['transform' => $transform]); |
|
| 649 | + return $svg; |
|
| 650 | + } |
|
| 651 | + return $img; |
|
| 652 | 652 | } |
| 653 | 653 | |
| 654 | 654 | /** |
@@ -662,20 +662,20 @@ discard block |
||
| 662 | 662 | * @return bool|string |
| 663 | 663 | */ |
| 664 | 664 | function svg_rotate($img, $angle, $center_x, $center_y) { |
| 665 | - if ( |
|
| 666 | - $svg = svg_force_viewBox_px($img) |
|
| 667 | - and $svg_infos = svg_lire_balise_svg($svg) |
|
| 668 | - ) { |
|
| 669 | - [$balise_svg, $atts] = $svg_infos; |
|
| 670 | - $viewBox = explode(' ', $atts['viewBox']); |
|
| 671 | - |
|
| 672 | - $center_x = round($viewBox[0] + $center_x * $viewBox[2]); |
|
| 673 | - $center_y = round($viewBox[1] + $center_y * $viewBox[3]); |
|
| 674 | - $svg = svg_transformer($svg, ['transform' => "rotate($angle $center_x $center_y)"]); |
|
| 675 | - |
|
| 676 | - return $svg; |
|
| 677 | - } |
|
| 678 | - return $img; |
|
| 665 | + if ( |
|
| 666 | + $svg = svg_force_viewBox_px($img) |
|
| 667 | + and $svg_infos = svg_lire_balise_svg($svg) |
|
| 668 | + ) { |
|
| 669 | + [$balise_svg, $atts] = $svg_infos; |
|
| 670 | + $viewBox = explode(' ', $atts['viewBox']); |
|
| 671 | + |
|
| 672 | + $center_x = round($viewBox[0] + $center_x * $viewBox[2]); |
|
| 673 | + $center_y = round($viewBox[1] + $center_y * $viewBox[3]); |
|
| 674 | + $svg = svg_transformer($svg, ['transform' => "rotate($angle $center_x $center_y)"]); |
|
| 675 | + |
|
| 676 | + return $svg; |
|
| 677 | + } |
|
| 678 | + return $img; |
|
| 679 | 679 | } |
| 680 | 680 | |
| 681 | 681 | /** |
@@ -687,41 +687,41 @@ discard block |
||
| 687 | 687 | * @return bool|mixed|string |
| 688 | 688 | */ |
| 689 | 689 | function svg_filtrer_couleurs($img, $callback_filter) { |
| 690 | - if ( |
|
| 691 | - $svg = svg_force_viewBox_px($img) |
|
| 692 | - and $colors = svg_extract_couleurs($svg) |
|
| 693 | - ) { |
|
| 694 | - $colors = array_unique($colors); |
|
| 695 | - |
|
| 696 | - $short = []; |
|
| 697 | - $long = []; |
|
| 698 | - while (count($colors)) { |
|
| 699 | - $c = array_shift($colors); |
|
| 700 | - if (strlen($c) == 4) { |
|
| 701 | - $short[] = $c; |
|
| 702 | - } |
|
| 703 | - else { |
|
| 704 | - $long[] = $c; |
|
| 705 | - } |
|
| 706 | - } |
|
| 707 | - |
|
| 708 | - $colors = [...$long, ...$short]; |
|
| 709 | - $new_colors = []; |
|
| 710 | - $colors = array_flip($colors); |
|
| 711 | - foreach ($colors as $c => $k) { |
|
| 712 | - $colors[$c] = "@@@COLOR$$k$@@@"; |
|
| 713 | - } |
|
| 714 | - |
|
| 715 | - |
|
| 716 | - foreach ($colors as $original => $replace) { |
|
| 717 | - $new = svg_couleur_to_hexa($original); |
|
| 718 | - $new_colors[$replace] = $callback_filter($new); |
|
| 719 | - } |
|
| 720 | - |
|
| 721 | - $svg = str_replace(array_keys($colors), array_values($colors), $svg); |
|
| 722 | - $svg = str_replace(array_keys($new_colors), array_values($new_colors), $svg); |
|
| 723 | - |
|
| 724 | - return $svg; |
|
| 725 | - } |
|
| 726 | - return $img; |
|
| 690 | + if ( |
|
| 691 | + $svg = svg_force_viewBox_px($img) |
|
| 692 | + and $colors = svg_extract_couleurs($svg) |
|
| 693 | + ) { |
|
| 694 | + $colors = array_unique($colors); |
|
| 695 | + |
|
| 696 | + $short = []; |
|
| 697 | + $long = []; |
|
| 698 | + while (count($colors)) { |
|
| 699 | + $c = array_shift($colors); |
|
| 700 | + if (strlen($c) == 4) { |
|
| 701 | + $short[] = $c; |
|
| 702 | + } |
|
| 703 | + else { |
|
| 704 | + $long[] = $c; |
|
| 705 | + } |
|
| 706 | + } |
|
| 707 | + |
|
| 708 | + $colors = [...$long, ...$short]; |
|
| 709 | + $new_colors = []; |
|
| 710 | + $colors = array_flip($colors); |
|
| 711 | + foreach ($colors as $c => $k) { |
|
| 712 | + $colors[$c] = "@@@COLOR$$k$@@@"; |
|
| 713 | + } |
|
| 714 | + |
|
| 715 | + |
|
| 716 | + foreach ($colors as $original => $replace) { |
|
| 717 | + $new = svg_couleur_to_hexa($original); |
|
| 718 | + $new_colors[$replace] = $callback_filter($new); |
|
| 719 | + } |
|
| 720 | + |
|
| 721 | + $svg = str_replace(array_keys($colors), array_values($colors), $svg); |
|
| 722 | + $svg = str_replace(array_keys($new_colors), array_values($new_colors), $svg); |
|
| 723 | + |
|
| 724 | + return $svg; |
|
| 725 | + } |
|
| 726 | + return $img; |
|
| 727 | 727 | } |
@@ -16,7 +16,7 @@ discard block |
||
| 16 | 16 | * @package SPIP\Core\Mail |
| 17 | 17 | **/ |
| 18 | 18 | if (!defined('_ECRIRE_INC_VERSION')) { |
| 19 | - return; |
|
| 19 | + return; |
|
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | include_spip('inc/charsets'); |
@@ -32,7 +32,7 @@ discard block |
||
| 32 | 32 | * @return string |
| 33 | 33 | */ |
| 34 | 34 | function nettoyer_titre_email($titre) { |
| 35 | - return str_replace("\n", ' ', nettoyer_caracteres_mail(textebrut(corriger_typo($titre)))); |
|
| 35 | + return str_replace("\n", ' ', nettoyer_caracteres_mail(textebrut(corriger_typo($titre)))); |
|
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | /** |
@@ -48,23 +48,23 @@ discard block |
||
| 48 | 48 | */ |
| 49 | 49 | function nettoyer_caracteres_mail($t) { |
| 50 | 50 | |
| 51 | - $t = filtrer_entites($t); |
|
| 51 | + $t = filtrer_entites($t); |
|
| 52 | 52 | |
| 53 | - if ($GLOBALS['meta']['charset'] <> 'utf-8') { |
|
| 54 | - $t = str_replace( |
|
| 55 | - ['’', '“', '”'], |
|
| 56 | - ["'", '"', '"'], |
|
| 57 | - $t |
|
| 58 | - ); |
|
| 59 | - } |
|
| 53 | + if ($GLOBALS['meta']['charset'] <> 'utf-8') { |
|
| 54 | + $t = str_replace( |
|
| 55 | + ['’', '“', '”'], |
|
| 56 | + ["'", '"', '"'], |
|
| 57 | + $t |
|
| 58 | + ); |
|
| 59 | + } |
|
| 60 | 60 | |
| 61 | - $t = str_replace( |
|
| 62 | - ['—', '&endash;'], |
|
| 63 | - ['--', '-'], |
|
| 64 | - $t |
|
| 65 | - ); |
|
| 61 | + $t = str_replace( |
|
| 62 | + ['—', '&endash;'], |
|
| 63 | + ['--', '-'], |
|
| 64 | + $t |
|
| 65 | + ); |
|
| 66 | 66 | |
| 67 | - return $t; |
|
| 67 | + return $t; |
|
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | /** |
@@ -97,87 +97,87 @@ discard block |
||
| 97 | 97 | */ |
| 98 | 98 | function inc_envoyer_mail_dist($destinataire, $sujet, $corps, $from = '', $headers = '') { |
| 99 | 99 | |
| 100 | - if (!email_valide($destinataire)) { |
|
| 101 | - return false; |
|
| 102 | - } |
|
| 103 | - if ($destinataire == _T('info_mail_fournisseur')) { |
|
| 104 | - return false; |
|
| 105 | - } // tres fort |
|
| 106 | - |
|
| 107 | - // Fournir si possible un Message-Id: conforme au RFC1036, |
|
| 108 | - // sinon SpamAssassin denoncera un MSGID_FROM_MTA_HEADER |
|
| 109 | - |
|
| 110 | - $email_envoi = $GLOBALS['meta']['email_envoi']; |
|
| 111 | - if (!email_valide($email_envoi)) { |
|
| 112 | - spip_log('Meta email_envoi invalide. Le mail sera probablement vu comme spam.'); |
|
| 113 | - $email_envoi = $destinataire; |
|
| 114 | - } |
|
| 115 | - |
|
| 116 | - $parts = ''; |
|
| 117 | - if (is_array($corps)) { |
|
| 118 | - $texte = $corps['texte']; |
|
| 119 | - $from = ($corps['from'] ?? $from); |
|
| 120 | - $headers = ($corps['headers'] ?? $headers); |
|
| 121 | - if (is_array($headers)) { |
|
| 122 | - $headers = implode("\n", $headers); |
|
| 123 | - } |
|
| 124 | - if (isset($corps['pieces_jointes']) and function_exists('mail_embarquer_pieces_jointes')) { |
|
| 125 | - $parts = mail_embarquer_pieces_jointes($corps['pieces_jointes']); |
|
| 126 | - } |
|
| 127 | - } else { |
|
| 128 | - $texte = $corps; |
|
| 129 | - } |
|
| 130 | - |
|
| 131 | - if (!$from) { |
|
| 132 | - $from = $email_envoi; |
|
| 133 | - } |
|
| 134 | - |
|
| 135 | - // ceci est la RegExp NO_REAL_NAME faisant hurler SpamAssassin |
|
| 136 | - if (preg_match('/^["\s]*\<?\S+\@\S+\>?\s*$/', $from)) { |
|
| 137 | - $from .= ' (' . str_replace(')', '', translitteration(str_replace('@', ' at ', $from))) . ')'; |
|
| 138 | - } |
|
| 139 | - |
|
| 140 | - // nettoyer les é ’, &emdash; etc... |
|
| 141 | - // les 'cliquer ici' etc sont a eviter; voir: |
|
| 142 | - // http://mta.org.ua/spamassassin-2.55/stuff/wiki.CustomRulesets/20050914/rules/french_rules.cf |
|
| 143 | - $texte = nettoyer_caracteres_mail($texte); |
|
| 144 | - $sujet = nettoyer_caracteres_mail($sujet); |
|
| 145 | - |
|
| 146 | - // encoder le sujet si possible selon la RFC |
|
| 147 | - if (init_mb_string()) { |
|
| 148 | - # un bug de mb_string casse mb_encode_mimeheader si l'encoding interne |
|
| 149 | - # est UTF-8 et le charset iso-8859-1 (constate php5-mac ; php4.3-debian) |
|
| 150 | - $charset = $GLOBALS['meta']['charset']; |
|
| 151 | - mb_internal_encoding($charset); |
|
| 152 | - $sujet = mb_encode_mimeheader($sujet, $charset, 'Q', "\n"); |
|
| 153 | - mb_internal_encoding('utf-8'); |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - $headers = $headers ?? ''; |
|
| 157 | - if (function_exists('wordwrap') && (preg_match(',multipart/mixed,', $headers) == 0)) { |
|
| 158 | - $texte = wordwrap($texte); |
|
| 159 | - } |
|
| 160 | - |
|
| 161 | - [$headers, $texte] = mail_normaliser_headers($headers, $from, $destinataire, $texte, $parts); |
|
| 162 | - |
|
| 163 | - if (_OS_SERVEUR == 'windows') { |
|
| 164 | - $texte = preg_replace("@\r*\n@", "\r\n", $texte); |
|
| 165 | - $headers = preg_replace("@\r*\n@", "\r\n", $headers); |
|
| 166 | - $sujet = preg_replace("@\r*\n@", "\r\n", $sujet); |
|
| 167 | - } |
|
| 168 | - |
|
| 169 | - spip_log("mail $destinataire\n$sujet\n$headers", 'mails'); |
|
| 170 | - // mode TEST : forcer l'email |
|
| 171 | - if (defined('_TEST_EMAIL_DEST')) { |
|
| 172 | - if (!_TEST_EMAIL_DEST) { |
|
| 173 | - return false; |
|
| 174 | - } else { |
|
| 175 | - $texte = "Dest : $destinataire\r\n" . $texte; |
|
| 176 | - $destinataire = _TEST_EMAIL_DEST; |
|
| 177 | - } |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - return @mail($destinataire, $sujet, $texte, $headers); |
|
| 100 | + if (!email_valide($destinataire)) { |
|
| 101 | + return false; |
|
| 102 | + } |
|
| 103 | + if ($destinataire == _T('info_mail_fournisseur')) { |
|
| 104 | + return false; |
|
| 105 | + } // tres fort |
|
| 106 | + |
|
| 107 | + // Fournir si possible un Message-Id: conforme au RFC1036, |
|
| 108 | + // sinon SpamAssassin denoncera un MSGID_FROM_MTA_HEADER |
|
| 109 | + |
|
| 110 | + $email_envoi = $GLOBALS['meta']['email_envoi']; |
|
| 111 | + if (!email_valide($email_envoi)) { |
|
| 112 | + spip_log('Meta email_envoi invalide. Le mail sera probablement vu comme spam.'); |
|
| 113 | + $email_envoi = $destinataire; |
|
| 114 | + } |
|
| 115 | + |
|
| 116 | + $parts = ''; |
|
| 117 | + if (is_array($corps)) { |
|
| 118 | + $texte = $corps['texte']; |
|
| 119 | + $from = ($corps['from'] ?? $from); |
|
| 120 | + $headers = ($corps['headers'] ?? $headers); |
|
| 121 | + if (is_array($headers)) { |
|
| 122 | + $headers = implode("\n", $headers); |
|
| 123 | + } |
|
| 124 | + if (isset($corps['pieces_jointes']) and function_exists('mail_embarquer_pieces_jointes')) { |
|
| 125 | + $parts = mail_embarquer_pieces_jointes($corps['pieces_jointes']); |
|
| 126 | + } |
|
| 127 | + } else { |
|
| 128 | + $texte = $corps; |
|
| 129 | + } |
|
| 130 | + |
|
| 131 | + if (!$from) { |
|
| 132 | + $from = $email_envoi; |
|
| 133 | + } |
|
| 134 | + |
|
| 135 | + // ceci est la RegExp NO_REAL_NAME faisant hurler SpamAssassin |
|
| 136 | + if (preg_match('/^["\s]*\<?\S+\@\S+\>?\s*$/', $from)) { |
|
| 137 | + $from .= ' (' . str_replace(')', '', translitteration(str_replace('@', ' at ', $from))) . ')'; |
|
| 138 | + } |
|
| 139 | + |
|
| 140 | + // nettoyer les é ’, &emdash; etc... |
|
| 141 | + // les 'cliquer ici' etc sont a eviter; voir: |
|
| 142 | + // http://mta.org.ua/spamassassin-2.55/stuff/wiki.CustomRulesets/20050914/rules/french_rules.cf |
|
| 143 | + $texte = nettoyer_caracteres_mail($texte); |
|
| 144 | + $sujet = nettoyer_caracteres_mail($sujet); |
|
| 145 | + |
|
| 146 | + // encoder le sujet si possible selon la RFC |
|
| 147 | + if (init_mb_string()) { |
|
| 148 | + # un bug de mb_string casse mb_encode_mimeheader si l'encoding interne |
|
| 149 | + # est UTF-8 et le charset iso-8859-1 (constate php5-mac ; php4.3-debian) |
|
| 150 | + $charset = $GLOBALS['meta']['charset']; |
|
| 151 | + mb_internal_encoding($charset); |
|
| 152 | + $sujet = mb_encode_mimeheader($sujet, $charset, 'Q', "\n"); |
|
| 153 | + mb_internal_encoding('utf-8'); |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + $headers = $headers ?? ''; |
|
| 157 | + if (function_exists('wordwrap') && (preg_match(',multipart/mixed,', $headers) == 0)) { |
|
| 158 | + $texte = wordwrap($texte); |
|
| 159 | + } |
|
| 160 | + |
|
| 161 | + [$headers, $texte] = mail_normaliser_headers($headers, $from, $destinataire, $texte, $parts); |
|
| 162 | + |
|
| 163 | + if (_OS_SERVEUR == 'windows') { |
|
| 164 | + $texte = preg_replace("@\r*\n@", "\r\n", $texte); |
|
| 165 | + $headers = preg_replace("@\r*\n@", "\r\n", $headers); |
|
| 166 | + $sujet = preg_replace("@\r*\n@", "\r\n", $sujet); |
|
| 167 | + } |
|
| 168 | + |
|
| 169 | + spip_log("mail $destinataire\n$sujet\n$headers", 'mails'); |
|
| 170 | + // mode TEST : forcer l'email |
|
| 171 | + if (defined('_TEST_EMAIL_DEST')) { |
|
| 172 | + if (!_TEST_EMAIL_DEST) { |
|
| 173 | + return false; |
|
| 174 | + } else { |
|
| 175 | + $texte = "Dest : $destinataire\r\n" . $texte; |
|
| 176 | + $destinataire = _TEST_EMAIL_DEST; |
|
| 177 | + } |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + return @mail($destinataire, $sujet, $texte, $headers); |
|
| 181 | 181 | } |
| 182 | 182 | |
| 183 | 183 | /** |
@@ -191,58 +191,58 @@ discard block |
||
| 191 | 191 | * @return array |
| 192 | 192 | */ |
| 193 | 193 | function mail_normaliser_headers($headers, $from, $to, $texte, $parts = '') { |
| 194 | - $charset = $GLOBALS['meta']['charset']; |
|
| 195 | - |
|
| 196 | - // Ajouter le Content-Type et consort s'il n'y est pas deja |
|
| 197 | - if (strpos($headers, 'Content-Type: ') === false) { |
|
| 198 | - $type = |
|
| 199 | - "Content-Type: text/plain;charset=\"$charset\";\n" . |
|
| 200 | - "Content-Transfer-Encoding: 8bit\n"; |
|
| 201 | - } else { |
|
| 202 | - $type = ''; |
|
| 203 | - } |
|
| 204 | - |
|
| 205 | - // calculer un identifiant unique |
|
| 206 | - // Marie Toto <[email protected]> => @toto.com |
|
| 207 | - if (preg_match('/@[^\s>]+/', $from, $domain)) { |
|
| 208 | - $domain = $domain[0]; |
|
| 209 | - } |
|
| 210 | - else { |
|
| 211 | - $domain = '@unknown-' . md5($from) . '.org'; |
|
| 212 | - } |
|
| 213 | - $uniq = random_int(0, mt_getrandmax()) . '_' . md5($to . $texte) . $domain; |
|
| 214 | - |
|
| 215 | - // Si multi-part, s'en servir comme borne ... |
|
| 216 | - if ($parts) { |
|
| 217 | - $texte = "--$uniq\n$type\n" . $texte . "\n"; |
|
| 218 | - foreach ($parts as $part) { |
|
| 219 | - $n = strlen($part[1]) . ($part[0] ? "\n" : ''); |
|
| 220 | - $e = join("\n", $part[0]); |
|
| 221 | - $texte .= "\n--$uniq\nContent-Length: $n$e\n\n" . $part[1]; |
|
| 222 | - } |
|
| 223 | - $texte .= "\n\n--$uniq--\n"; |
|
| 224 | - // Si boundary n'est pas entre guillemets, |
|
| 225 | - // elle est comprise mais le charset est ignoree ! |
|
| 226 | - $type = "Content-Type: multipart/mixed; boundary=\"$uniq\"\n"; |
|
| 227 | - } |
|
| 228 | - |
|
| 229 | - // .. et s'en servir pour plaire a SpamAssassin |
|
| 230 | - |
|
| 231 | - $mid = 'Message-Id: <' . $uniq . '>'; |
|
| 232 | - |
|
| 233 | - // indispensable pour les sites qui collent d'office From: serveur-http |
|
| 234 | - // sauf si deja mis par l'envoyeur |
|
| 235 | - $rep = (strpos($headers, 'Reply-To:') !== false) ? '' : "Reply-To: $from\n"; |
|
| 236 | - |
|
| 237 | - // Nettoyer les en-tetes envoyees |
|
| 238 | - // Ajouter le \n final |
|
| 239 | - if (strlen($headers = trim($headers))) { |
|
| 240 | - $headers .= "\n"; |
|
| 241 | - } |
|
| 242 | - |
|
| 243 | - // Et mentionner l'indeboulonable nomenclature ratee |
|
| 244 | - |
|
| 245 | - $headers .= "From: $from\n$type$rep$mid\nMIME-Version: 1.0\n"; |
|
| 246 | - |
|
| 247 | - return [$headers, $texte]; |
|
| 194 | + $charset = $GLOBALS['meta']['charset']; |
|
| 195 | + |
|
| 196 | + // Ajouter le Content-Type et consort s'il n'y est pas deja |
|
| 197 | + if (strpos($headers, 'Content-Type: ') === false) { |
|
| 198 | + $type = |
|
| 199 | + "Content-Type: text/plain;charset=\"$charset\";\n" . |
|
| 200 | + "Content-Transfer-Encoding: 8bit\n"; |
|
| 201 | + } else { |
|
| 202 | + $type = ''; |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | + // calculer un identifiant unique |
|
| 206 | + // Marie Toto <[email protected]> => @toto.com |
|
| 207 | + if (preg_match('/@[^\s>]+/', $from, $domain)) { |
|
| 208 | + $domain = $domain[0]; |
|
| 209 | + } |
|
| 210 | + else { |
|
| 211 | + $domain = '@unknown-' . md5($from) . '.org'; |
|
| 212 | + } |
|
| 213 | + $uniq = random_int(0, mt_getrandmax()) . '_' . md5($to . $texte) . $domain; |
|
| 214 | + |
|
| 215 | + // Si multi-part, s'en servir comme borne ... |
|
| 216 | + if ($parts) { |
|
| 217 | + $texte = "--$uniq\n$type\n" . $texte . "\n"; |
|
| 218 | + foreach ($parts as $part) { |
|
| 219 | + $n = strlen($part[1]) . ($part[0] ? "\n" : ''); |
|
| 220 | + $e = join("\n", $part[0]); |
|
| 221 | + $texte .= "\n--$uniq\nContent-Length: $n$e\n\n" . $part[1]; |
|
| 222 | + } |
|
| 223 | + $texte .= "\n\n--$uniq--\n"; |
|
| 224 | + // Si boundary n'est pas entre guillemets, |
|
| 225 | + // elle est comprise mais le charset est ignoree ! |
|
| 226 | + $type = "Content-Type: multipart/mixed; boundary=\"$uniq\"\n"; |
|
| 227 | + } |
|
| 228 | + |
|
| 229 | + // .. et s'en servir pour plaire a SpamAssassin |
|
| 230 | + |
|
| 231 | + $mid = 'Message-Id: <' . $uniq . '>'; |
|
| 232 | + |
|
| 233 | + // indispensable pour les sites qui collent d'office From: serveur-http |
|
| 234 | + // sauf si deja mis par l'envoyeur |
|
| 235 | + $rep = (strpos($headers, 'Reply-To:') !== false) ? '' : "Reply-To: $from\n"; |
|
| 236 | + |
|
| 237 | + // Nettoyer les en-tetes envoyees |
|
| 238 | + // Ajouter le \n final |
|
| 239 | + if (strlen($headers = trim($headers))) { |
|
| 240 | + $headers .= "\n"; |
|
| 241 | + } |
|
| 242 | + |
|
| 243 | + // Et mentionner l'indeboulonable nomenclature ratee |
|
| 244 | + |
|
| 245 | + $headers .= "From: $from\n$type$rep$mid\nMIME-Version: 1.0\n"; |
|
| 246 | + |
|
| 247 | + return [$headers, $texte]; |
|
| 248 | 248 | } |
@@ -19,78 +19,78 @@ |
||
| 19 | 19 | * @link https://www.php.net/manual/fr/book.sodium.php |
| 20 | 20 | */ |
| 21 | 21 | class Chiffrement { |
| 22 | - /** Chiffre un message en utilisant une clé ou un mot de passe */ |
|
| 23 | - public static function chiffrer( |
|
| 24 | - string $message, |
|
| 25 | - #[\SensitiveParameter] |
|
| 26 | - string $key |
|
| 27 | - ): ?string { |
|
| 28 | - // create a random salt for key derivation |
|
| 29 | - $salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES); |
|
| 30 | - $key = self::deriveKeyFromPassword($key, $salt); |
|
| 31 | - $nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 32 | - $padded_message = sodium_pad($message, 16); |
|
| 33 | - $encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key); |
|
| 34 | - $encoded = base64_encode($salt . $nonce . $encrypted); |
|
| 35 | - sodium_memzero($key); |
|
| 36 | - sodium_memzero($nonce); |
|
| 37 | - sodium_memzero($salt); |
|
| 38 | - #spip_log("chiffrer($message)=$encoded", 'chiffrer' . _LOG_DEBUG); |
|
| 39 | - return $encoded; |
|
| 40 | - } |
|
| 22 | + /** Chiffre un message en utilisant une clé ou un mot de passe */ |
|
| 23 | + public static function chiffrer( |
|
| 24 | + string $message, |
|
| 25 | + #[\SensitiveParameter] |
|
| 26 | + string $key |
|
| 27 | + ): ?string { |
|
| 28 | + // create a random salt for key derivation |
|
| 29 | + $salt = random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES); |
|
| 30 | + $key = self::deriveKeyFromPassword($key, $salt); |
|
| 31 | + $nonce = random_bytes(\SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 32 | + $padded_message = sodium_pad($message, 16); |
|
| 33 | + $encrypted = sodium_crypto_secretbox($padded_message, $nonce, $key); |
|
| 34 | + $encoded = base64_encode($salt . $nonce . $encrypted); |
|
| 35 | + sodium_memzero($key); |
|
| 36 | + sodium_memzero($nonce); |
|
| 37 | + sodium_memzero($salt); |
|
| 38 | + #spip_log("chiffrer($message)=$encoded", 'chiffrer' . _LOG_DEBUG); |
|
| 39 | + return $encoded; |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - /** Déchiffre un message en utilisant une clé ou un mot de passe */ |
|
| 43 | - public static function dechiffrer( |
|
| 44 | - string $encoded, |
|
| 45 | - #[\SensitiveParameter] |
|
| 46 | - string $key |
|
| 47 | - ): ?string { |
|
| 48 | - $decoded = base64_decode($encoded); |
|
| 49 | - $salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES); |
|
| 50 | - $nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 51 | - $encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 52 | - $key = self::deriveKeyFromPassword($key, $salt); |
|
| 53 | - $padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key); |
|
| 54 | - sodium_memzero($key); |
|
| 55 | - sodium_memzero($nonce); |
|
| 56 | - sodium_memzero($salt); |
|
| 57 | - if ($padded_message === false) { |
|
| 58 | - spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG); |
|
| 59 | - return null; |
|
| 60 | - } |
|
| 61 | - $message = sodium_unpad($padded_message, 16); |
|
| 62 | - #spip_log("dechiffrer($encoded)=$message", 'chiffrer' . _LOG_DEBUG); |
|
| 63 | - return $message; |
|
| 64 | - } |
|
| 42 | + /** Déchiffre un message en utilisant une clé ou un mot de passe */ |
|
| 43 | + public static function dechiffrer( |
|
| 44 | + string $encoded, |
|
| 45 | + #[\SensitiveParameter] |
|
| 46 | + string $key |
|
| 47 | + ): ?string { |
|
| 48 | + $decoded = base64_decode($encoded); |
|
| 49 | + $salt = substr($decoded, 0, \SODIUM_CRYPTO_PWHASH_SALTBYTES); |
|
| 50 | + $nonce = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES, \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 51 | + $encrypted = substr($decoded, \SODIUM_CRYPTO_PWHASH_SALTBYTES + \SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); |
|
| 52 | + $key = self::deriveKeyFromPassword($key, $salt); |
|
| 53 | + $padded_message = sodium_crypto_secretbox_open($encrypted, $nonce, $key); |
|
| 54 | + sodium_memzero($key); |
|
| 55 | + sodium_memzero($nonce); |
|
| 56 | + sodium_memzero($salt); |
|
| 57 | + if ($padded_message === false) { |
|
| 58 | + spip_log("dechiffrer() chiffre corrompu `$encoded`", 'chiffrer' . _LOG_DEBUG); |
|
| 59 | + return null; |
|
| 60 | + } |
|
| 61 | + $message = sodium_unpad($padded_message, 16); |
|
| 62 | + #spip_log("dechiffrer($encoded)=$message", 'chiffrer' . _LOG_DEBUG); |
|
| 63 | + return $message; |
|
| 64 | + } |
|
| 65 | 65 | |
| 66 | - /** Génère une clé de la taille attendue pour le chiffrement */ |
|
| 67 | - public static function keygen(): string { |
|
| 68 | - return sodium_crypto_secretbox_keygen(); |
|
| 69 | - } |
|
| 66 | + /** Génère une clé de la taille attendue pour le chiffrement */ |
|
| 67 | + public static function keygen(): string { |
|
| 68 | + return sodium_crypto_secretbox_keygen(); |
|
| 69 | + } |
|
| 70 | 70 | |
| 71 | - /** |
|
| 72 | - * Retourne une clé de la taille attendue pour le chiffrement |
|
| 73 | - * |
|
| 74 | - * Notamment si on utilise un mot de passe comme clé, il faut le hacher |
|
| 75 | - * pour servir de clé à la taille correspondante. |
|
| 76 | - */ |
|
| 77 | - private static function deriveKeyFromPassword( |
|
| 78 | - #[\SensitiveParameter] |
|
| 79 | - string $password, |
|
| 80 | - string $salt |
|
| 81 | - ): string { |
|
| 82 | - if (strlen($password) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { |
|
| 83 | - return $password; |
|
| 84 | - } |
|
| 85 | - $key = sodium_crypto_pwhash( |
|
| 86 | - \SODIUM_CRYPTO_SECRETBOX_KEYBYTES, |
|
| 87 | - $password, |
|
| 88 | - $salt, |
|
| 89 | - \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, |
|
| 90 | - \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE |
|
| 91 | - ); |
|
| 92 | - sodium_memzero($password); |
|
| 71 | + /** |
|
| 72 | + * Retourne une clé de la taille attendue pour le chiffrement |
|
| 73 | + * |
|
| 74 | + * Notamment si on utilise un mot de passe comme clé, il faut le hacher |
|
| 75 | + * pour servir de clé à la taille correspondante. |
|
| 76 | + */ |
|
| 77 | + private static function deriveKeyFromPassword( |
|
| 78 | + #[\SensitiveParameter] |
|
| 79 | + string $password, |
|
| 80 | + string $salt |
|
| 81 | + ): string { |
|
| 82 | + if (strlen($password) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { |
|
| 83 | + return $password; |
|
| 84 | + } |
|
| 85 | + $key = sodium_crypto_pwhash( |
|
| 86 | + \SODIUM_CRYPTO_SECRETBOX_KEYBYTES, |
|
| 87 | + $password, |
|
| 88 | + $salt, |
|
| 89 | + \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, |
|
| 90 | + \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE |
|
| 91 | + ); |
|
| 92 | + sodium_memzero($password); |
|
| 93 | 93 | |
| 94 | - return $key; |
|
| 95 | - } |
|
| 94 | + return $key; |
|
| 95 | + } |
|
| 96 | 96 | } |
@@ -14,48 +14,48 @@ |
||
| 14 | 14 | |
| 15 | 15 | /** Conteneur de clés (chiffrement, authentification) */ |
| 16 | 16 | class Cles implements \Countable /* , ContainerInterface */ { |
| 17 | - private array $keys; |
|
| 18 | - public function __construct(array $keys) { |
|
| 19 | - $this->keys = $keys; |
|
| 20 | - } |
|
| 21 | - |
|
| 22 | - public function has(string $name): bool { |
|
| 23 | - return array_key_exists($name, $this->keys); |
|
| 24 | - } |
|
| 25 | - |
|
| 26 | - public function get(string $name): ?string { |
|
| 27 | - return $this->keys[$name] ?? null; |
|
| 28 | - } |
|
| 29 | - |
|
| 30 | - public function generate(string $name): string { |
|
| 31 | - $key = Chiffrement::keygen(); |
|
| 32 | - $this->keys[$name] = $key; |
|
| 33 | - spip_log("Création de la cle $name", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 34 | - return $key; |
|
| 35 | - } |
|
| 36 | - |
|
| 37 | - public function set( |
|
| 38 | - string $name, |
|
| 39 | - #[\SensitiveParameter] |
|
| 40 | - string $key |
|
| 41 | - ): void { |
|
| 42 | - $this->keys[$name] = $key; |
|
| 43 | - } |
|
| 44 | - |
|
| 45 | - public function delete(string $name): bool { |
|
| 46 | - if (isset($this->keys[$name])) { |
|
| 47 | - unset($this->keys[$name]); |
|
| 48 | - return true; |
|
| 49 | - }; |
|
| 50 | - return false; |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - public function count(): int { |
|
| 54 | - return count($this->keys); |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - public function toJson(): string { |
|
| 58 | - $json = array_map('base64_encode', $this->keys); |
|
| 59 | - return \json_encode($json); |
|
| 60 | - } |
|
| 17 | + private array $keys; |
|
| 18 | + public function __construct(array $keys) { |
|
| 19 | + $this->keys = $keys; |
|
| 20 | + } |
|
| 21 | + |
|
| 22 | + public function has(string $name): bool { |
|
| 23 | + return array_key_exists($name, $this->keys); |
|
| 24 | + } |
|
| 25 | + |
|
| 26 | + public function get(string $name): ?string { |
|
| 27 | + return $this->keys[$name] ?? null; |
|
| 28 | + } |
|
| 29 | + |
|
| 30 | + public function generate(string $name): string { |
|
| 31 | + $key = Chiffrement::keygen(); |
|
| 32 | + $this->keys[$name] = $key; |
|
| 33 | + spip_log("Création de la cle $name", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 34 | + return $key; |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + public function set( |
|
| 38 | + string $name, |
|
| 39 | + #[\SensitiveParameter] |
|
| 40 | + string $key |
|
| 41 | + ): void { |
|
| 42 | + $this->keys[$name] = $key; |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + public function delete(string $name): bool { |
|
| 46 | + if (isset($this->keys[$name])) { |
|
| 47 | + unset($this->keys[$name]); |
|
| 48 | + return true; |
|
| 49 | + }; |
|
| 50 | + return false; |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + public function count(): int { |
|
| 54 | + return count($this->keys); |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + public function toJson(): string { |
|
| 58 | + $json = array_map('base64_encode', $this->keys); |
|
| 59 | + return \json_encode($json); |
|
| 60 | + } |
|
| 61 | 61 | } |
@@ -17,7 +17,7 @@ discard block |
||
| 17 | 17 | **/ |
| 18 | 18 | |
| 19 | 19 | if (!defined('_ECRIRE_INC_VERSION')) { |
| 20 | - return; |
|
| 20 | + return; |
|
| 21 | 21 | } |
| 22 | 22 | include_spip('base/abstract_sql'); |
| 23 | 23 | |
@@ -59,56 +59,56 @@ discard block |
||
| 59 | 59 | * Retour des traitements. |
| 60 | 60 | **/ |
| 61 | 61 | function formulaires_editer_objet_traiter( |
| 62 | - $type, |
|
| 63 | - $id = 'new', |
|
| 64 | - $id_parent = 0, |
|
| 65 | - $lier_trad = 0, |
|
| 66 | - $retour = '', |
|
| 67 | - $config_fonc = 'articles_edit_config', |
|
| 68 | - $row = [], |
|
| 69 | - $hidden = '' |
|
| 62 | + $type, |
|
| 63 | + $id = 'new', |
|
| 64 | + $id_parent = 0, |
|
| 65 | + $lier_trad = 0, |
|
| 66 | + $retour = '', |
|
| 67 | + $config_fonc = 'articles_edit_config', |
|
| 68 | + $row = [], |
|
| 69 | + $hidden = '' |
|
| 70 | 70 | ) { |
| 71 | 71 | |
| 72 | - $res = []; |
|
| 73 | - // eviter la redirection forcee par l'action... |
|
| 74 | - set_request('redirect'); |
|
| 75 | - if ($action_editer = charger_fonction("editer_$type", 'action', true)) { |
|
| 76 | - [$id, $err] = $action_editer($id); |
|
| 77 | - } else { |
|
| 78 | - $action_editer = charger_fonction('editer_objet', 'action'); |
|
| 79 | - [$id, $err] = $action_editer($id, $type); |
|
| 80 | - } |
|
| 81 | - $id_table_objet = id_table_objet($type); |
|
| 82 | - $res[$id_table_objet] = $id; |
|
| 83 | - if ($err or !$id) { |
|
| 84 | - $res['message_erreur'] = ($err ?: _T('erreur')); |
|
| 85 | - } else { |
|
| 86 | - // Un lien de trad a prendre en compte |
|
| 87 | - if ($lier_trad) { |
|
| 88 | - // referencer la traduction |
|
| 89 | - $referencer_traduction = charger_fonction('referencer_traduction', 'action'); |
|
| 90 | - $referencer_traduction($type, $id, $lier_trad); |
|
| 91 | - // actions de recopie de champs / liens sur le nouvel objet créé |
|
| 92 | - $completer_traduction = charger_fonction('completer_traduction', 'inc'); |
|
| 93 | - $err = $completer_traduction($type, $id, $lier_trad); |
|
| 94 | - if ($err) { |
|
| 95 | - $res['message_erreur'] = $err; |
|
| 96 | - return $res; |
|
| 97 | - } |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - $res['message_ok'] = _T('info_modification_enregistree'); |
|
| 101 | - if ($retour) { |
|
| 102 | - if (strncmp($retour, 'javascript:', 11) == 0) { |
|
| 103 | - $res['message_ok'] .= '<script type="text/javascript">/*<![CDATA[*/' . substr($retour, 11) . '/*]]>*/</script>'; |
|
| 104 | - $res['editable'] = true; |
|
| 105 | - } else { |
|
| 106 | - $res['redirect'] = parametre_url($retour, $id_table_objet, $id); |
|
| 107 | - } |
|
| 108 | - } |
|
| 109 | - } |
|
| 110 | - |
|
| 111 | - return $res; |
|
| 72 | + $res = []; |
|
| 73 | + // eviter la redirection forcee par l'action... |
|
| 74 | + set_request('redirect'); |
|
| 75 | + if ($action_editer = charger_fonction("editer_$type", 'action', true)) { |
|
| 76 | + [$id, $err] = $action_editer($id); |
|
| 77 | + } else { |
|
| 78 | + $action_editer = charger_fonction('editer_objet', 'action'); |
|
| 79 | + [$id, $err] = $action_editer($id, $type); |
|
| 80 | + } |
|
| 81 | + $id_table_objet = id_table_objet($type); |
|
| 82 | + $res[$id_table_objet] = $id; |
|
| 83 | + if ($err or !$id) { |
|
| 84 | + $res['message_erreur'] = ($err ?: _T('erreur')); |
|
| 85 | + } else { |
|
| 86 | + // Un lien de trad a prendre en compte |
|
| 87 | + if ($lier_trad) { |
|
| 88 | + // referencer la traduction |
|
| 89 | + $referencer_traduction = charger_fonction('referencer_traduction', 'action'); |
|
| 90 | + $referencer_traduction($type, $id, $lier_trad); |
|
| 91 | + // actions de recopie de champs / liens sur le nouvel objet créé |
|
| 92 | + $completer_traduction = charger_fonction('completer_traduction', 'inc'); |
|
| 93 | + $err = $completer_traduction($type, $id, $lier_trad); |
|
| 94 | + if ($err) { |
|
| 95 | + $res['message_erreur'] = $err; |
|
| 96 | + return $res; |
|
| 97 | + } |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + $res['message_ok'] = _T('info_modification_enregistree'); |
|
| 101 | + if ($retour) { |
|
| 102 | + if (strncmp($retour, 'javascript:', 11) == 0) { |
|
| 103 | + $res['message_ok'] .= '<script type="text/javascript">/*<![CDATA[*/' . substr($retour, 11) . '/*]]>*/</script>'; |
|
| 104 | + $res['editable'] = true; |
|
| 105 | + } else { |
|
| 106 | + $res['redirect'] = parametre_url($retour, $id_table_objet, $id); |
|
| 107 | + } |
|
| 108 | + } |
|
| 109 | + } |
|
| 110 | + |
|
| 111 | + return $res; |
|
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | /** |
@@ -132,29 +132,29 @@ discard block |
||
| 132 | 132 | * Tableau des erreurs |
| 133 | 133 | **/ |
| 134 | 134 | function formulaires_editer_objet_verifier($type, $id = 'new', $oblis = []) { |
| 135 | - $erreurs = []; |
|
| 136 | - if (intval($id)) { |
|
| 137 | - $conflits = controler_contenu($type, $id); |
|
| 138 | - if ($conflits and is_countable($conflits) ? count($conflits) : 0) { |
|
| 139 | - foreach ($conflits as $champ => $conflit) { |
|
| 140 | - if (!isset($erreurs[$champ])) { |
|
| 141 | - $erreurs[$champ] = ''; |
|
| 142 | - } |
|
| 143 | - $erreurs[$champ] .= _T('alerte_modif_info_concourante') . "<br /><textarea readonly='readonly' class='forml'>" . entites_html($conflit['base']) . '</textarea>'; |
|
| 144 | - } |
|
| 145 | - } |
|
| 146 | - } |
|
| 147 | - foreach ($oblis as $obli) { |
|
| 148 | - $value = _request($obli); |
|
| 149 | - if (is_null($value) or !(is_array($value) ? count($value) : strlen($value))) { |
|
| 150 | - if (!isset($erreurs[$obli])) { |
|
| 151 | - $erreurs[$obli] = ''; |
|
| 152 | - } |
|
| 153 | - $erreurs[$obli] .= _T('info_obligatoire'); |
|
| 154 | - } |
|
| 155 | - } |
|
| 156 | - |
|
| 157 | - return $erreurs; |
|
| 135 | + $erreurs = []; |
|
| 136 | + if (intval($id)) { |
|
| 137 | + $conflits = controler_contenu($type, $id); |
|
| 138 | + if ($conflits and is_countable($conflits) ? count($conflits) : 0) { |
|
| 139 | + foreach ($conflits as $champ => $conflit) { |
|
| 140 | + if (!isset($erreurs[$champ])) { |
|
| 141 | + $erreurs[$champ] = ''; |
|
| 142 | + } |
|
| 143 | + $erreurs[$champ] .= _T('alerte_modif_info_concourante') . "<br /><textarea readonly='readonly' class='forml'>" . entites_html($conflit['base']) . '</textarea>'; |
|
| 144 | + } |
|
| 145 | + } |
|
| 146 | + } |
|
| 147 | + foreach ($oblis as $obli) { |
|
| 148 | + $value = _request($obli); |
|
| 149 | + if (is_null($value) or !(is_array($value) ? count($value) : strlen($value))) { |
|
| 150 | + if (!isset($erreurs[$obli])) { |
|
| 151 | + $erreurs[$obli] = ''; |
|
| 152 | + } |
|
| 153 | + $erreurs[$obli] .= _T('info_obligatoire'); |
|
| 154 | + } |
|
| 155 | + } |
|
| 156 | + |
|
| 157 | + return $erreurs; |
|
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | /** |
@@ -199,154 +199,154 @@ discard block |
||
| 199 | 199 | * Environnement du formulaire. |
| 200 | 200 | **/ |
| 201 | 201 | function formulaires_editer_objet_charger( |
| 202 | - $type, |
|
| 203 | - $id = 'new', |
|
| 204 | - $id_parent = 0, |
|
| 205 | - $lier_trad = 0, |
|
| 206 | - $retour = '', |
|
| 207 | - $config_fonc = 'articles_edit_config', |
|
| 208 | - $row = [], |
|
| 209 | - $hidden = '' |
|
| 202 | + $type, |
|
| 203 | + $id = 'new', |
|
| 204 | + $id_parent = 0, |
|
| 205 | + $lier_trad = 0, |
|
| 206 | + $retour = '', |
|
| 207 | + $config_fonc = 'articles_edit_config', |
|
| 208 | + $row = [], |
|
| 209 | + $hidden = '' |
|
| 210 | 210 | ) { |
| 211 | 211 | |
| 212 | - $table_objet = table_objet($type); |
|
| 213 | - $table_objet_sql = table_objet_sql($type); |
|
| 214 | - $id_table_objet = id_table_objet($type); |
|
| 215 | - if (!is_array($row)) { |
|
| 216 | - $row = []; |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - // on accepte pas une fonction de config inconnue si elle vient d'un modele |
|
| 220 | - if ( |
|
| 221 | - $config_fonc |
|
| 222 | - and !in_array($config_fonc, ['articles_edit_config', 'rubriques_edit_config', 'auteurs_edit_config']) |
|
| 223 | - and $config_fonc !== $table_objet . '_edit_config' |
|
| 224 | - ) { |
|
| 225 | - if ( |
|
| 226 | - $args = test_formulaire_inclus_par_modele() |
|
| 227 | - and in_array($config_fonc, $args) |
|
| 228 | - ) { |
|
| 229 | - $config_fonc = ''; |
|
| 230 | - } |
|
| 231 | - } |
|
| 232 | - |
|
| 233 | - $new = !is_numeric($id); |
|
| 234 | - $lang_default = ''; |
|
| 235 | - // Appel direct dans un squelette |
|
| 236 | - if (!$row) { |
|
| 237 | - if (!$new or $lier_trad) { |
|
| 238 | - if ($select = charger_fonction('precharger_' . $type, 'inc', true)) { |
|
| 239 | - $row = $select($id, $id_parent, $lier_trad); |
|
| 240 | - // si on a une fonction precharger, elle pu faire un reglage de langue |
|
| 241 | - $lang_default = (!empty($row['lang']) ? $row['lang'] : null); |
|
| 242 | - } else { |
|
| 243 | - $row = sql_fetsel('*', $table_objet_sql, $id_table_objet . '=' . intval($id)); |
|
| 244 | - } |
|
| 245 | - if (!$new) { |
|
| 246 | - $md5 = controles_md5($row ?: []); |
|
| 247 | - } |
|
| 248 | - } |
|
| 249 | - if (!$row) { |
|
| 250 | - $row = []; |
|
| 251 | - $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 252 | - if ($desc = $trouver_table($table_objet)) { |
|
| 253 | - foreach ($desc['field'] as $k => $v) { |
|
| 254 | - $row[$k] = ''; |
|
| 255 | - } |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - } |
|
| 259 | - |
|
| 260 | - // Gaffe: sans ceci, on ecrase systematiquement l'article d'origine |
|
| 261 | - // (et donc: pas de lien de traduction) |
|
| 262 | - $id = ($new or $lier_trad) |
|
| 263 | - ? 'oui' |
|
| 264 | - : $row[$id_table_objet]; |
|
| 265 | - $row[$id_table_objet] = $id; |
|
| 266 | - |
|
| 267 | - $contexte = $row; |
|
| 268 | - if (is_numeric($id_parent) && strlen($id_parent) && (!isset($contexte['id_parent']) or $new)) { |
|
| 269 | - if (!isset($contexte['id_parent'])) { |
|
| 270 | - unset($contexte['id_rubrique']); |
|
| 271 | - } |
|
| 272 | - $contexte['id_parent'] = $id_parent; |
|
| 273 | - } elseif (!isset($contexte['id_parent'])) { |
|
| 274 | - // id_rubrique dans id_parent si possible |
|
| 275 | - if (isset($contexte['id_rubrique'])) { |
|
| 276 | - $contexte['id_parent'] = $contexte['id_rubrique']; |
|
| 277 | - unset($contexte['id_rubrique']); |
|
| 278 | - } else { |
|
| 279 | - $contexte['id_parent'] = ''; |
|
| 280 | - } |
|
| 281 | - if ( |
|
| 282 | - !$contexte['id_parent'] |
|
| 283 | - and $preselectionner_parent_nouvel_objet = charger_fonction('preselectionner_parent_nouvel_objet', 'inc', true) |
|
| 284 | - ) { |
|
| 285 | - $contexte['id_parent'] = $preselectionner_parent_nouvel_objet($type, $row); |
|
| 286 | - } |
|
| 287 | - } |
|
| 288 | - |
|
| 289 | - $config = []; |
|
| 290 | - if ($config_fonc) { |
|
| 291 | - $contexte['config'] = $config = $config_fonc($contexte); |
|
| 292 | - if (!$lang_default) { |
|
| 293 | - $lang_default = $config['langue'] ?? session_get('lang') ; |
|
| 294 | - } |
|
| 295 | - } |
|
| 296 | - $config = $config + [ |
|
| 297 | - 'lignes' => 0, |
|
| 298 | - 'langue' => '', |
|
| 299 | - ]; |
|
| 300 | - |
|
| 301 | - $att_text = " class='textarea' " |
|
| 302 | - . " rows='" |
|
| 303 | - . ($config['lignes'] + 15) |
|
| 304 | - . "' cols='40'"; |
|
| 305 | - if (isset($contexte['texte'])) { |
|
| 306 | - [$contexte['texte'], $contexte['_texte_trop_long']] = editer_texte_recolle($contexte['texte'], $att_text); |
|
| 307 | - } |
|
| 308 | - |
|
| 309 | - // on veut conserver la langue de l'interface ; |
|
| 310 | - // on passe cette donnee sous un autre nom, au cas ou le squelette |
|
| 311 | - // voudrait l'exploiter |
|
| 312 | - if (isset($contexte['lang'])) { |
|
| 313 | - $contexte['langue'] = $contexte['lang']; |
|
| 314 | - unset($contexte['lang']); |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - $contexte['_hidden'] = "<input type='hidden' name='editer_$type' value='oui' />\n" . |
|
| 318 | - (!$lier_trad ? '' : |
|
| 319 | - ("\n<input type='hidden' name='lier_trad' value='" . |
|
| 320 | - $lier_trad . |
|
| 321 | - "' />" . |
|
| 322 | - "\n<input type='hidden' name='changer_lang' value='" . |
|
| 323 | - $lang_default . |
|
| 324 | - "' />")) |
|
| 325 | - . $hidden |
|
| 326 | - . ($md5 ?? ''); |
|
| 327 | - |
|
| 328 | - // preciser que le formulaire doit passer dans un pipeline |
|
| 329 | - $contexte['_pipeline'] = ['editer_contenu_objet', ['type' => $type, 'id' => $id]]; |
|
| 330 | - |
|
| 331 | - // preciser que le formulaire doit etre securise auteur/action |
|
| 332 | - // n'est plus utile lorsque l'action accepte l'id en argument direct |
|
| 333 | - // on le garde pour compat |
|
| 334 | - $contexte['_action'] = ["editer_$type", $id]; |
|
| 335 | - |
|
| 336 | - // et in fine placer l'autorisation |
|
| 337 | - include_spip('inc/autoriser'); |
|
| 338 | - if (intval($id)) { |
|
| 339 | - if (!autoriser('modifier', $type, intval($id))) { |
|
| 340 | - $contexte['editable'] = ''; |
|
| 341 | - } |
|
| 342 | - } |
|
| 343 | - else { |
|
| 344 | - if (!autoriser('creer', $type, 0, null, ['id_parent' => $id_parent])) { |
|
| 345 | - $contexte['editable'] = ''; |
|
| 346 | - } |
|
| 347 | - } |
|
| 348 | - |
|
| 349 | - return $contexte; |
|
| 212 | + $table_objet = table_objet($type); |
|
| 213 | + $table_objet_sql = table_objet_sql($type); |
|
| 214 | + $id_table_objet = id_table_objet($type); |
|
| 215 | + if (!is_array($row)) { |
|
| 216 | + $row = []; |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + // on accepte pas une fonction de config inconnue si elle vient d'un modele |
|
| 220 | + if ( |
|
| 221 | + $config_fonc |
|
| 222 | + and !in_array($config_fonc, ['articles_edit_config', 'rubriques_edit_config', 'auteurs_edit_config']) |
|
| 223 | + and $config_fonc !== $table_objet . '_edit_config' |
|
| 224 | + ) { |
|
| 225 | + if ( |
|
| 226 | + $args = test_formulaire_inclus_par_modele() |
|
| 227 | + and in_array($config_fonc, $args) |
|
| 228 | + ) { |
|
| 229 | + $config_fonc = ''; |
|
| 230 | + } |
|
| 231 | + } |
|
| 232 | + |
|
| 233 | + $new = !is_numeric($id); |
|
| 234 | + $lang_default = ''; |
|
| 235 | + // Appel direct dans un squelette |
|
| 236 | + if (!$row) { |
|
| 237 | + if (!$new or $lier_trad) { |
|
| 238 | + if ($select = charger_fonction('precharger_' . $type, 'inc', true)) { |
|
| 239 | + $row = $select($id, $id_parent, $lier_trad); |
|
| 240 | + // si on a une fonction precharger, elle pu faire un reglage de langue |
|
| 241 | + $lang_default = (!empty($row['lang']) ? $row['lang'] : null); |
|
| 242 | + } else { |
|
| 243 | + $row = sql_fetsel('*', $table_objet_sql, $id_table_objet . '=' . intval($id)); |
|
| 244 | + } |
|
| 245 | + if (!$new) { |
|
| 246 | + $md5 = controles_md5($row ?: []); |
|
| 247 | + } |
|
| 248 | + } |
|
| 249 | + if (!$row) { |
|
| 250 | + $row = []; |
|
| 251 | + $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 252 | + if ($desc = $trouver_table($table_objet)) { |
|
| 253 | + foreach ($desc['field'] as $k => $v) { |
|
| 254 | + $row[$k] = ''; |
|
| 255 | + } |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + } |
|
| 259 | + |
|
| 260 | + // Gaffe: sans ceci, on ecrase systematiquement l'article d'origine |
|
| 261 | + // (et donc: pas de lien de traduction) |
|
| 262 | + $id = ($new or $lier_trad) |
|
| 263 | + ? 'oui' |
|
| 264 | + : $row[$id_table_objet]; |
|
| 265 | + $row[$id_table_objet] = $id; |
|
| 266 | + |
|
| 267 | + $contexte = $row; |
|
| 268 | + if (is_numeric($id_parent) && strlen($id_parent) && (!isset($contexte['id_parent']) or $new)) { |
|
| 269 | + if (!isset($contexte['id_parent'])) { |
|
| 270 | + unset($contexte['id_rubrique']); |
|
| 271 | + } |
|
| 272 | + $contexte['id_parent'] = $id_parent; |
|
| 273 | + } elseif (!isset($contexte['id_parent'])) { |
|
| 274 | + // id_rubrique dans id_parent si possible |
|
| 275 | + if (isset($contexte['id_rubrique'])) { |
|
| 276 | + $contexte['id_parent'] = $contexte['id_rubrique']; |
|
| 277 | + unset($contexte['id_rubrique']); |
|
| 278 | + } else { |
|
| 279 | + $contexte['id_parent'] = ''; |
|
| 280 | + } |
|
| 281 | + if ( |
|
| 282 | + !$contexte['id_parent'] |
|
| 283 | + and $preselectionner_parent_nouvel_objet = charger_fonction('preselectionner_parent_nouvel_objet', 'inc', true) |
|
| 284 | + ) { |
|
| 285 | + $contexte['id_parent'] = $preselectionner_parent_nouvel_objet($type, $row); |
|
| 286 | + } |
|
| 287 | + } |
|
| 288 | + |
|
| 289 | + $config = []; |
|
| 290 | + if ($config_fonc) { |
|
| 291 | + $contexte['config'] = $config = $config_fonc($contexte); |
|
| 292 | + if (!$lang_default) { |
|
| 293 | + $lang_default = $config['langue'] ?? session_get('lang') ; |
|
| 294 | + } |
|
| 295 | + } |
|
| 296 | + $config = $config + [ |
|
| 297 | + 'lignes' => 0, |
|
| 298 | + 'langue' => '', |
|
| 299 | + ]; |
|
| 300 | + |
|
| 301 | + $att_text = " class='textarea' " |
|
| 302 | + . " rows='" |
|
| 303 | + . ($config['lignes'] + 15) |
|
| 304 | + . "' cols='40'"; |
|
| 305 | + if (isset($contexte['texte'])) { |
|
| 306 | + [$contexte['texte'], $contexte['_texte_trop_long']] = editer_texte_recolle($contexte['texte'], $att_text); |
|
| 307 | + } |
|
| 308 | + |
|
| 309 | + // on veut conserver la langue de l'interface ; |
|
| 310 | + // on passe cette donnee sous un autre nom, au cas ou le squelette |
|
| 311 | + // voudrait l'exploiter |
|
| 312 | + if (isset($contexte['lang'])) { |
|
| 313 | + $contexte['langue'] = $contexte['lang']; |
|
| 314 | + unset($contexte['lang']); |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + $contexte['_hidden'] = "<input type='hidden' name='editer_$type' value='oui' />\n" . |
|
| 318 | + (!$lier_trad ? '' : |
|
| 319 | + ("\n<input type='hidden' name='lier_trad' value='" . |
|
| 320 | + $lier_trad . |
|
| 321 | + "' />" . |
|
| 322 | + "\n<input type='hidden' name='changer_lang' value='" . |
|
| 323 | + $lang_default . |
|
| 324 | + "' />")) |
|
| 325 | + . $hidden |
|
| 326 | + . ($md5 ?? ''); |
|
| 327 | + |
|
| 328 | + // preciser que le formulaire doit passer dans un pipeline |
|
| 329 | + $contexte['_pipeline'] = ['editer_contenu_objet', ['type' => $type, 'id' => $id]]; |
|
| 330 | + |
|
| 331 | + // preciser que le formulaire doit etre securise auteur/action |
|
| 332 | + // n'est plus utile lorsque l'action accepte l'id en argument direct |
|
| 333 | + // on le garde pour compat |
|
| 334 | + $contexte['_action'] = ["editer_$type", $id]; |
|
| 335 | + |
|
| 336 | + // et in fine placer l'autorisation |
|
| 337 | + include_spip('inc/autoriser'); |
|
| 338 | + if (intval($id)) { |
|
| 339 | + if (!autoriser('modifier', $type, intval($id))) { |
|
| 340 | + $contexte['editable'] = ''; |
|
| 341 | + } |
|
| 342 | + } |
|
| 343 | + else { |
|
| 344 | + if (!autoriser('creer', $type, 0, null, ['id_parent' => $id_parent])) { |
|
| 345 | + $contexte['editable'] = ''; |
|
| 346 | + } |
|
| 347 | + } |
|
| 348 | + |
|
| 349 | + return $contexte; |
|
| 350 | 350 | } |
| 351 | 351 | |
| 352 | 352 | /** |
@@ -357,29 +357,29 @@ discard block |
||
| 357 | 357 | * @return array |
| 358 | 358 | */ |
| 359 | 359 | function coupe_trop_long($texte) { |
| 360 | - $aider = charger_fonction('aider', 'inc'); |
|
| 361 | - if (strlen($texte) > 28 * 1024) { |
|
| 362 | - $texte = str_replace("\r\n", "\n", $texte); |
|
| 363 | - $pos = strpos($texte, "\n\n", 28 * 1024); // coupe para > 28 ko |
|
| 364 | - if ($pos > 0 and $pos < 32 * 1024) { |
|
| 365 | - $debut = substr($texte, 0, $pos) . "\n\n<!--SPIP-->\n"; |
|
| 366 | - $suite = substr($texte, $pos + 2); |
|
| 367 | - } else { |
|
| 368 | - $pos = strpos($texte, ' ', 28 * 1024); // sinon coupe espace |
|
| 369 | - if (!($pos > 0 and $pos < 32 * 1024)) { |
|
| 370 | - $pos = 28 * 1024; // au pire (pas d'espace trouv'e) |
|
| 371 | - $decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere |
|
| 372 | - } else { |
|
| 373 | - $decalage = 1; |
|
| 374 | - } |
|
| 375 | - $debut = substr($texte, 0, $pos + $decalage); // Il faut conserver l'espace s'il y en a un |
|
| 376 | - $suite = substr($texte, $pos + $decalage); |
|
| 377 | - } |
|
| 378 | - |
|
| 379 | - return ([$debut, $suite]); |
|
| 380 | - } else { |
|
| 381 | - return ([$texte, '']); |
|
| 382 | - } |
|
| 360 | + $aider = charger_fonction('aider', 'inc'); |
|
| 361 | + if (strlen($texte) > 28 * 1024) { |
|
| 362 | + $texte = str_replace("\r\n", "\n", $texte); |
|
| 363 | + $pos = strpos($texte, "\n\n", 28 * 1024); // coupe para > 28 ko |
|
| 364 | + if ($pos > 0 and $pos < 32 * 1024) { |
|
| 365 | + $debut = substr($texte, 0, $pos) . "\n\n<!--SPIP-->\n"; |
|
| 366 | + $suite = substr($texte, $pos + 2); |
|
| 367 | + } else { |
|
| 368 | + $pos = strpos($texte, ' ', 28 * 1024); // sinon coupe espace |
|
| 369 | + if (!($pos > 0 and $pos < 32 * 1024)) { |
|
| 370 | + $pos = 28 * 1024; // au pire (pas d'espace trouv'e) |
|
| 371 | + $decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere |
|
| 372 | + } else { |
|
| 373 | + $decalage = 1; |
|
| 374 | + } |
|
| 375 | + $debut = substr($texte, 0, $pos + $decalage); // Il faut conserver l'espace s'il y en a un |
|
| 376 | + $suite = substr($texte, $pos + $decalage); |
|
| 377 | + } |
|
| 378 | + |
|
| 379 | + return ([$debut, $suite]); |
|
| 380 | + } else { |
|
| 381 | + return ([$texte, '']); |
|
| 382 | + } |
|
| 383 | 383 | } |
| 384 | 384 | |
| 385 | 385 | /** |
@@ -390,25 +390,25 @@ discard block |
||
| 390 | 390 | * @return array |
| 391 | 391 | */ |
| 392 | 392 | function editer_texte_recolle($texte, $att_text) { |
| 393 | - if ( |
|
| 394 | - (strlen($texte) < 29 * 1024) |
|
| 395 | - or (include_spip('inc/layer') and ($GLOBALS['browser_name'] != 'MSIE')) |
|
| 396 | - ) { |
|
| 397 | - return [$texte, '']; |
|
| 398 | - } |
|
| 399 | - |
|
| 400 | - include_spip('inc/barre'); |
|
| 401 | - $textes_supplement = "<br /><span style='color: red'>" . _T('info_texte_long') . "</span>\n"; |
|
| 402 | - $nombre = 0; |
|
| 403 | - |
|
| 404 | - while (strlen($texte) > 29 * 1024) { |
|
| 405 | - $nombre++; |
|
| 406 | - [$texte1, $texte] = coupe_trop_long($texte); |
|
| 407 | - $textes_supplement .= '<br />' . |
|
| 408 | - "<textarea id='texte$nombre' name='texte_plus[$nombre]'$att_text>$texte1</textarea>\n"; |
|
| 409 | - } |
|
| 410 | - |
|
| 411 | - return [$texte, $textes_supplement]; |
|
| 393 | + if ( |
|
| 394 | + (strlen($texte) < 29 * 1024) |
|
| 395 | + or (include_spip('inc/layer') and ($GLOBALS['browser_name'] != 'MSIE')) |
|
| 396 | + ) { |
|
| 397 | + return [$texte, '']; |
|
| 398 | + } |
|
| 399 | + |
|
| 400 | + include_spip('inc/barre'); |
|
| 401 | + $textes_supplement = "<br /><span style='color: red'>" . _T('info_texte_long') . "</span>\n"; |
|
| 402 | + $nombre = 0; |
|
| 403 | + |
|
| 404 | + while (strlen($texte) > 29 * 1024) { |
|
| 405 | + $nombre++; |
|
| 406 | + [$texte1, $texte] = coupe_trop_long($texte); |
|
| 407 | + $textes_supplement .= '<br />' . |
|
| 408 | + "<textarea id='texte$nombre' name='texte_plus[$nombre]'$att_text>$texte1</textarea>\n"; |
|
| 409 | + } |
|
| 410 | + |
|
| 411 | + return [$texte, $textes_supplement]; |
|
| 412 | 412 | } |
| 413 | 413 | |
| 414 | 414 | /** |
@@ -419,17 +419,17 @@ discard block |
||
| 419 | 419 | * @param int $longueur |
| 420 | 420 | */ |
| 421 | 421 | function titre_automatique($champ_titre, $champs_contenu, $longueur = null) { |
| 422 | - if (!_request($champ_titre)) { |
|
| 423 | - $titrer_contenu = charger_fonction('titrer_contenu', 'inc'); |
|
| 424 | - if (!is_null($longueur)) { |
|
| 425 | - $t = $titrer_contenu($champs_contenu, null, $longueur); |
|
| 426 | - } else { |
|
| 427 | - $t = $titrer_contenu($champs_contenu); |
|
| 428 | - } |
|
| 429 | - if ($t) { |
|
| 430 | - set_request($champ_titre, $t); |
|
| 431 | - } |
|
| 432 | - } |
|
| 422 | + if (!_request($champ_titre)) { |
|
| 423 | + $titrer_contenu = charger_fonction('titrer_contenu', 'inc'); |
|
| 424 | + if (!is_null($longueur)) { |
|
| 425 | + $t = $titrer_contenu($champs_contenu, null, $longueur); |
|
| 426 | + } else { |
|
| 427 | + $t = $titrer_contenu($champs_contenu); |
|
| 428 | + } |
|
| 429 | + if ($t) { |
|
| 430 | + set_request($champ_titre, $t); |
|
| 431 | + } |
|
| 432 | + } |
|
| 433 | 433 | } |
| 434 | 434 | |
| 435 | 435 | /** |
@@ -449,20 +449,20 @@ discard block |
||
| 449 | 449 | * @return string |
| 450 | 450 | */ |
| 451 | 451 | function inc_titrer_contenu_dist($champs_contenu, $c = null, $longueur = 50) { |
| 452 | - // trouver un champ texte non vide |
|
| 453 | - $t = ''; |
|
| 454 | - foreach ($champs_contenu as $champ) { |
|
| 455 | - if ($t = _request($champ, $c)) { |
|
| 456 | - break; |
|
| 457 | - } |
|
| 458 | - } |
|
| 459 | - |
|
| 460 | - if ($t) { |
|
| 461 | - include_spip('inc/texte_mini'); |
|
| 462 | - $t = couper($t, $longueur, '...'); |
|
| 463 | - } |
|
| 464 | - |
|
| 465 | - return $t; |
|
| 452 | + // trouver un champ texte non vide |
|
| 453 | + $t = ''; |
|
| 454 | + foreach ($champs_contenu as $champ) { |
|
| 455 | + if ($t = _request($champ, $c)) { |
|
| 456 | + break; |
|
| 457 | + } |
|
| 458 | + } |
|
| 459 | + |
|
| 460 | + if ($t) { |
|
| 461 | + include_spip('inc/texte_mini'); |
|
| 462 | + $t = couper($t, $longueur, '...'); |
|
| 463 | + } |
|
| 464 | + |
|
| 465 | + return $t; |
|
| 466 | 466 | } |
| 467 | 467 | |
| 468 | 468 | /** |
@@ -484,26 +484,26 @@ discard block |
||
| 484 | 484 | * - array sinon couples ('$prefixe$colonne => md5) |
| 485 | 485 | **/ |
| 486 | 486 | function controles_md5(array $data, string $prefixe = 'ctr_', string $format = 'html') { |
| 487 | - $ctr = []; |
|
| 488 | - foreach ($data as $key => $val) { |
|
| 489 | - $m = md5($val ?? ''); |
|
| 490 | - $k = $prefixe . $key; |
|
| 491 | - |
|
| 492 | - switch ($format) { |
|
| 493 | - case 'html': |
|
| 494 | - $ctr[$k] = "<input type='hidden' value='$m' name='$k' />"; |
|
| 495 | - break; |
|
| 496 | - default: |
|
| 497 | - $ctr[$k] = $m; |
|
| 498 | - break; |
|
| 499 | - } |
|
| 500 | - } |
|
| 501 | - |
|
| 502 | - if ($format === 'html') { |
|
| 503 | - return "\n\n<!-- controles md5 -->\n" . join("\n", $ctr) . "\n\n"; |
|
| 504 | - } else { |
|
| 505 | - return $ctr; |
|
| 506 | - } |
|
| 487 | + $ctr = []; |
|
| 488 | + foreach ($data as $key => $val) { |
|
| 489 | + $m = md5($val ?? ''); |
|
| 490 | + $k = $prefixe . $key; |
|
| 491 | + |
|
| 492 | + switch ($format) { |
|
| 493 | + case 'html': |
|
| 494 | + $ctr[$k] = "<input type='hidden' value='$m' name='$k' />"; |
|
| 495 | + break; |
|
| 496 | + default: |
|
| 497 | + $ctr[$k] = $m; |
|
| 498 | + break; |
|
| 499 | + } |
|
| 500 | + } |
|
| 501 | + |
|
| 502 | + if ($format === 'html') { |
|
| 503 | + return "\n\n<!-- controles md5 -->\n" . join("\n", $ctr) . "\n\n"; |
|
| 504 | + } else { |
|
| 505 | + return $ctr; |
|
| 506 | + } |
|
| 507 | 507 | } |
| 508 | 508 | |
| 509 | 509 | /** |
@@ -542,80 +542,80 @@ discard block |
||
| 542 | 542 | * - post : le contenu posté |
| 543 | 543 | **/ |
| 544 | 544 | function controler_contenu($type, $id, $options = [], $c = false, $serveur = '') { |
| 545 | - include_spip('inc/filtres'); |
|
| 546 | - |
|
| 547 | - $table_objet = table_objet($type); |
|
| 548 | - $spip_table_objet = table_objet_sql($type); |
|
| 549 | - $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 550 | - $desc = $trouver_table($table_objet, $serveur); |
|
| 551 | - |
|
| 552 | - // Appels incomplets (sans $c) |
|
| 553 | - if (!is_array($c)) { |
|
| 554 | - $c = []; |
|
| 555 | - foreach ($desc['field'] as $champ => $ignore) { |
|
| 556 | - if (_request($champ)) { |
|
| 557 | - $c[$champ] = _request($champ); |
|
| 558 | - } |
|
| 559 | - } |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - // Securite : certaines variables ne sont jamais acceptees ici |
|
| 563 | - // car elles ne relevent pas de autoriser(article, modifier) ; |
|
| 564 | - // il faut passer par instituer_XX() |
|
| 565 | - // TODO: faut-il passer ces variables interdites |
|
| 566 | - // dans un fichier de description separe ? |
|
| 567 | - unset($c['statut']); |
|
| 568 | - unset($c['id_parent']); |
|
| 569 | - unset($c['id_rubrique']); |
|
| 570 | - unset($c['id_secteur']); |
|
| 571 | - |
|
| 572 | - // Gerer les champs non vides |
|
| 573 | - if (isset($options['nonvide']) and is_array($options['nonvide'])) { |
|
| 574 | - foreach ($options['nonvide'] as $champ => $sinon) { |
|
| 575 | - if ($c[$champ] === '') { |
|
| 576 | - $c[$champ] = $sinon; |
|
| 577 | - } |
|
| 578 | - } |
|
| 579 | - } |
|
| 580 | - |
|
| 581 | - // N'accepter que les champs qui existent |
|
| 582 | - // [TODO] ici aussi on peut valider les contenus en fonction du type |
|
| 583 | - $champs = []; |
|
| 584 | - foreach ($desc['field'] as $champ => $ignore) { |
|
| 585 | - if (isset($c[$champ])) { |
|
| 586 | - $champs[$champ] = $c[$champ]; |
|
| 587 | - } |
|
| 588 | - } |
|
| 589 | - |
|
| 590 | - // Nettoyer les valeurs |
|
| 591 | - $champs = array_map('corriger_caracteres', $champs); |
|
| 592 | - |
|
| 593 | - // Envoyer aux plugins |
|
| 594 | - $champs = pipeline( |
|
| 595 | - 'pre_edition', |
|
| 596 | - [ |
|
| 597 | - 'args' => [ |
|
| 598 | - 'table' => $spip_table_objet, // compatibilite |
|
| 599 | - 'table_objet' => $table_objet, |
|
| 600 | - 'spip_table_objet' => $spip_table_objet, |
|
| 601 | - 'type' => $type, |
|
| 602 | - 'id_objet' => $id, |
|
| 603 | - 'champs' => $options['champs'] ?? [], // [doc] c'est quoi ? |
|
| 604 | - 'action' => 'controler', |
|
| 605 | - 'serveur' => $serveur, |
|
| 606 | - ], |
|
| 607 | - 'data' => $champs |
|
| 608 | - ] |
|
| 609 | - ); |
|
| 610 | - |
|
| 611 | - if (!$champs) { |
|
| 612 | - return false; |
|
| 613 | - } |
|
| 614 | - |
|
| 615 | - // Verifier si les mises a jour sont pertinentes, datees, en conflit etc |
|
| 616 | - $conflits = controler_md5($champs, $_POST, $type, $id, $serveur, $options['prefix'] ?? 'ctr_'); |
|
| 617 | - |
|
| 618 | - return $conflits; |
|
| 545 | + include_spip('inc/filtres'); |
|
| 546 | + |
|
| 547 | + $table_objet = table_objet($type); |
|
| 548 | + $spip_table_objet = table_objet_sql($type); |
|
| 549 | + $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 550 | + $desc = $trouver_table($table_objet, $serveur); |
|
| 551 | + |
|
| 552 | + // Appels incomplets (sans $c) |
|
| 553 | + if (!is_array($c)) { |
|
| 554 | + $c = []; |
|
| 555 | + foreach ($desc['field'] as $champ => $ignore) { |
|
| 556 | + if (_request($champ)) { |
|
| 557 | + $c[$champ] = _request($champ); |
|
| 558 | + } |
|
| 559 | + } |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + // Securite : certaines variables ne sont jamais acceptees ici |
|
| 563 | + // car elles ne relevent pas de autoriser(article, modifier) ; |
|
| 564 | + // il faut passer par instituer_XX() |
|
| 565 | + // TODO: faut-il passer ces variables interdites |
|
| 566 | + // dans un fichier de description separe ? |
|
| 567 | + unset($c['statut']); |
|
| 568 | + unset($c['id_parent']); |
|
| 569 | + unset($c['id_rubrique']); |
|
| 570 | + unset($c['id_secteur']); |
|
| 571 | + |
|
| 572 | + // Gerer les champs non vides |
|
| 573 | + if (isset($options['nonvide']) and is_array($options['nonvide'])) { |
|
| 574 | + foreach ($options['nonvide'] as $champ => $sinon) { |
|
| 575 | + if ($c[$champ] === '') { |
|
| 576 | + $c[$champ] = $sinon; |
|
| 577 | + } |
|
| 578 | + } |
|
| 579 | + } |
|
| 580 | + |
|
| 581 | + // N'accepter que les champs qui existent |
|
| 582 | + // [TODO] ici aussi on peut valider les contenus en fonction du type |
|
| 583 | + $champs = []; |
|
| 584 | + foreach ($desc['field'] as $champ => $ignore) { |
|
| 585 | + if (isset($c[$champ])) { |
|
| 586 | + $champs[$champ] = $c[$champ]; |
|
| 587 | + } |
|
| 588 | + } |
|
| 589 | + |
|
| 590 | + // Nettoyer les valeurs |
|
| 591 | + $champs = array_map('corriger_caracteres', $champs); |
|
| 592 | + |
|
| 593 | + // Envoyer aux plugins |
|
| 594 | + $champs = pipeline( |
|
| 595 | + 'pre_edition', |
|
| 596 | + [ |
|
| 597 | + 'args' => [ |
|
| 598 | + 'table' => $spip_table_objet, // compatibilite |
|
| 599 | + 'table_objet' => $table_objet, |
|
| 600 | + 'spip_table_objet' => $spip_table_objet, |
|
| 601 | + 'type' => $type, |
|
| 602 | + 'id_objet' => $id, |
|
| 603 | + 'champs' => $options['champs'] ?? [], // [doc] c'est quoi ? |
|
| 604 | + 'action' => 'controler', |
|
| 605 | + 'serveur' => $serveur, |
|
| 606 | + ], |
|
| 607 | + 'data' => $champs |
|
| 608 | + ] |
|
| 609 | + ); |
|
| 610 | + |
|
| 611 | + if (!$champs) { |
|
| 612 | + return false; |
|
| 613 | + } |
|
| 614 | + |
|
| 615 | + // Verifier si les mises a jour sont pertinentes, datees, en conflit etc |
|
| 616 | + $conflits = controler_md5($champs, $_POST, $type, $id, $serveur, $options['prefix'] ?? 'ctr_'); |
|
| 617 | + |
|
| 618 | + return $conflits; |
|
| 619 | 619 | } |
| 620 | 620 | |
| 621 | 621 | |
@@ -645,64 +645,64 @@ discard block |
||
| 645 | 645 | * - post : le contenu posté |
| 646 | 646 | **/ |
| 647 | 647 | function controler_md5(&$champs, $ctr, $type, $id, $serveur, $prefix = 'ctr_') { |
| 648 | - $spip_table_objet = table_objet_sql($type); |
|
| 649 | - $id_table_objet = id_table_objet($type); |
|
| 650 | - |
|
| 651 | - // Controle des MD5 envoyes |
|
| 652 | - // On elimine les donnees non modifiees par le formulaire (mais |
|
| 653 | - // potentiellement modifiees entre temps par un autre utilisateur) |
|
| 654 | - foreach ($champs as $key => $val) { |
|
| 655 | - if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) { |
|
| 656 | - if (is_scalar($val) and $m == md5($val)) { |
|
| 657 | - unset($champs[$key]); |
|
| 658 | - } |
|
| 659 | - } |
|
| 660 | - } |
|
| 661 | - if (!$champs) { |
|
| 662 | - return; |
|
| 663 | - } |
|
| 664 | - |
|
| 665 | - // On veut savoir si notre modif va avoir un impact |
|
| 666 | - // par rapport aux donnees contenues dans la base |
|
| 667 | - // (qui peuvent etre differentes de celles ayant servi a calculer le ctr) |
|
| 668 | - $s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur); |
|
| 669 | - $intact = true; |
|
| 670 | - foreach ($champs as $ch => $val) { |
|
| 671 | - $intact &= ($s[$ch] == $val); |
|
| 672 | - } |
|
| 673 | - if ($intact) { |
|
| 674 | - return; |
|
| 675 | - } |
|
| 676 | - |
|
| 677 | - // Detection de conflits : |
|
| 678 | - // On verifie si notre modif ne provient pas d'un formulaire |
|
| 679 | - // genere a partir de donnees modifiees dans l'intervalle ; ici |
|
| 680 | - // on compare a ce qui est dans la base, et on bloque en cas |
|
| 681 | - // de conflit. |
|
| 682 | - $ctrh = $ctrq = $conflits = []; |
|
| 683 | - foreach (array_keys($champs) as $key) { |
|
| 684 | - if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) { |
|
| 685 | - $ctrh[$key] = $m; |
|
| 686 | - $ctrq[] = $key; |
|
| 687 | - } |
|
| 688 | - } |
|
| 689 | - if ($ctrq) { |
|
| 690 | - $ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur); |
|
| 691 | - foreach ($ctrh as $key => $m) { |
|
| 692 | - if ( |
|
| 693 | - $m != md5($ctrq[$key]) |
|
| 694 | - and $champs[$key] !== $ctrq[$key] |
|
| 695 | - ) { |
|
| 696 | - $conflits[$key] = [ |
|
| 697 | - 'base' => $ctrq[$key], |
|
| 698 | - 'post' => $champs[$key] |
|
| 699 | - ]; |
|
| 700 | - unset($champs[$key]); # stocker quand meme les modifs ? |
|
| 701 | - } |
|
| 702 | - } |
|
| 703 | - } |
|
| 704 | - |
|
| 705 | - return $conflits; |
|
| 648 | + $spip_table_objet = table_objet_sql($type); |
|
| 649 | + $id_table_objet = id_table_objet($type); |
|
| 650 | + |
|
| 651 | + // Controle des MD5 envoyes |
|
| 652 | + // On elimine les donnees non modifiees par le formulaire (mais |
|
| 653 | + // potentiellement modifiees entre temps par un autre utilisateur) |
|
| 654 | + foreach ($champs as $key => $val) { |
|
| 655 | + if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) { |
|
| 656 | + if (is_scalar($val) and $m == md5($val)) { |
|
| 657 | + unset($champs[$key]); |
|
| 658 | + } |
|
| 659 | + } |
|
| 660 | + } |
|
| 661 | + if (!$champs) { |
|
| 662 | + return; |
|
| 663 | + } |
|
| 664 | + |
|
| 665 | + // On veut savoir si notre modif va avoir un impact |
|
| 666 | + // par rapport aux donnees contenues dans la base |
|
| 667 | + // (qui peuvent etre differentes de celles ayant servi a calculer le ctr) |
|
| 668 | + $s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur); |
|
| 669 | + $intact = true; |
|
| 670 | + foreach ($champs as $ch => $val) { |
|
| 671 | + $intact &= ($s[$ch] == $val); |
|
| 672 | + } |
|
| 673 | + if ($intact) { |
|
| 674 | + return; |
|
| 675 | + } |
|
| 676 | + |
|
| 677 | + // Detection de conflits : |
|
| 678 | + // On verifie si notre modif ne provient pas d'un formulaire |
|
| 679 | + // genere a partir de donnees modifiees dans l'intervalle ; ici |
|
| 680 | + // on compare a ce qui est dans la base, et on bloque en cas |
|
| 681 | + // de conflit. |
|
| 682 | + $ctrh = $ctrq = $conflits = []; |
|
| 683 | + foreach (array_keys($champs) as $key) { |
|
| 684 | + if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) { |
|
| 685 | + $ctrh[$key] = $m; |
|
| 686 | + $ctrq[] = $key; |
|
| 687 | + } |
|
| 688 | + } |
|
| 689 | + if ($ctrq) { |
|
| 690 | + $ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur); |
|
| 691 | + foreach ($ctrh as $key => $m) { |
|
| 692 | + if ( |
|
| 693 | + $m != md5($ctrq[$key]) |
|
| 694 | + and $champs[$key] !== $ctrq[$key] |
|
| 695 | + ) { |
|
| 696 | + $conflits[$key] = [ |
|
| 697 | + 'base' => $ctrq[$key], |
|
| 698 | + 'post' => $champs[$key] |
|
| 699 | + ]; |
|
| 700 | + unset($champs[$key]); # stocker quand meme les modifs ? |
|
| 701 | + } |
|
| 702 | + } |
|
| 703 | + } |
|
| 704 | + |
|
| 705 | + return $conflits; |
|
| 706 | 706 | } |
| 707 | 707 | |
| 708 | 708 | /** |
@@ -714,9 +714,9 @@ discard block |
||
| 714 | 714 | * @return string |
| 715 | 715 | */ |
| 716 | 716 | function display_conflit_champ($x) { |
| 717 | - if (strstr($x, "\n") or strlen($x) > 80) { |
|
| 718 | - return "<textarea style='width:99%; height:10em;'>" . entites_html($x) . "</textarea>\n"; |
|
| 719 | - } else { |
|
| 720 | - return "<input type='text' size='40' style='width:99%' value=\"" . entites_html($x) . "\" />\n"; |
|
| 721 | - } |
|
| 717 | + if (strstr($x, "\n") or strlen($x) > 80) { |
|
| 718 | + return "<textarea style='width:99%; height:10em;'>" . entites_html($x) . "</textarea>\n"; |
|
| 719 | + } else { |
|
| 720 | + return "<input type='text' size='40' style='width:99%' value=\"" . entites_html($x) . "\" />\n"; |
|
| 721 | + } |
|
| 722 | 722 | } |
@@ -23,7 +23,7 @@ discard block |
||
| 23 | 23 | **/ |
| 24 | 24 | |
| 25 | 25 | if (!defined('_ECRIRE_INC_VERSION')) { |
| 26 | - return; |
|
| 26 | + return; |
|
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | // public/interfaces definit des traitements sur les champs qui utilisent des fonctions de inc/texte |
@@ -55,75 +55,75 @@ discard block |
||
| 55 | 55 | * Introduction calculée |
| 56 | 56 | **/ |
| 57 | 57 | function filtre_introduction_dist($descriptif, $texte, $longueur, $connect, $suite = null) { |
| 58 | - // Si un descriptif est envoye, on l'utilise directement |
|
| 59 | - if (strlen($descriptif)) { |
|
| 60 | - return appliquer_traitement_champ($descriptif, 'introduction', '', [], $connect); |
|
| 61 | - } |
|
| 62 | - |
|
| 63 | - // De preference ce qui est marque <intro>...</intro> |
|
| 64 | - $intro = ''; |
|
| 65 | - $texte = preg_replace(',(</?)intro>,i', "\\1intro>", $texte); // minuscules |
|
| 66 | - while ($fin = strpos($texte, '</intro>')) { |
|
| 67 | - $zone = substr($texte, 0, $fin); |
|
| 68 | - $texte = substr($texte, $fin + strlen('</intro>')); |
|
| 69 | - if ($deb = strpos($zone, '<intro>') or substr($zone, 0, 7) == '<intro>') { |
|
| 70 | - $zone = substr($zone, $deb + 7); |
|
| 71 | - } |
|
| 72 | - $intro .= $zone; |
|
| 73 | - } |
|
| 74 | - |
|
| 75 | - // [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut, |
|
| 76 | - // qui inclus raccourcis et modeles |
|
| 77 | - // un simple <articlexx> peut etre ensuite transforme en 1000 lignes ... |
|
| 78 | - // par ailleurs le nettoyage des raccourcis ne tient pas compte |
|
| 79 | - // des surcharges et enrichissement de propre |
|
| 80 | - // couper doit se faire apres propre |
|
| 81 | - //$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect); |
|
| 82 | - |
|
| 83 | - // Cependant pour des questions de perfs on coupe quand meme, en prenant |
|
| 84 | - // large et en se mefiant des tableaux #1323 |
|
| 85 | - |
|
| 86 | - if (strlen($intro)) { |
|
| 87 | - $texte = $intro; |
|
| 88 | - } else { |
|
| 89 | - if ( |
|
| 90 | - strpos("\n" . $texte, "\n|") === false |
|
| 91 | - and strlen($texte) > 2.5 * $longueur |
|
| 92 | - ) { |
|
| 93 | - if (strpos($texte, '<multi') !== false) { |
|
| 94 | - $texte = extraire_multi($texte); |
|
| 95 | - } |
|
| 96 | - $texte = couper($texte, 2 * $longueur); |
|
| 97 | - } |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - // ne pas tenir compte des notes |
|
| 101 | - if ($notes = charger_fonction('notes', 'inc', true)) { |
|
| 102 | - $notes('', 'empiler'); |
|
| 103 | - } |
|
| 104 | - // Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable |
|
| 105 | - // dans l'introduction. |
|
| 106 | - $texte = supprime_img($texte, ''); |
|
| 107 | - $texte = appliquer_traitement_champ($texte, 'introduction', '', [], $connect); |
|
| 108 | - |
|
| 109 | - if ($notes) { |
|
| 110 | - $notes('', 'depiler'); |
|
| 111 | - } |
|
| 112 | - |
|
| 113 | - if (is_null($suite) and defined('_INTRODUCTION_SUITE')) { |
|
| 114 | - $suite = _INTRODUCTION_SUITE; |
|
| 115 | - } |
|
| 116 | - $texte = couper($texte, $longueur, $suite); |
|
| 117 | - // comme on a coupe il faut repasser la typo (on a perdu les insecables) |
|
| 118 | - $texte = typo($texte, true, $connect, []); |
|
| 119 | - |
|
| 120 | - // et reparagrapher si necessaire (coherence avec le cas descriptif) |
|
| 121 | - // une introduction a tojours un <p> |
|
| 122 | - if ($GLOBALS['toujours_paragrapher']) { // Fermer les paragraphes |
|
| 123 | - $texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']); |
|
| 124 | - } |
|
| 125 | - |
|
| 126 | - return $texte; |
|
| 58 | + // Si un descriptif est envoye, on l'utilise directement |
|
| 59 | + if (strlen($descriptif)) { |
|
| 60 | + return appliquer_traitement_champ($descriptif, 'introduction', '', [], $connect); |
|
| 61 | + } |
|
| 62 | + |
|
| 63 | + // De preference ce qui est marque <intro>...</intro> |
|
| 64 | + $intro = ''; |
|
| 65 | + $texte = preg_replace(',(</?)intro>,i', "\\1intro>", $texte); // minuscules |
|
| 66 | + while ($fin = strpos($texte, '</intro>')) { |
|
| 67 | + $zone = substr($texte, 0, $fin); |
|
| 68 | + $texte = substr($texte, $fin + strlen('</intro>')); |
|
| 69 | + if ($deb = strpos($zone, '<intro>') or substr($zone, 0, 7) == '<intro>') { |
|
| 70 | + $zone = substr($zone, $deb + 7); |
|
| 71 | + } |
|
| 72 | + $intro .= $zone; |
|
| 73 | + } |
|
| 74 | + |
|
| 75 | + // [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut, |
|
| 76 | + // qui inclus raccourcis et modeles |
|
| 77 | + // un simple <articlexx> peut etre ensuite transforme en 1000 lignes ... |
|
| 78 | + // par ailleurs le nettoyage des raccourcis ne tient pas compte |
|
| 79 | + // des surcharges et enrichissement de propre |
|
| 80 | + // couper doit se faire apres propre |
|
| 81 | + //$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect); |
|
| 82 | + |
|
| 83 | + // Cependant pour des questions de perfs on coupe quand meme, en prenant |
|
| 84 | + // large et en se mefiant des tableaux #1323 |
|
| 85 | + |
|
| 86 | + if (strlen($intro)) { |
|
| 87 | + $texte = $intro; |
|
| 88 | + } else { |
|
| 89 | + if ( |
|
| 90 | + strpos("\n" . $texte, "\n|") === false |
|
| 91 | + and strlen($texte) > 2.5 * $longueur |
|
| 92 | + ) { |
|
| 93 | + if (strpos($texte, '<multi') !== false) { |
|
| 94 | + $texte = extraire_multi($texte); |
|
| 95 | + } |
|
| 96 | + $texte = couper($texte, 2 * $longueur); |
|
| 97 | + } |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + // ne pas tenir compte des notes |
|
| 101 | + if ($notes = charger_fonction('notes', 'inc', true)) { |
|
| 102 | + $notes('', 'empiler'); |
|
| 103 | + } |
|
| 104 | + // Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable |
|
| 105 | + // dans l'introduction. |
|
| 106 | + $texte = supprime_img($texte, ''); |
|
| 107 | + $texte = appliquer_traitement_champ($texte, 'introduction', '', [], $connect); |
|
| 108 | + |
|
| 109 | + if ($notes) { |
|
| 110 | + $notes('', 'depiler'); |
|
| 111 | + } |
|
| 112 | + |
|
| 113 | + if (is_null($suite) and defined('_INTRODUCTION_SUITE')) { |
|
| 114 | + $suite = _INTRODUCTION_SUITE; |
|
| 115 | + } |
|
| 116 | + $texte = couper($texte, $longueur, $suite); |
|
| 117 | + // comme on a coupe il faut repasser la typo (on a perdu les insecables) |
|
| 118 | + $texte = typo($texte, true, $connect, []); |
|
| 119 | + |
|
| 120 | + // et reparagrapher si necessaire (coherence avec le cas descriptif) |
|
| 121 | + // une introduction a tojours un <p> |
|
| 122 | + if ($GLOBALS['toujours_paragrapher']) { // Fermer les paragraphes |
|
| 123 | + $texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']); |
|
| 124 | + } |
|
| 125 | + |
|
| 126 | + return $texte; |
|
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | |
@@ -158,73 +158,73 @@ discard block |
||
| 158 | 158 | * Code HTML de la pagination |
| 159 | 159 | **/ |
| 160 | 160 | function filtre_pagination_dist( |
| 161 | - $total, |
|
| 162 | - $nom, |
|
| 163 | - $position, |
|
| 164 | - $pas, |
|
| 165 | - $liste = true, |
|
| 166 | - $modele = '', |
|
| 167 | - string $connect = '', |
|
| 168 | - $env = [] |
|
| 161 | + $total, |
|
| 162 | + $nom, |
|
| 163 | + $position, |
|
| 164 | + $pas, |
|
| 165 | + $liste = true, |
|
| 166 | + $modele = '', |
|
| 167 | + string $connect = '', |
|
| 168 | + $env = [] |
|
| 169 | 169 | ) { |
| 170 | - static $ancres = []; |
|
| 171 | - if ($pas < 1) { |
|
| 172 | - return ''; |
|
| 173 | - } |
|
| 174 | - $ancre = 'pagination' . $nom; // #pagination_articles |
|
| 175 | - $debut = 'debut' . $nom; // 'debut_articles' |
|
| 176 | - |
|
| 177 | - // n'afficher l'ancre qu'une fois |
|
| 178 | - if (!isset($ancres[$ancre])) { |
|
| 179 | - $bloc_ancre = $ancres[$ancre] = "<a id='" . $ancre . "' class='pagination_ancre'></a>"; |
|
| 180 | - } else { |
|
| 181 | - $bloc_ancre = ''; |
|
| 182 | - } |
|
| 183 | - // liste = false : on ne veut que l'ancre |
|
| 184 | - if (!$liste) { |
|
| 185 | - return $ancres[$ancre]; |
|
| 186 | - } |
|
| 187 | - |
|
| 188 | - $self = (empty($env['self']) ? self() : $env['self']); |
|
| 189 | - $pagination = [ |
|
| 190 | - 'debut' => $debut, |
|
| 191 | - 'url' => parametre_url($self, 'fragment', ''), // nettoyer l'id ahah eventuel |
|
| 192 | - 'total' => $total, |
|
| 193 | - 'position' => intval($position), |
|
| 194 | - 'pas' => $pas, |
|
| 195 | - 'nombre_pages' => floor(($total - 1) / $pas) + 1, |
|
| 196 | - 'page_courante' => floor(intval($position) / $pas) + 1, |
|
| 197 | - 'ancre' => $ancre, |
|
| 198 | - 'bloc_ancre' => $bloc_ancre |
|
| 199 | - ]; |
|
| 200 | - if (is_array($env)) { |
|
| 201 | - $pagination = array_merge($env, $pagination); |
|
| 202 | - } |
|
| 203 | - |
|
| 204 | - // Pas de pagination |
|
| 205 | - if ($pagination['nombre_pages'] <= 1) { |
|
| 206 | - return ''; |
|
| 207 | - } |
|
| 208 | - |
|
| 209 | - if ($modele) { |
|
| 210 | - $pagination['type_pagination'] = $modele; |
|
| 211 | - if (trouver_fond('pagination_' . $modele, 'modeles')) { |
|
| 212 | - $modele = '_' . $modele; |
|
| 213 | - } |
|
| 214 | - else { |
|
| 215 | - $modele = ''; |
|
| 216 | - } |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) { |
|
| 220 | - define('_PAGINATION_NOMBRE_LIENS_MAX', 10); |
|
| 221 | - } |
|
| 222 | - if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) { |
|
| 223 | - define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 5); |
|
| 224 | - } |
|
| 225 | - |
|
| 226 | - |
|
| 227 | - return recuperer_fond("modeles/pagination$modele", $pagination, ['trim' => true], $connect); |
|
| 170 | + static $ancres = []; |
|
| 171 | + if ($pas < 1) { |
|
| 172 | + return ''; |
|
| 173 | + } |
|
| 174 | + $ancre = 'pagination' . $nom; // #pagination_articles |
|
| 175 | + $debut = 'debut' . $nom; // 'debut_articles' |
|
| 176 | + |
|
| 177 | + // n'afficher l'ancre qu'une fois |
|
| 178 | + if (!isset($ancres[$ancre])) { |
|
| 179 | + $bloc_ancre = $ancres[$ancre] = "<a id='" . $ancre . "' class='pagination_ancre'></a>"; |
|
| 180 | + } else { |
|
| 181 | + $bloc_ancre = ''; |
|
| 182 | + } |
|
| 183 | + // liste = false : on ne veut que l'ancre |
|
| 184 | + if (!$liste) { |
|
| 185 | + return $ancres[$ancre]; |
|
| 186 | + } |
|
| 187 | + |
|
| 188 | + $self = (empty($env['self']) ? self() : $env['self']); |
|
| 189 | + $pagination = [ |
|
| 190 | + 'debut' => $debut, |
|
| 191 | + 'url' => parametre_url($self, 'fragment', ''), // nettoyer l'id ahah eventuel |
|
| 192 | + 'total' => $total, |
|
| 193 | + 'position' => intval($position), |
|
| 194 | + 'pas' => $pas, |
|
| 195 | + 'nombre_pages' => floor(($total - 1) / $pas) + 1, |
|
| 196 | + 'page_courante' => floor(intval($position) / $pas) + 1, |
|
| 197 | + 'ancre' => $ancre, |
|
| 198 | + 'bloc_ancre' => $bloc_ancre |
|
| 199 | + ]; |
|
| 200 | + if (is_array($env)) { |
|
| 201 | + $pagination = array_merge($env, $pagination); |
|
| 202 | + } |
|
| 203 | + |
|
| 204 | + // Pas de pagination |
|
| 205 | + if ($pagination['nombre_pages'] <= 1) { |
|
| 206 | + return ''; |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + if ($modele) { |
|
| 210 | + $pagination['type_pagination'] = $modele; |
|
| 211 | + if (trouver_fond('pagination_' . $modele, 'modeles')) { |
|
| 212 | + $modele = '_' . $modele; |
|
| 213 | + } |
|
| 214 | + else { |
|
| 215 | + $modele = ''; |
|
| 216 | + } |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) { |
|
| 220 | + define('_PAGINATION_NOMBRE_LIENS_MAX', 10); |
|
| 221 | + } |
|
| 222 | + if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) { |
|
| 223 | + define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 5); |
|
| 224 | + } |
|
| 225 | + |
|
| 226 | + |
|
| 227 | + return recuperer_fond("modeles/pagination$modele", $pagination, ['trim' => true], $connect); |
|
| 228 | 228 | } |
| 229 | 229 | |
| 230 | 230 | |
@@ -243,44 +243,44 @@ discard block |
||
| 243 | 243 | * Liste (première page, dernière page). |
| 244 | 244 | **/ |
| 245 | 245 | function filtre_bornes_pagination_dist($courante, $nombre, $max = 10) { |
| 246 | - if ($max <= 0 or $max >= $nombre) { |
|
| 247 | - return [1, $nombre]; |
|
| 248 | - } |
|
| 249 | - if ($max <= 1) { |
|
| 250 | - return [$courante, $courante]; |
|
| 251 | - } |
|
| 252 | - |
|
| 253 | - $premiere = max(1, $courante - floor(($max - 1) / 2)); |
|
| 254 | - $derniere = min($nombre, $premiere + $max - 2); |
|
| 255 | - $premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere; |
|
| 256 | - |
|
| 257 | - return [$premiere, $derniere]; |
|
| 246 | + if ($max <= 0 or $max >= $nombre) { |
|
| 247 | + return [1, $nombre]; |
|
| 248 | + } |
|
| 249 | + if ($max <= 1) { |
|
| 250 | + return [$courante, $courante]; |
|
| 251 | + } |
|
| 252 | + |
|
| 253 | + $premiere = max(1, $courante - floor(($max - 1) / 2)); |
|
| 254 | + $derniere = min($nombre, $premiere + $max - 2); |
|
| 255 | + $premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere; |
|
| 256 | + |
|
| 257 | + return [$premiere, $derniere]; |
|
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 | function filtre_pagination_affiche_texte_lien_page_dist($type_pagination, $numero_page, $rang_item) { |
| 261 | - if ($numero_page === 'tous') { |
|
| 262 | - return '∞'; |
|
| 263 | - } |
|
| 264 | - if ($numero_page === 'prev') { |
|
| 265 | - return '<'; |
|
| 266 | - } |
|
| 267 | - if ($numero_page === 'next') { |
|
| 268 | - return '>'; |
|
| 269 | - } |
|
| 270 | - |
|
| 271 | - switch ($type_pagination) { |
|
| 272 | - case 'resultats': |
|
| 273 | - return $rang_item + 1; // 1 11 21 31... |
|
| 274 | - case 'naturel': |
|
| 275 | - return $rang_item ?: 1; // 1 10 20 30... |
|
| 276 | - case 'rang': |
|
| 277 | - return $rang_item; // 0 10 20 30... |
|
| 278 | - |
|
| 279 | - case 'page': |
|
| 280 | - case 'prive': |
|
| 281 | - default: |
|
| 282 | - return $numero_page; // 1 2 3 4 5... |
|
| 283 | - } |
|
| 261 | + if ($numero_page === 'tous') { |
|
| 262 | + return '∞'; |
|
| 263 | + } |
|
| 264 | + if ($numero_page === 'prev') { |
|
| 265 | + return '<'; |
|
| 266 | + } |
|
| 267 | + if ($numero_page === 'next') { |
|
| 268 | + return '>'; |
|
| 269 | + } |
|
| 270 | + |
|
| 271 | + switch ($type_pagination) { |
|
| 272 | + case 'resultats': |
|
| 273 | + return $rang_item + 1; // 1 11 21 31... |
|
| 274 | + case 'naturel': |
|
| 275 | + return $rang_item ?: 1; // 1 10 20 30... |
|
| 276 | + case 'rang': |
|
| 277 | + return $rang_item; // 0 10 20 30... |
|
| 278 | + |
|
| 279 | + case 'page': |
|
| 280 | + case 'prive': |
|
| 281 | + default: |
|
| 282 | + return $numero_page; // 1 2 3 4 5... |
|
| 283 | + } |
|
| 284 | 284 | } |
| 285 | 285 | |
| 286 | 286 | /** |
@@ -293,15 +293,15 @@ discard block |
||
| 293 | 293 | **/ |
| 294 | 294 | function lister_objets_avec_logos($type) { |
| 295 | 295 | |
| 296 | - $objet = objet_type($type); |
|
| 297 | - $ids = sql_allfetsel('L.id_objet', 'spip_documents AS D JOIN spip_documents_liens AS L ON L.id_document=D.id_document', 'D.mode=' . sql_quote('logoon') . ' AND L.objet=' . sql_quote($objet)); |
|
| 298 | - if ($ids) { |
|
| 299 | - $ids = array_column($ids, 'id_objet'); |
|
| 300 | - return implode(',', $ids); |
|
| 301 | - } |
|
| 302 | - else { |
|
| 303 | - return '0'; |
|
| 304 | - } |
|
| 296 | + $objet = objet_type($type); |
|
| 297 | + $ids = sql_allfetsel('L.id_objet', 'spip_documents AS D JOIN spip_documents_liens AS L ON L.id_document=D.id_document', 'D.mode=' . sql_quote('logoon') . ' AND L.objet=' . sql_quote($objet)); |
|
| 298 | + if ($ids) { |
|
| 299 | + $ids = array_column($ids, 'id_objet'); |
|
| 300 | + return implode(',', $ids); |
|
| 301 | + } |
|
| 302 | + else { |
|
| 303 | + return '0'; |
|
| 304 | + } |
|
| 305 | 305 | } |
| 306 | 306 | |
| 307 | 307 | |
@@ -317,14 +317,14 @@ discard block |
||
| 317 | 317 | * Code HTML des notes |
| 318 | 318 | **/ |
| 319 | 319 | function calculer_notes() { |
| 320 | - $r = ''; |
|
| 321 | - if ($notes = charger_fonction('notes', 'inc', true)) { |
|
| 322 | - $r = $notes([]); |
|
| 323 | - $notes('', 'depiler'); |
|
| 324 | - $notes('', 'empiler'); |
|
| 325 | - } |
|
| 326 | - |
|
| 327 | - return $r; |
|
| 320 | + $r = ''; |
|
| 321 | + if ($notes = charger_fonction('notes', 'inc', true)) { |
|
| 322 | + $r = $notes([]); |
|
| 323 | + $notes('', 'depiler'); |
|
| 324 | + $notes('', 'empiler'); |
|
| 325 | + } |
|
| 326 | + |
|
| 327 | + return $r; |
|
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | |
@@ -341,10 +341,10 @@ discard block |
||
| 341 | 341 | * @return string |
| 342 | 342 | */ |
| 343 | 343 | function retrouver_rang_lien($objet_source, $ids, $objet_lie, $idl, $objet_lien) { |
| 344 | - $res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien); |
|
| 345 | - $res = array_column($res, 'rang_lien', $objet_source); |
|
| 344 | + $res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien); |
|
| 345 | + $res = array_column($res, 'rang_lien', $objet_source); |
|
| 346 | 346 | |
| 347 | - return ($res[$ids] ?? ''); |
|
| 347 | + return ($res[$ids] ?? ''); |
|
| 348 | 348 | } |
| 349 | 349 | |
| 350 | 350 | |
@@ -361,19 +361,19 @@ discard block |
||
| 361 | 361 | * @private |
| 362 | 362 | */ |
| 363 | 363 | function lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien) { |
| 364 | - static $liens = []; |
|
| 365 | - if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) { |
|
| 366 | - include_spip('action/editer_liens'); |
|
| 367 | - // quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source |
|
| 368 | - if ($objet_lien == $objet and $objet_lien !== $objet_source) { |
|
| 369 | - $res = objet_trouver_liens([$objet => $id_objet], [$objet_source => '*']); |
|
| 370 | - } else { |
|
| 371 | - $res = objet_trouver_liens([$objet_source => '*'], [$objet => $id_objet]); |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - $liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res; |
|
| 375 | - } |
|
| 376 | - return $liens["$objet_source-$objet-$id_objet-$objet_lien"]; |
|
| 364 | + static $liens = []; |
|
| 365 | + if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) { |
|
| 366 | + include_spip('action/editer_liens'); |
|
| 367 | + // quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source |
|
| 368 | + if ($objet_lien == $objet and $objet_lien !== $objet_source) { |
|
| 369 | + $res = objet_trouver_liens([$objet => $id_objet], [$objet_source => '*']); |
|
| 370 | + } else { |
|
| 371 | + $res = objet_trouver_liens([$objet_source => '*'], [$objet => $id_objet]); |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + $liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res; |
|
| 375 | + } |
|
| 376 | + return $liens["$objet_source-$objet-$id_objet-$objet_lien"]; |
|
| 377 | 377 | } |
| 378 | 378 | |
| 379 | 379 | /** |
@@ -387,24 +387,24 @@ discard block |
||
| 387 | 387 | * @return int|string |
| 388 | 388 | */ |
| 389 | 389 | function calculer_rang_smart($titre, $objet_source, $id, $env) { |
| 390 | - // Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien |
|
| 391 | - // permet de voir le rang du lien si il y en a un en base, meme avant un squelette xxxx-lies.html ne gerant pas les liens |
|
| 392 | - if ( |
|
| 393 | - isset($env['form']) and $env['form'] |
|
| 394 | - and isset($env['_objet_lien']) and $env['_objet_lien'] |
|
| 395 | - and (function_exists('lien_triables') or include_spip('action/editer_liens')) |
|
| 396 | - and $r = objet_associable($env['_objet_lien']) |
|
| 397 | - and [$p, $table_lien] = $r |
|
| 398 | - and lien_triables($table_lien) |
|
| 399 | - and isset($env['objet']) and $env['objet'] |
|
| 400 | - and isset($env['id_objet']) and $env['id_objet'] |
|
| 401 | - and $objet_source |
|
| 402 | - and $id = intval($id) |
|
| 403 | - ) { |
|
| 404 | - $rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']); |
|
| 405 | - return ($rang ?: ''); |
|
| 406 | - } |
|
| 407 | - return recuperer_numero($titre); |
|
| 390 | + // Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien |
|
| 391 | + // permet de voir le rang du lien si il y en a un en base, meme avant un squelette xxxx-lies.html ne gerant pas les liens |
|
| 392 | + if ( |
|
| 393 | + isset($env['form']) and $env['form'] |
|
| 394 | + and isset($env['_objet_lien']) and $env['_objet_lien'] |
|
| 395 | + and (function_exists('lien_triables') or include_spip('action/editer_liens')) |
|
| 396 | + and $r = objet_associable($env['_objet_lien']) |
|
| 397 | + and [$p, $table_lien] = $r |
|
| 398 | + and lien_triables($table_lien) |
|
| 399 | + and isset($env['objet']) and $env['objet'] |
|
| 400 | + and isset($env['id_objet']) and $env['id_objet'] |
|
| 401 | + and $objet_source |
|
| 402 | + and $id = intval($id) |
|
| 403 | + ) { |
|
| 404 | + $rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']); |
|
| 405 | + return ($rang ?: ''); |
|
| 406 | + } |
|
| 407 | + return recuperer_numero($titre); |
|
| 408 | 408 | } |
| 409 | 409 | |
| 410 | 410 | /** |
@@ -431,72 +431,72 @@ discard block |
||
| 431 | 431 | */ |
| 432 | 432 | function calculer_balise_tri(string $champ_ou_sens, string $libelle, string $classe, string $tri_nom, string $tri_champ, string $tri_sens, $liste_tri_sens_defaut): string { |
| 433 | 433 | |
| 434 | - $url = self('&'); |
|
| 435 | - $tri_sens = (int) $tri_sens; |
|
| 436 | - $alias_sens = [ |
|
| 437 | - '<' => -1, |
|
| 438 | - '>' => 1, |
|
| 439 | - 'inverse' => -1, |
|
| 440 | - ]; |
|
| 441 | - |
|
| 442 | - // Normaliser la liste des sens de tri par défaut |
|
| 443 | - // On ajoute un jocker pour les champs non présents dans la liste |
|
| 444 | - // avec la valeur du 1er item de la liste, idem critère {tri} |
|
| 445 | - if (is_array($liste_tri_sens_defaut)) { |
|
| 446 | - $liste_tri_sens_defaut['*'] = array_values($liste_tri_sens_defaut)[0]; |
|
| 447 | - } else { |
|
| 448 | - $liste_tri_sens_defaut = [ |
|
| 449 | - '*' => (int) ($alias_sens[$liste_tri_sens_defaut] ?? $liste_tri_sens_defaut), |
|
| 450 | - ]; |
|
| 451 | - } |
|
| 452 | - |
|
| 453 | - // Les sens de tri actuel et nouveau : |
|
| 454 | - // Soit c'est un sens fixe donné en paramètre (< ou >) |
|
| 455 | - $is_sens_fixe = array_key_exists($champ_ou_sens, $alias_sens); |
|
| 456 | - if ($is_sens_fixe) { |
|
| 457 | - $tri_sens_actuel = $tri_sens; |
|
| 458 | - $tri_sens_nouveau = $alias_sens[$champ_ou_sens]; |
|
| 459 | - // Soit c'est le champ utilisé actuellement pour le tri → on inverse le sens |
|
| 460 | - } elseif ($champ_ou_sens === $tri_champ) { |
|
| 461 | - $tri_sens_actuel = $tri_sens; |
|
| 462 | - $tri_sens_nouveau = $tri_sens * -1; |
|
| 463 | - // Sinon c'est un nouveau champ, et on prend son tri par défaut |
|
| 464 | - } else { |
|
| 465 | - $tri_sens_actuel = $tri_sens_nouveau = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']); |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - // URL : ajouter le champ sur lequel porte le tri |
|
| 469 | - if (!$is_sens_fixe) { |
|
| 470 | - $param_tri = "tri$tri_nom"; |
|
| 471 | - $url = parametre_url($url, $param_tri, $champ_ou_sens); |
|
| 472 | - } |
|
| 473 | - |
|
| 474 | - // URL : n'ajouter le sens de tri que si nécessaire, |
|
| 475 | - // c.à.d différent du sens par défaut pour le champ |
|
| 476 | - $param_sens = "sens$tri_nom"; |
|
| 477 | - $tri_sens_defaut_champ = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']); |
|
| 478 | - if ($tri_sens_nouveau !== $tri_sens_defaut_champ) { |
|
| 479 | - $url = parametre_url($url, $param_sens, $tri_sens_nouveau); |
|
| 480 | - } else { |
|
| 481 | - $url = parametre_url($url, $param_sens, ''); |
|
| 482 | - } |
|
| 483 | - |
|
| 484 | - // Drapeau pour garder en session ? |
|
| 485 | - $param_memo = (!$is_sens_fixe ? $param_tri : $param_sens); |
|
| 486 | - $url = parametre_url($url, 'var_memotri', strncmp($tri_nom, 'session', 7) == 0 ? $param_memo : ''); |
|
| 487 | - |
|
| 488 | - // Classes : on indique le sens de tri et l'item exposé |
|
| 489 | - if (!$is_sens_fixe) { |
|
| 490 | - $classe .= ' item-tri item-tri_' . ($tri_sens_actuel === 1 ? 'asc' : 'desc'); |
|
| 491 | - } |
|
| 492 | - if ($champ_ou_sens === $tri_champ) { |
|
| 493 | - $classe .= ' item-tri_actif'; |
|
| 494 | - } |
|
| 495 | - |
|
| 496 | - // Lien |
|
| 497 | - $balise = lien_ou_expose($url, $libelle, false, $classe); |
|
| 498 | - |
|
| 499 | - return $balise; |
|
| 434 | + $url = self('&'); |
|
| 435 | + $tri_sens = (int) $tri_sens; |
|
| 436 | + $alias_sens = [ |
|
| 437 | + '<' => -1, |
|
| 438 | + '>' => 1, |
|
| 439 | + 'inverse' => -1, |
|
| 440 | + ]; |
|
| 441 | + |
|
| 442 | + // Normaliser la liste des sens de tri par défaut |
|
| 443 | + // On ajoute un jocker pour les champs non présents dans la liste |
|
| 444 | + // avec la valeur du 1er item de la liste, idem critère {tri} |
|
| 445 | + if (is_array($liste_tri_sens_defaut)) { |
|
| 446 | + $liste_tri_sens_defaut['*'] = array_values($liste_tri_sens_defaut)[0]; |
|
| 447 | + } else { |
|
| 448 | + $liste_tri_sens_defaut = [ |
|
| 449 | + '*' => (int) ($alias_sens[$liste_tri_sens_defaut] ?? $liste_tri_sens_defaut), |
|
| 450 | + ]; |
|
| 451 | + } |
|
| 452 | + |
|
| 453 | + // Les sens de tri actuel et nouveau : |
|
| 454 | + // Soit c'est un sens fixe donné en paramètre (< ou >) |
|
| 455 | + $is_sens_fixe = array_key_exists($champ_ou_sens, $alias_sens); |
|
| 456 | + if ($is_sens_fixe) { |
|
| 457 | + $tri_sens_actuel = $tri_sens; |
|
| 458 | + $tri_sens_nouveau = $alias_sens[$champ_ou_sens]; |
|
| 459 | + // Soit c'est le champ utilisé actuellement pour le tri → on inverse le sens |
|
| 460 | + } elseif ($champ_ou_sens === $tri_champ) { |
|
| 461 | + $tri_sens_actuel = $tri_sens; |
|
| 462 | + $tri_sens_nouveau = $tri_sens * -1; |
|
| 463 | + // Sinon c'est un nouveau champ, et on prend son tri par défaut |
|
| 464 | + } else { |
|
| 465 | + $tri_sens_actuel = $tri_sens_nouveau = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']); |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + // URL : ajouter le champ sur lequel porte le tri |
|
| 469 | + if (!$is_sens_fixe) { |
|
| 470 | + $param_tri = "tri$tri_nom"; |
|
| 471 | + $url = parametre_url($url, $param_tri, $champ_ou_sens); |
|
| 472 | + } |
|
| 473 | + |
|
| 474 | + // URL : n'ajouter le sens de tri que si nécessaire, |
|
| 475 | + // c.à.d différent du sens par défaut pour le champ |
|
| 476 | + $param_sens = "sens$tri_nom"; |
|
| 477 | + $tri_sens_defaut_champ = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']); |
|
| 478 | + if ($tri_sens_nouveau !== $tri_sens_defaut_champ) { |
|
| 479 | + $url = parametre_url($url, $param_sens, $tri_sens_nouveau); |
|
| 480 | + } else { |
|
| 481 | + $url = parametre_url($url, $param_sens, ''); |
|
| 482 | + } |
|
| 483 | + |
|
| 484 | + // Drapeau pour garder en session ? |
|
| 485 | + $param_memo = (!$is_sens_fixe ? $param_tri : $param_sens); |
|
| 486 | + $url = parametre_url($url, 'var_memotri', strncmp($tri_nom, 'session', 7) == 0 ? $param_memo : ''); |
|
| 487 | + |
|
| 488 | + // Classes : on indique le sens de tri et l'item exposé |
|
| 489 | + if (!$is_sens_fixe) { |
|
| 490 | + $classe .= ' item-tri item-tri_' . ($tri_sens_actuel === 1 ? 'asc' : 'desc'); |
|
| 491 | + } |
|
| 492 | + if ($champ_ou_sens === $tri_champ) { |
|
| 493 | + $classe .= ' item-tri_actif'; |
|
| 494 | + } |
|
| 495 | + |
|
| 496 | + // Lien |
|
| 497 | + $balise = lien_ou_expose($url, $libelle, false, $classe); |
|
| 498 | + |
|
| 499 | + return $balise; |
|
| 500 | 500 | } |
| 501 | 501 | |
| 502 | 502 | |
@@ -512,7 +512,7 @@ discard block |
||
| 512 | 512 | * @return string |
| 513 | 513 | */ |
| 514 | 514 | function tri_protege_champ($t) { |
| 515 | - return preg_replace(',[^\s\w.+\[\]],', '', $t); |
|
| 515 | + return preg_replace(',[^\s\w.+\[\]],', '', $t); |
|
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 | /** |
@@ -525,43 +525,43 @@ discard block |
||
| 525 | 525 | * @return string |
| 526 | 526 | */ |
| 527 | 527 | function tri_champ_order($t, $from = null, $senstri = '') { |
| 528 | - if (strncmp($t, 'multi ', 6) == 0) { |
|
| 529 | - return 'multi' . $senstri; |
|
| 530 | - } |
|
| 531 | - |
|
| 532 | - $champ = $t; |
|
| 533 | - |
|
| 534 | - $prefixe = ''; |
|
| 535 | - foreach (['num ', 'sinum '] as $p) { |
|
| 536 | - if (strpos($t, $p) === 0) { |
|
| 537 | - $champ = substr($t, strlen($p)); |
|
| 538 | - $prefixe = $p; |
|
| 539 | - } |
|
| 540 | - } |
|
| 541 | - |
|
| 542 | - // enlever les autres espaces non evacues par tri_protege_champ |
|
| 543 | - $champ = preg_replace(',\s,', '', $champ); |
|
| 544 | - |
|
| 545 | - if (is_array($from)) { |
|
| 546 | - $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 547 | - foreach ($from as $idt => $table_sql) { |
|
| 548 | - if ( |
|
| 549 | - $desc = $trouver_table($table_sql) |
|
| 550 | - and isset($desc['field'][$champ]) |
|
| 551 | - ) { |
|
| 552 | - $champ = "$idt.$champ"; |
|
| 553 | - break; |
|
| 554 | - } |
|
| 555 | - } |
|
| 556 | - } |
|
| 557 | - switch ($prefixe) { |
|
| 558 | - case 'num ': |
|
| 559 | - return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}, 0+$champ{$senstri}"; |
|
| 560 | - case 'sinum ': |
|
| 561 | - return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}"; |
|
| 562 | - default: |
|
| 563 | - return $champ . $senstri; |
|
| 564 | - } |
|
| 528 | + if (strncmp($t, 'multi ', 6) == 0) { |
|
| 529 | + return 'multi' . $senstri; |
|
| 530 | + } |
|
| 531 | + |
|
| 532 | + $champ = $t; |
|
| 533 | + |
|
| 534 | + $prefixe = ''; |
|
| 535 | + foreach (['num ', 'sinum '] as $p) { |
|
| 536 | + if (strpos($t, $p) === 0) { |
|
| 537 | + $champ = substr($t, strlen($p)); |
|
| 538 | + $prefixe = $p; |
|
| 539 | + } |
|
| 540 | + } |
|
| 541 | + |
|
| 542 | + // enlever les autres espaces non evacues par tri_protege_champ |
|
| 543 | + $champ = preg_replace(',\s,', '', $champ); |
|
| 544 | + |
|
| 545 | + if (is_array($from)) { |
|
| 546 | + $trouver_table = charger_fonction('trouver_table', 'base'); |
|
| 547 | + foreach ($from as $idt => $table_sql) { |
|
| 548 | + if ( |
|
| 549 | + $desc = $trouver_table($table_sql) |
|
| 550 | + and isset($desc['field'][$champ]) |
|
| 551 | + ) { |
|
| 552 | + $champ = "$idt.$champ"; |
|
| 553 | + break; |
|
| 554 | + } |
|
| 555 | + } |
|
| 556 | + } |
|
| 557 | + switch ($prefixe) { |
|
| 558 | + case 'num ': |
|
| 559 | + return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}, 0+$champ{$senstri}"; |
|
| 560 | + case 'sinum ': |
|
| 561 | + return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}"; |
|
| 562 | + default: |
|
| 563 | + return $champ . $senstri; |
|
| 564 | + } |
|
| 565 | 565 | } |
| 566 | 566 | |
| 567 | 567 | /** |
@@ -575,18 +575,18 @@ discard block |
||
| 575 | 575 | * @return string |
| 576 | 576 | */ |
| 577 | 577 | function tri_champ_select($t) { |
| 578 | - if (strncmp($t, 'multi ', 6) == 0) { |
|
| 579 | - $t = substr($t, 6); |
|
| 580 | - $t = preg_replace(',\s,', '', $t); |
|
| 581 | - $t = sql_multi($t, $GLOBALS['spip_lang']); |
|
| 582 | - |
|
| 583 | - return $t; |
|
| 584 | - } |
|
| 585 | - if (trim($t) == 'hasard') { |
|
| 586 | - return 'rand() AS hasard'; |
|
| 587 | - } |
|
| 588 | - |
|
| 589 | - return "''"; |
|
| 578 | + if (strncmp($t, 'multi ', 6) == 0) { |
|
| 579 | + $t = substr($t, 6); |
|
| 580 | + $t = preg_replace(',\s,', '', $t); |
|
| 581 | + $t = sql_multi($t, $GLOBALS['spip_lang']); |
|
| 582 | + |
|
| 583 | + return $t; |
|
| 584 | + } |
|
| 585 | + if (trim($t) == 'hasard') { |
|
| 586 | + return 'rand() AS hasard'; |
|
| 587 | + } |
|
| 588 | + |
|
| 589 | + return "''"; |
|
| 590 | 590 | } |
| 591 | 591 | |
| 592 | 592 | /** |
@@ -598,16 +598,16 @@ discard block |
||
| 598 | 598 | * @return string |
| 599 | 599 | */ |
| 600 | 600 | function formate_liste_critere_par_ordre_liste($valeurs, $serveur = '') { |
| 601 | - if (!is_array($valeurs)) { |
|
| 602 | - return ''; |
|
| 603 | - } |
|
| 604 | - $f = sql_serveur('quote', $serveur, true); |
|
| 605 | - if (!is_string($f) or !$f) { |
|
| 606 | - return ''; |
|
| 607 | - } |
|
| 608 | - $valeurs = implode(',', array_map($f, array_unique($valeurs))); |
|
| 609 | - |
|
| 610 | - return $valeurs; |
|
| 601 | + if (!is_array($valeurs)) { |
|
| 602 | + return ''; |
|
| 603 | + } |
|
| 604 | + $f = sql_serveur('quote', $serveur, true); |
|
| 605 | + if (!is_string($f) or !$f) { |
|
| 606 | + return ''; |
|
| 607 | + } |
|
| 608 | + $valeurs = implode(',', array_map($f, array_unique($valeurs))); |
|
| 609 | + |
|
| 610 | + return $valeurs; |
|
| 611 | 611 | } |
| 612 | 612 | |
| 613 | 613 | /** |
@@ -630,20 +630,20 @@ discard block |
||
| 630 | 630 | * Valeur $defaut sinon. |
| 631 | 631 | **/ |
| 632 | 632 | function appliquer_filtre_sinon($arg, $filtre, $args, $defaut = '') { |
| 633 | - // Si c'est un filtre d'image, on utilise image_filtrer() |
|
| 634 | - // Attention : les 2 premiers arguments sont inversés dans ce cas |
|
| 635 | - if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') { |
|
| 636 | - include_spip('inc/filtres_images_lib_mini'); |
|
| 637 | - $args[1] = $args[0]; |
|
| 638 | - $args[0] = $filtre; |
|
| 639 | - return image_graver(image_filtrer($args)); |
|
| 640 | - } |
|
| 641 | - |
|
| 642 | - $f = chercher_filtre($filtre); |
|
| 643 | - if (!$f) { |
|
| 644 | - return $defaut; |
|
| 645 | - } |
|
| 646 | - array_shift($args); // enlever $arg |
|
| 647 | - array_shift($args); // enlever $filtre |
|
| 648 | - return $f($arg, ...$args); |
|
| 633 | + // Si c'est un filtre d'image, on utilise image_filtrer() |
|
| 634 | + // Attention : les 2 premiers arguments sont inversés dans ce cas |
|
| 635 | + if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') { |
|
| 636 | + include_spip('inc/filtres_images_lib_mini'); |
|
| 637 | + $args[1] = $args[0]; |
|
| 638 | + $args[0] = $filtre; |
|
| 639 | + return image_graver(image_filtrer($args)); |
|
| 640 | + } |
|
| 641 | + |
|
| 642 | + $f = chercher_filtre($filtre); |
|
| 643 | + if (!$f) { |
|
| 644 | + return $defaut; |
|
| 645 | + } |
|
| 646 | + array_shift($args); // enlever $arg |
|
| 647 | + array_shift($args); // enlever $filtre |
|
| 648 | + return $f($arg, ...$args); |
|
| 649 | 649 | } |
@@ -30,7 +30,7 @@ discard block |
||
| 30 | 30 | * @package SPIP\Core\Drapeaux\Edition |
| 31 | 31 | **/ |
| 32 | 32 | if (!defined('_ECRIRE_INC_VERSION')) { |
| 33 | - return; |
|
| 33 | + return; |
|
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | |
@@ -45,46 +45,46 @@ discard block |
||
| 45 | 45 | * `[ type d'objet ][id_objet][id_auteur][nom de l'auteur] = time()` |
| 46 | 46 | **/ |
| 47 | 47 | function lire_tableau_edition() { |
| 48 | - $edition = @unserialize($GLOBALS['meta']['drapeau_edition']); |
|
| 49 | - if (!$edition) { |
|
| 50 | - return []; |
|
| 51 | - } |
|
| 52 | - $changed = false; |
|
| 48 | + $edition = @unserialize($GLOBALS['meta']['drapeau_edition']); |
|
| 49 | + if (!$edition) { |
|
| 50 | + return []; |
|
| 51 | + } |
|
| 52 | + $changed = false; |
|
| 53 | 53 | |
| 54 | - $bon_pour_le_service = time() - 3600; |
|
| 55 | - // parcourir le tableau et virer les vieux |
|
| 56 | - foreach ($edition as $objet => $data) { |
|
| 57 | - if (!is_array($data)) { |
|
| 58 | - unset($edition[$objet]); |
|
| 59 | - } // vieille version |
|
| 60 | - else { |
|
| 61 | - foreach ($data as $id => $tab) { |
|
| 62 | - if (!is_array($tab)) { |
|
| 63 | - unset($edition[$objet][$tab]); |
|
| 64 | - } // vieille version |
|
| 65 | - else { |
|
| 66 | - foreach ($tab as $n => $duo) { |
|
| 67 | - if (current($duo) < $bon_pour_le_service) { |
|
| 68 | - unset($edition[$objet][$id][$n]); |
|
| 69 | - $changed = true; |
|
| 70 | - } |
|
| 71 | - } |
|
| 72 | - } |
|
| 73 | - if (!$edition[$objet][$id]) { |
|
| 74 | - unset($edition[$objet][$id]); |
|
| 75 | - } |
|
| 76 | - } |
|
| 77 | - } |
|
| 78 | - if (!$edition[$objet]) { |
|
| 79 | - unset($edition[$objet]); |
|
| 80 | - } |
|
| 81 | - } |
|
| 54 | + $bon_pour_le_service = time() - 3600; |
|
| 55 | + // parcourir le tableau et virer les vieux |
|
| 56 | + foreach ($edition as $objet => $data) { |
|
| 57 | + if (!is_array($data)) { |
|
| 58 | + unset($edition[$objet]); |
|
| 59 | + } // vieille version |
|
| 60 | + else { |
|
| 61 | + foreach ($data as $id => $tab) { |
|
| 62 | + if (!is_array($tab)) { |
|
| 63 | + unset($edition[$objet][$tab]); |
|
| 64 | + } // vieille version |
|
| 65 | + else { |
|
| 66 | + foreach ($tab as $n => $duo) { |
|
| 67 | + if (current($duo) < $bon_pour_le_service) { |
|
| 68 | + unset($edition[$objet][$id][$n]); |
|
| 69 | + $changed = true; |
|
| 70 | + } |
|
| 71 | + } |
|
| 72 | + } |
|
| 73 | + if (!$edition[$objet][$id]) { |
|
| 74 | + unset($edition[$objet][$id]); |
|
| 75 | + } |
|
| 76 | + } |
|
| 77 | + } |
|
| 78 | + if (!$edition[$objet]) { |
|
| 79 | + unset($edition[$objet]); |
|
| 80 | + } |
|
| 81 | + } |
|
| 82 | 82 | |
| 83 | - if ($changed) { |
|
| 84 | - ecrire_tableau_edition($edition); |
|
| 85 | - } |
|
| 83 | + if ($changed) { |
|
| 84 | + ecrire_tableau_edition($edition); |
|
| 85 | + } |
|
| 86 | 86 | |
| 87 | - return $edition; |
|
| 87 | + return $edition; |
|
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | /** |
@@ -97,7 +97,7 @@ discard block |
||
| 97 | 97 | * `[ type d'objet ][id_objet][id_auteur][nom de l'auteur] = time()` |
| 98 | 98 | **/ |
| 99 | 99 | function ecrire_tableau_edition($edition) { |
| 100 | - ecrire_meta('drapeau_edition', serialize($edition)); |
|
| 100 | + ecrire_meta('drapeau_edition', serialize($edition)); |
|
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | /** |
@@ -117,22 +117,22 @@ discard block |
||
| 117 | 117 | * Type d'objet édité |
| 118 | 118 | */ |
| 119 | 119 | function signale_edition($id, $auteur, $type = 'article') { |
| 120 | - include_spip('base/objets'); |
|
| 121 | - include_spip('inc/filtres'); |
|
| 122 | - if (objet_info($type, 'editable') !== 'oui') { |
|
| 123 | - return; |
|
| 124 | - } |
|
| 120 | + include_spip('base/objets'); |
|
| 121 | + include_spip('inc/filtres'); |
|
| 122 | + if (objet_info($type, 'editable') !== 'oui') { |
|
| 123 | + return; |
|
| 124 | + } |
|
| 125 | 125 | |
| 126 | - $edition = lire_tableau_edition(); |
|
| 126 | + $edition = lire_tableau_edition(); |
|
| 127 | 127 | |
| 128 | - $nom = $auteur['nom'] ?? $GLOBALS['ip']; |
|
| 129 | - $id_a = $auteur['id_auteur'] ?? $GLOBALS['ip']; |
|
| 128 | + $nom = $auteur['nom'] ?? $GLOBALS['ip']; |
|
| 129 | + $id_a = $auteur['id_auteur'] ?? $GLOBALS['ip']; |
|
| 130 | 130 | |
| 131 | - if (!isset($edition[$type][$id]) or !is_array($edition[$type][$id])) { |
|
| 132 | - $edition[$type][$id] = []; |
|
| 133 | - } |
|
| 134 | - $edition[$type][$id][$id_a][$nom] = time(); |
|
| 135 | - ecrire_tableau_edition($edition); |
|
| 131 | + if (!isset($edition[$type][$id]) or !is_array($edition[$type][$id])) { |
|
| 132 | + $edition[$type][$id] = []; |
|
| 133 | + } |
|
| 134 | + $edition[$type][$id][$id_a][$nom] = time(); |
|
| 135 | + ecrire_tableau_edition($edition); |
|
| 136 | 136 | } |
| 137 | 137 | |
| 138 | 138 | /** |
@@ -149,9 +149,9 @@ discard block |
||
| 149 | 149 | */ |
| 150 | 150 | function qui_edite($id, $type = 'article') { |
| 151 | 151 | |
| 152 | - $edition = lire_tableau_edition(); |
|
| 152 | + $edition = lire_tableau_edition(); |
|
| 153 | 153 | |
| 154 | - return empty($edition[$type][$id]) ? [] : $edition[$type][$id]; |
|
| 154 | + return empty($edition[$type][$id]) ? [] : $edition[$type][$id]; |
|
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | /** |
@@ -165,23 +165,23 @@ discard block |
||
| 165 | 165 | * Liste de tableaux `['nom_auteur_modif' => x|y|z, 'date_diff' => n]` |
| 166 | 166 | */ |
| 167 | 167 | function mention_qui_edite($id, $type = 'article'): array { |
| 168 | - $modif = qui_edite($id, $type); |
|
| 169 | - unset($modif[$GLOBALS['visiteur_session']['id_auteur']]); |
|
| 168 | + $modif = qui_edite($id, $type); |
|
| 169 | + unset($modif[$GLOBALS['visiteur_session']['id_auteur']]); |
|
| 170 | 170 | |
| 171 | - if ($modif) { |
|
| 172 | - $quand = 0; |
|
| 173 | - foreach ($modif as $duo) { |
|
| 174 | - $auteurs[] = typo(key($duo)); |
|
| 175 | - $quand = max($quand, current($duo)); |
|
| 176 | - } |
|
| 171 | + if ($modif) { |
|
| 172 | + $quand = 0; |
|
| 173 | + foreach ($modif as $duo) { |
|
| 174 | + $auteurs[] = typo(key($duo)); |
|
| 175 | + $quand = max($quand, current($duo)); |
|
| 176 | + } |
|
| 177 | 177 | |
| 178 | - // format lie a la chaine de langue 'avis_article_modifie' |
|
| 179 | - return [ |
|
| 180 | - 'nom_auteur_modif' => join(' | ', $auteurs), |
|
| 181 | - 'date_diff' => ceil((time() - $quand) / 60) |
|
| 182 | - ]; |
|
| 183 | - } |
|
| 184 | - return []; |
|
| 178 | + // format lie a la chaine de langue 'avis_article_modifie' |
|
| 179 | + return [ |
|
| 180 | + 'nom_auteur_modif' => join(' | ', $auteurs), |
|
| 181 | + 'date_diff' => ceil((time() - $quand) / 60) |
|
| 182 | + ]; |
|
| 183 | + } |
|
| 184 | + return []; |
|
| 185 | 185 | } |
| 186 | 186 | |
| 187 | 187 | /** |
@@ -195,25 +195,25 @@ discard block |
||
| 195 | 195 | * Liste de tableaux `['objet' => x, 'id_objet' => n]` |
| 196 | 196 | */ |
| 197 | 197 | function liste_drapeau_edition($id_auteur) { |
| 198 | - $edition = lire_tableau_edition(); |
|
| 199 | - $objets_ouverts = []; |
|
| 198 | + $edition = lire_tableau_edition(); |
|
| 199 | + $objets_ouverts = []; |
|
| 200 | 200 | |
| 201 | - foreach ($edition as $objet => $data) { |
|
| 202 | - foreach ($data as $id => $auteurs) { |
|
| 203 | - if ( |
|
| 204 | - isset($auteurs[$id_auteur]) |
|
| 205 | - and is_array($auteurs[$id_auteur]) // precaution |
|
| 206 | - and (array_pop($auteurs[$id_auteur]) > time() - 3600) |
|
| 207 | - ) { |
|
| 208 | - $objets_ouverts[] = [ |
|
| 209 | - 'objet' => $objet, |
|
| 210 | - 'id_objet' => $id, |
|
| 211 | - ]; |
|
| 212 | - } |
|
| 213 | - } |
|
| 214 | - } |
|
| 201 | + foreach ($edition as $objet => $data) { |
|
| 202 | + foreach ($data as $id => $auteurs) { |
|
| 203 | + if ( |
|
| 204 | + isset($auteurs[$id_auteur]) |
|
| 205 | + and is_array($auteurs[$id_auteur]) // precaution |
|
| 206 | + and (array_pop($auteurs[$id_auteur]) > time() - 3600) |
|
| 207 | + ) { |
|
| 208 | + $objets_ouverts[] = [ |
|
| 209 | + 'objet' => $objet, |
|
| 210 | + 'id_objet' => $id, |
|
| 211 | + ]; |
|
| 212 | + } |
|
| 213 | + } |
|
| 214 | + } |
|
| 215 | 215 | |
| 216 | - return $objets_ouverts; |
|
| 216 | + return $objets_ouverts; |
|
| 217 | 217 | } |
| 218 | 218 | |
| 219 | 219 | /** |
@@ -226,15 +226,15 @@ discard block |
||
| 226 | 226 | * @return void |
| 227 | 227 | */ |
| 228 | 228 | function debloquer_tous($id_auteur) { |
| 229 | - $edition = lire_tableau_edition(); |
|
| 230 | - foreach ($edition as $objet => $data) { |
|
| 231 | - foreach ($data as $id => $auteurs) { |
|
| 232 | - if (isset($auteurs[$id_auteur])) { |
|
| 233 | - unset($edition[$objet][$id][$id_auteur]); |
|
| 234 | - ecrire_tableau_edition($edition); |
|
| 235 | - } |
|
| 236 | - } |
|
| 237 | - } |
|
| 229 | + $edition = lire_tableau_edition(); |
|
| 230 | + foreach ($edition as $objet => $data) { |
|
| 231 | + foreach ($data as $id => $auteurs) { |
|
| 232 | + if (isset($auteurs[$id_auteur])) { |
|
| 233 | + unset($edition[$objet][$id][$id_auteur]); |
|
| 234 | + ecrire_tableau_edition($edition); |
|
| 235 | + } |
|
| 236 | + } |
|
| 237 | + } |
|
| 238 | 238 | } |
| 239 | 239 | |
| 240 | 240 | /** |
@@ -252,19 +252,19 @@ discard block |
||
| 252 | 252 | * @return void |
| 253 | 253 | */ |
| 254 | 254 | function debloquer_edition($id_auteur, $id_objet, $type = 'article') { |
| 255 | - $edition = lire_tableau_edition(); |
|
| 255 | + $edition = lire_tableau_edition(); |
|
| 256 | 256 | |
| 257 | - foreach ($edition as $objet => $data) { |
|
| 258 | - if ($objet == $type) { |
|
| 259 | - foreach ($data as $id => $auteurs) { |
|
| 260 | - if ( |
|
| 261 | - $id == $id_objet |
|
| 262 | - and isset($auteurs[$id_auteur]) |
|
| 263 | - ) { |
|
| 264 | - unset($edition[$objet][$id][$id_auteur]); |
|
| 265 | - ecrire_tableau_edition($edition); |
|
| 266 | - } |
|
| 267 | - } |
|
| 268 | - } |
|
| 269 | - } |
|
| 257 | + foreach ($edition as $objet => $data) { |
|
| 258 | + if ($objet == $type) { |
|
| 259 | + foreach ($data as $id => $auteurs) { |
|
| 260 | + if ( |
|
| 261 | + $id == $id_objet |
|
| 262 | + and isset($auteurs[$id_auteur]) |
|
| 263 | + ) { |
|
| 264 | + unset($edition[$objet][$id][$id_auteur]); |
|
| 265 | + ecrire_tableau_edition($edition); |
|
| 266 | + } |
|
| 267 | + } |
|
| 268 | + } |
|
| 269 | + } |
|
| 270 | 270 | } |
@@ -15,11 +15,11 @@ discard block |
||
| 15 | 15 | * Test utilisateur |
| 16 | 16 | */ |
| 17 | 17 | if (isset($_GET['test_ecran_securite'])) { |
| 18 | - $ecran_securite_raison = 'test ' . _ECRAN_SECURITE; |
|
| 18 | + $ecran_securite_raison = 'test ' . _ECRAN_SECURITE; |
|
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | if (file_exists($f = __DIR__ . DIRECTORY_SEPARATOR . 'ecran_securite_options.php')) { |
| 22 | - include ($f); |
|
| 22 | + include ($f); |
|
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | /* |
@@ -29,222 +29,222 @@ discard block |
||
| 29 | 29 | * le load depasse ECRAN_SECURITE_LOAD) |
| 30 | 30 | */ |
| 31 | 31 | if (!defined('_IS_BOT') and isset($_GET['var_isbot'])) { |
| 32 | - define('_IS_BOT', $_GET['var_isbot'] ? true : false); |
|
| 32 | + define('_IS_BOT', $_GET['var_isbot'] ? true : false); |
|
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | /* |
| 36 | 36 | * Détecteur de robot d'indexation |
| 37 | 37 | */ |
| 38 | 38 | if (!defined('_IS_BOT')) { |
| 39 | - define( |
|
| 40 | - '_IS_BOT', |
|
| 41 | - isset($_SERVER['HTTP_USER_AGENT']) |
|
| 42 | - and preg_match( |
|
| 43 | - ',' |
|
| 44 | - . implode('|', array( |
|
| 45 | - // mots generiques |
|
| 46 | - 'bot', |
|
| 47 | - 'slurp', |
|
| 48 | - 'crawler', |
|
| 49 | - 'crwlr', |
|
| 50 | - 'java', |
|
| 51 | - 'monitoring', |
|
| 52 | - 'spider', |
|
| 53 | - 'webvac', |
|
| 54 | - 'yandex', |
|
| 55 | - 'MSIE 6\.0', // botnet 99,9% du temps |
|
| 56 | - // UA plus cibles |
|
| 57 | - '200please', |
|
| 58 | - '80legs', |
|
| 59 | - 'a6-indexer', |
|
| 60 | - 'aboundex', |
|
| 61 | - 'accoona', |
|
| 62 | - 'acrylicapps', |
|
| 63 | - 'addthis', |
|
| 64 | - 'adressendeutschland', |
|
| 65 | - 'alexa', |
|
| 66 | - 'altavista', |
|
| 67 | - 'analyticsseo', |
|
| 68 | - 'antennapod', |
|
| 69 | - 'arachnys', |
|
| 70 | - 'archive', |
|
| 71 | - 'argclrint', |
|
| 72 | - 'aspseek', |
|
| 73 | - 'baidu', |
|
| 74 | - 'begunadvertising', |
|
| 75 | - 'bing', |
|
| 76 | - 'bloglines', |
|
| 77 | - 'buck', |
|
| 78 | - 'browsershots', |
|
| 79 | - 'bubing', |
|
| 80 | - 'butterfly', |
|
| 81 | - 'changedetection', |
|
| 82 | - 'charlotte', |
|
| 83 | - 'chilkat', |
|
| 84 | - 'china', |
|
| 85 | - 'coccoc', |
|
| 86 | - 'crowsnest', |
|
| 87 | - 'dataminr', |
|
| 88 | - 'daumoa', |
|
| 89 | - 'dlvr\.it', |
|
| 90 | - 'dlweb', |
|
| 91 | - 'drupal', |
|
| 92 | - 'ec2linkfinder', |
|
| 93 | - 'eset\.com', |
|
| 94 | - 'estyle', |
|
| 95 | - 'exalead', |
|
| 96 | - 'ezooms', |
|
| 97 | - 'facebookexternalhit', |
|
| 98 | - 'facebookplatform', |
|
| 99 | - 'fairshare', |
|
| 100 | - 'feedfetcher', |
|
| 101 | - 'feedfetcher-google', |
|
| 102 | - 'feedly', |
|
| 103 | - 'fetch', |
|
| 104 | - 'flipboardproxy', |
|
| 105 | - 'genieo', |
|
| 106 | - 'google', |
|
| 107 | - 'go-http-client', |
|
| 108 | - 'grapeshot', |
|
| 109 | - 'hatena-useragent', |
|
| 110 | - 'head', |
|
| 111 | - 'hosttracker', |
|
| 112 | - 'hubspot', |
|
| 113 | - 'ia_archiver', |
|
| 114 | - 'ichiro', |
|
| 115 | - 'iltrovatore-setaccio', |
|
| 116 | - 'immediatenet', |
|
| 117 | - 'ina', |
|
| 118 | - 'inoreader', |
|
| 119 | - 'infegyatlas', |
|
| 120 | - 'infohelfer', |
|
| 121 | - 'instapaper', |
|
| 122 | - 'jabse', |
|
| 123 | - 'james', |
|
| 124 | - 'jersey', |
|
| 125 | - 'kumkie', |
|
| 126 | - 'linkdex', |
|
| 127 | - 'linkfluence', |
|
| 128 | - 'linkwalker', |
|
| 129 | - 'litefinder', |
|
| 130 | - 'loadimpactpageanalyzer', |
|
| 131 | - 'ltx71', |
|
| 132 | - 'luminate', |
|
| 133 | - 'lycos', |
|
| 134 | - 'lycosa', |
|
| 135 | - 'mediapartners-google', |
|
| 136 | - 'msai', |
|
| 137 | - 'myapp', |
|
| 138 | - 'nativehost', |
|
| 139 | - 'najdi', |
|
| 140 | - 'netcraftsurveyagent', |
|
| 141 | - 'netestate', |
|
| 142 | - 'netseer', |
|
| 143 | - 'netnewswire', |
|
| 144 | - 'newspaper', |
|
| 145 | - 'newsblur', |
|
| 146 | - 'nuhk', |
|
| 147 | - 'nuzzel', |
|
| 148 | - 'okhttp', |
|
| 149 | - 'otmedia', |
|
| 150 | - 'owlin', |
|
| 151 | - 'owncloud', |
|
| 152 | - 'panscient', |
|
| 153 | - 'paper\.li', |
|
| 154 | - 'parsijoo', |
|
| 155 | - 'protopage', |
|
| 156 | - 'plukkie', |
|
| 157 | - 'proximic', |
|
| 158 | - 'pubsub', |
|
| 159 | - 'python', |
|
| 160 | - 'qirina', |
|
| 161 | - 'qoshe', |
|
| 162 | - 'qualidator', |
|
| 163 | - 'qwantify', |
|
| 164 | - 'rambler', |
|
| 165 | - 'readability', |
|
| 166 | - 'ruby', |
|
| 167 | - 'sbsearch', |
|
| 168 | - 'scoop\.it', |
|
| 169 | - 'scooter', |
|
| 170 | - 'scoutjet', |
|
| 171 | - 'scrapy', |
|
| 172 | - 'scrubby', |
|
| 173 | - 'scrubbybloglines', |
|
| 174 | - 'shareaholic', |
|
| 175 | - 'shopwiki', |
|
| 176 | - 'simplepie', |
|
| 177 | - 'sistrix', |
|
| 178 | - 'sitechecker', |
|
| 179 | - 'siteexplorer', |
|
| 180 | - 'snapshot', |
|
| 181 | - 'sogou', |
|
| 182 | - 'special_archiver', |
|
| 183 | - 'speedy', |
|
| 184 | - 'spinn3r', |
|
| 185 | - 'spreadtrum', |
|
| 186 | - 'steeler', |
|
| 187 | - 'subscriber', |
|
| 188 | - 'suma', |
|
| 189 | - 'superdownloads', |
|
| 190 | - 'svenska-webbsido', |
|
| 191 | - 'teoma', |
|
| 192 | - 'the knowledge AI', |
|
| 193 | - 'thumbshots', |
|
| 194 | - 'tineye', |
|
| 195 | - 'traackr', |
|
| 196 | - 'trendiction', |
|
| 197 | - 'trendsmap', |
|
| 198 | - 'tweetedtimes', |
|
| 199 | - 'tweetmeme', |
|
| 200 | - 'universalfeedparser', |
|
| 201 | - 'uaslinkchecker', |
|
| 202 | - 'undrip', |
|
| 203 | - 'unwindfetchor', |
|
| 204 | - 'upday', |
|
| 205 | - 'vedma', |
|
| 206 | - 'vkshare', |
|
| 207 | - 'vm', |
|
| 208 | - 'wch', |
|
| 209 | - 'webalta', |
|
| 210 | - 'webcookies', |
|
| 211 | - 'webparser', |
|
| 212 | - 'webthumbnail', |
|
| 213 | - 'wesee', |
|
| 214 | - 'wise-guys', |
|
| 215 | - 'woko', |
|
| 216 | - 'wordpress', |
|
| 217 | - 'wotbox', |
|
| 218 | - 'y!j-bri', |
|
| 219 | - 'y!j-bro', |
|
| 220 | - 'y!j-brw', |
|
| 221 | - 'y!j-bsc', |
|
| 222 | - 'yahoo', |
|
| 223 | - 'yahoo!', |
|
| 224 | - 'yahooysmcm', |
|
| 225 | - 'ymobactus', |
|
| 226 | - 'yats', |
|
| 227 | - 'yeti', |
|
| 228 | - 'zeerch' |
|
| 229 | - )) . ',i', |
|
| 230 | - (string)$_SERVER['HTTP_USER_AGENT'] |
|
| 231 | - ) |
|
| 232 | - ); |
|
| 39 | + define( |
|
| 40 | + '_IS_BOT', |
|
| 41 | + isset($_SERVER['HTTP_USER_AGENT']) |
|
| 42 | + and preg_match( |
|
| 43 | + ',' |
|
| 44 | + . implode('|', array( |
|
| 45 | + // mots generiques |
|
| 46 | + 'bot', |
|
| 47 | + 'slurp', |
|
| 48 | + 'crawler', |
|
| 49 | + 'crwlr', |
|
| 50 | + 'java', |
|
| 51 | + 'monitoring', |
|
| 52 | + 'spider', |
|
| 53 | + 'webvac', |
|
| 54 | + 'yandex', |
|
| 55 | + 'MSIE 6\.0', // botnet 99,9% du temps |
|
| 56 | + // UA plus cibles |
|
| 57 | + '200please', |
|
| 58 | + '80legs', |
|
| 59 | + 'a6-indexer', |
|
| 60 | + 'aboundex', |
|
| 61 | + 'accoona', |
|
| 62 | + 'acrylicapps', |
|
| 63 | + 'addthis', |
|
| 64 | + 'adressendeutschland', |
|
| 65 | + 'alexa', |
|
| 66 | + 'altavista', |
|
| 67 | + 'analyticsseo', |
|
| 68 | + 'antennapod', |
|
| 69 | + 'arachnys', |
|
| 70 | + 'archive', |
|
| 71 | + 'argclrint', |
|
| 72 | + 'aspseek', |
|
| 73 | + 'baidu', |
|
| 74 | + 'begunadvertising', |
|
| 75 | + 'bing', |
|
| 76 | + 'bloglines', |
|
| 77 | + 'buck', |
|
| 78 | + 'browsershots', |
|
| 79 | + 'bubing', |
|
| 80 | + 'butterfly', |
|
| 81 | + 'changedetection', |
|
| 82 | + 'charlotte', |
|
| 83 | + 'chilkat', |
|
| 84 | + 'china', |
|
| 85 | + 'coccoc', |
|
| 86 | + 'crowsnest', |
|
| 87 | + 'dataminr', |
|
| 88 | + 'daumoa', |
|
| 89 | + 'dlvr\.it', |
|
| 90 | + 'dlweb', |
|
| 91 | + 'drupal', |
|
| 92 | + 'ec2linkfinder', |
|
| 93 | + 'eset\.com', |
|
| 94 | + 'estyle', |
|
| 95 | + 'exalead', |
|
| 96 | + 'ezooms', |
|
| 97 | + 'facebookexternalhit', |
|
| 98 | + 'facebookplatform', |
|
| 99 | + 'fairshare', |
|
| 100 | + 'feedfetcher', |
|
| 101 | + 'feedfetcher-google', |
|
| 102 | + 'feedly', |
|
| 103 | + 'fetch', |
|
| 104 | + 'flipboardproxy', |
|
| 105 | + 'genieo', |
|
| 106 | + 'google', |
|
| 107 | + 'go-http-client', |
|
| 108 | + 'grapeshot', |
|
| 109 | + 'hatena-useragent', |
|
| 110 | + 'head', |
|
| 111 | + 'hosttracker', |
|
| 112 | + 'hubspot', |
|
| 113 | + 'ia_archiver', |
|
| 114 | + 'ichiro', |
|
| 115 | + 'iltrovatore-setaccio', |
|
| 116 | + 'immediatenet', |
|
| 117 | + 'ina', |
|
| 118 | + 'inoreader', |
|
| 119 | + 'infegyatlas', |
|
| 120 | + 'infohelfer', |
|
| 121 | + 'instapaper', |
|
| 122 | + 'jabse', |
|
| 123 | + 'james', |
|
| 124 | + 'jersey', |
|
| 125 | + 'kumkie', |
|
| 126 | + 'linkdex', |
|
| 127 | + 'linkfluence', |
|
| 128 | + 'linkwalker', |
|
| 129 | + 'litefinder', |
|
| 130 | + 'loadimpactpageanalyzer', |
|
| 131 | + 'ltx71', |
|
| 132 | + 'luminate', |
|
| 133 | + 'lycos', |
|
| 134 | + 'lycosa', |
|
| 135 | + 'mediapartners-google', |
|
| 136 | + 'msai', |
|
| 137 | + 'myapp', |
|
| 138 | + 'nativehost', |
|
| 139 | + 'najdi', |
|
| 140 | + 'netcraftsurveyagent', |
|
| 141 | + 'netestate', |
|
| 142 | + 'netseer', |
|
| 143 | + 'netnewswire', |
|
| 144 | + 'newspaper', |
|
| 145 | + 'newsblur', |
|
| 146 | + 'nuhk', |
|
| 147 | + 'nuzzel', |
|
| 148 | + 'okhttp', |
|
| 149 | + 'otmedia', |
|
| 150 | + 'owlin', |
|
| 151 | + 'owncloud', |
|
| 152 | + 'panscient', |
|
| 153 | + 'paper\.li', |
|
| 154 | + 'parsijoo', |
|
| 155 | + 'protopage', |
|
| 156 | + 'plukkie', |
|
| 157 | + 'proximic', |
|
| 158 | + 'pubsub', |
|
| 159 | + 'python', |
|
| 160 | + 'qirina', |
|
| 161 | + 'qoshe', |
|
| 162 | + 'qualidator', |
|
| 163 | + 'qwantify', |
|
| 164 | + 'rambler', |
|
| 165 | + 'readability', |
|
| 166 | + 'ruby', |
|
| 167 | + 'sbsearch', |
|
| 168 | + 'scoop\.it', |
|
| 169 | + 'scooter', |
|
| 170 | + 'scoutjet', |
|
| 171 | + 'scrapy', |
|
| 172 | + 'scrubby', |
|
| 173 | + 'scrubbybloglines', |
|
| 174 | + 'shareaholic', |
|
| 175 | + 'shopwiki', |
|
| 176 | + 'simplepie', |
|
| 177 | + 'sistrix', |
|
| 178 | + 'sitechecker', |
|
| 179 | + 'siteexplorer', |
|
| 180 | + 'snapshot', |
|
| 181 | + 'sogou', |
|
| 182 | + 'special_archiver', |
|
| 183 | + 'speedy', |
|
| 184 | + 'spinn3r', |
|
| 185 | + 'spreadtrum', |
|
| 186 | + 'steeler', |
|
| 187 | + 'subscriber', |
|
| 188 | + 'suma', |
|
| 189 | + 'superdownloads', |
|
| 190 | + 'svenska-webbsido', |
|
| 191 | + 'teoma', |
|
| 192 | + 'the knowledge AI', |
|
| 193 | + 'thumbshots', |
|
| 194 | + 'tineye', |
|
| 195 | + 'traackr', |
|
| 196 | + 'trendiction', |
|
| 197 | + 'trendsmap', |
|
| 198 | + 'tweetedtimes', |
|
| 199 | + 'tweetmeme', |
|
| 200 | + 'universalfeedparser', |
|
| 201 | + 'uaslinkchecker', |
|
| 202 | + 'undrip', |
|
| 203 | + 'unwindfetchor', |
|
| 204 | + 'upday', |
|
| 205 | + 'vedma', |
|
| 206 | + 'vkshare', |
|
| 207 | + 'vm', |
|
| 208 | + 'wch', |
|
| 209 | + 'webalta', |
|
| 210 | + 'webcookies', |
|
| 211 | + 'webparser', |
|
| 212 | + 'webthumbnail', |
|
| 213 | + 'wesee', |
|
| 214 | + 'wise-guys', |
|
| 215 | + 'woko', |
|
| 216 | + 'wordpress', |
|
| 217 | + 'wotbox', |
|
| 218 | + 'y!j-bri', |
|
| 219 | + 'y!j-bro', |
|
| 220 | + 'y!j-brw', |
|
| 221 | + 'y!j-bsc', |
|
| 222 | + 'yahoo', |
|
| 223 | + 'yahoo!', |
|
| 224 | + 'yahooysmcm', |
|
| 225 | + 'ymobactus', |
|
| 226 | + 'yats', |
|
| 227 | + 'yeti', |
|
| 228 | + 'zeerch' |
|
| 229 | + )) . ',i', |
|
| 230 | + (string)$_SERVER['HTTP_USER_AGENT'] |
|
| 231 | + ) |
|
| 232 | + ); |
|
| 233 | 233 | } |
| 234 | 234 | if (!defined('_IS_BOT_FRIEND')) { |
| 235 | - define( |
|
| 236 | - '_IS_BOT_FRIEND', |
|
| 237 | - isset($_SERVER['HTTP_USER_AGENT']) |
|
| 238 | - and preg_match( |
|
| 239 | - ',' . implode('|', array( |
|
| 240 | - 'facebookexternalhit', |
|
| 241 | - 'twitterbot', |
|
| 242 | - 'flipboardproxy', |
|
| 243 | - 'wordpress' |
|
| 244 | - )) . ',i', |
|
| 245 | - (string)$_SERVER['HTTP_USER_AGENT'] |
|
| 246 | - ) |
|
| 247 | - ); |
|
| 235 | + define( |
|
| 236 | + '_IS_BOT_FRIEND', |
|
| 237 | + isset($_SERVER['HTTP_USER_AGENT']) |
|
| 238 | + and preg_match( |
|
| 239 | + ',' . implode('|', array( |
|
| 240 | + 'facebookexternalhit', |
|
| 241 | + 'twitterbot', |
|
| 242 | + 'flipboardproxy', |
|
| 243 | + 'wordpress' |
|
| 244 | + )) . ',i', |
|
| 245 | + (string)$_SERVER['HTTP_USER_AGENT'] |
|
| 246 | + ) |
|
| 247 | + ); |
|
| 248 | 248 | } |
| 249 | 249 | |
| 250 | 250 | /* |
@@ -256,28 +256,28 @@ discard block |
||
| 256 | 256 | */ |
| 257 | 257 | $_exceptions = array('id_table', 'id_base', 'id_parent', 'id_article_pdf'); |
| 258 | 258 | foreach ($_GET as $var => $val) { |
| 259 | - if ( |
|
| 260 | - $_GET[$var] and strncmp($var, "id_", 3) == 0 |
|
| 261 | - and !in_array($var, $_exceptions) |
|
| 262 | - ) { |
|
| 263 | - $_GET[$var] = is_array($_GET[$var]) ? @array_map('intval', $_GET[$var]) : intval($_GET[$var]); |
|
| 264 | - } |
|
| 259 | + if ( |
|
| 260 | + $_GET[$var] and strncmp($var, "id_", 3) == 0 |
|
| 261 | + and !in_array($var, $_exceptions) |
|
| 262 | + ) { |
|
| 263 | + $_GET[$var] = is_array($_GET[$var]) ? @array_map('intval', $_GET[$var]) : intval($_GET[$var]); |
|
| 264 | + } |
|
| 265 | 265 | } |
| 266 | 266 | foreach ($_POST as $var => $val) { |
| 267 | - if ( |
|
| 268 | - $_POST[$var] and strncmp($var, "id_", 3) == 0 |
|
| 269 | - and !in_array($var, $_exceptions) |
|
| 270 | - ) { |
|
| 271 | - $_POST[$var] = is_array($_POST[$var]) ? @array_map('intval', $_POST[$var]) : intval($_POST[$var]); |
|
| 272 | - } |
|
| 267 | + if ( |
|
| 268 | + $_POST[$var] and strncmp($var, "id_", 3) == 0 |
|
| 269 | + and !in_array($var, $_exceptions) |
|
| 270 | + ) { |
|
| 271 | + $_POST[$var] = is_array($_POST[$var]) ? @array_map('intval', $_POST[$var]) : intval($_POST[$var]); |
|
| 272 | + } |
|
| 273 | 273 | } |
| 274 | 274 | foreach ($GLOBALS as $var => $val) { |
| 275 | - if ( |
|
| 276 | - $GLOBALS[$var] and strncmp($var, "id_", 3) == 0 |
|
| 277 | - and !in_array($var, $_exceptions) |
|
| 278 | - ) { |
|
| 279 | - $GLOBALS[$var] = is_array($GLOBALS[$var]) ? @array_map('intval', $GLOBALS[$var]) : intval($GLOBALS[$var]); |
|
| 280 | - } |
|
| 275 | + if ( |
|
| 276 | + $GLOBALS[$var] and strncmp($var, "id_", 3) == 0 |
|
| 277 | + and !in_array($var, $_exceptions) |
|
| 278 | + ) { |
|
| 279 | + $GLOBALS[$var] = is_array($GLOBALS[$var]) ? @array_map('intval', $GLOBALS[$var]) : intval($GLOBALS[$var]); |
|
| 280 | + } |
|
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | /* |
@@ -290,116 +290,116 @@ discard block |
||
| 290 | 290 | * Contrôle de quelques variables (XSS) |
| 291 | 291 | */ |
| 292 | 292 | foreach (array('lang', 'var_recherche', 'aide', 'var_lang_r', 'lang_r', 'var_ajax_ancre', 'nom_fichier') as $var) { |
| 293 | - if (isset($_GET[$var])) { |
|
| 294 | - $_REQUEST[$var] = $GLOBALS[$var] = $_GET[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_GET[$var]); |
|
| 295 | - } |
|
| 296 | - if (isset($_POST[$var])) { |
|
| 297 | - $_REQUEST[$var] = $GLOBALS[$var] = $_POST[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_POST[$var]); |
|
| 298 | - } |
|
| 293 | + if (isset($_GET[$var])) { |
|
| 294 | + $_REQUEST[$var] = $GLOBALS[$var] = $_GET[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_GET[$var]); |
|
| 295 | + } |
|
| 296 | + if (isset($_POST[$var])) { |
|
| 297 | + $_REQUEST[$var] = $GLOBALS[$var] = $_POST[$var] = preg_replace(',[^\w\,/#&;-]+,', ' ', (string)$_POST[$var]); |
|
| 298 | + } |
|
| 299 | 299 | } |
| 300 | 300 | |
| 301 | 301 | /* |
| 302 | 302 | * Filtre l'accès à spip_acces_doc (injection SQL en 1.8.2x) |
| 303 | 303 | */ |
| 304 | 304 | if (isset($_SERVER['REQUEST_URI'])) { |
| 305 | - if (preg_match(',^(.*/)?spip_acces_doc\.,', (string)$_SERVER['REQUEST_URI'])) { |
|
| 306 | - $file = addslashes((string)$_GET['file']); |
|
| 307 | - } |
|
| 305 | + if (preg_match(',^(.*/)?spip_acces_doc\.,', (string)$_SERVER['REQUEST_URI'])) { |
|
| 306 | + $file = addslashes((string)$_GET['file']); |
|
| 307 | + } |
|
| 308 | 308 | } |
| 309 | 309 | |
| 310 | 310 | /* |
| 311 | 311 | * Pas d'inscription abusive |
| 312 | 312 | */ |
| 313 | 313 | if ( |
| 314 | - isset($_REQUEST['mode']) and isset($_REQUEST['page']) |
|
| 315 | - and !in_array($_REQUEST['mode'], array("6forum", "1comite")) |
|
| 316 | - and $_REQUEST['page'] == "identifiants" |
|
| 314 | + isset($_REQUEST['mode']) and isset($_REQUEST['page']) |
|
| 315 | + and !in_array($_REQUEST['mode'], array("6forum", "1comite")) |
|
| 316 | + and $_REQUEST['page'] == "identifiants" |
|
| 317 | 317 | ) { |
| 318 | - $ecran_securite_raison = "identifiants"; |
|
| 318 | + $ecran_securite_raison = "identifiants"; |
|
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | /* |
| 322 | 322 | * Agenda joue à l'injection php |
| 323 | 323 | */ |
| 324 | 324 | if ( |
| 325 | - isset($_REQUEST['partie_cal']) |
|
| 326 | - and $_REQUEST['partie_cal'] !== htmlentities((string)$_REQUEST['partie_cal']) |
|
| 325 | + isset($_REQUEST['partie_cal']) |
|
| 326 | + and $_REQUEST['partie_cal'] !== htmlentities((string)$_REQUEST['partie_cal']) |
|
| 327 | 327 | ) { |
| 328 | - $ecran_securite_raison = "partie_cal"; |
|
| 328 | + $ecran_securite_raison = "partie_cal"; |
|
| 329 | 329 | } |
| 330 | 330 | if ( |
| 331 | - isset($_REQUEST['echelle']) |
|
| 332 | - and $_REQUEST['echelle'] !== htmlentities((string)$_REQUEST['echelle']) |
|
| 331 | + isset($_REQUEST['echelle']) |
|
| 332 | + and $_REQUEST['echelle'] !== htmlentities((string)$_REQUEST['echelle']) |
|
| 333 | 333 | ) { |
| 334 | - $ecran_securite_raison = "echelle"; |
|
| 334 | + $ecran_securite_raison = "echelle"; |
|
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | /* |
| 338 | 338 | * Espace privé |
| 339 | 339 | */ |
| 340 | 340 | if ( |
| 341 | - isset($_REQUEST['exec']) |
|
| 342 | - and !preg_match(',^[\w-]+$,', (string)$_REQUEST['exec']) |
|
| 341 | + isset($_REQUEST['exec']) |
|
| 342 | + and !preg_match(',^[\w-]+$,', (string)$_REQUEST['exec']) |
|
| 343 | 343 | ) { |
| 344 | - $ecran_securite_raison = "exec"; |
|
| 344 | + $ecran_securite_raison = "exec"; |
|
| 345 | 345 | } |
| 346 | 346 | if ( |
| 347 | - isset($_REQUEST['cherche_auteur']) |
|
| 348 | - and preg_match(',[<],', (string)$_REQUEST['cherche_auteur']) |
|
| 347 | + isset($_REQUEST['cherche_auteur']) |
|
| 348 | + and preg_match(',[<],', (string)$_REQUEST['cherche_auteur']) |
|
| 349 | 349 | ) { |
| 350 | - $ecran_securite_raison = "cherche_auteur"; |
|
| 350 | + $ecran_securite_raison = "cherche_auteur"; |
|
| 351 | 351 | } |
| 352 | 352 | if ( |
| 353 | - isset($_REQUEST['exec']) |
|
| 354 | - and $_REQUEST['exec'] == 'auteurs' |
|
| 355 | - and isset($_REQUEST['recherche']) |
|
| 356 | - and preg_match(',[<],', (string)$_REQUEST['recherche']) |
|
| 353 | + isset($_REQUEST['exec']) |
|
| 354 | + and $_REQUEST['exec'] == 'auteurs' |
|
| 355 | + and isset($_REQUEST['recherche']) |
|
| 356 | + and preg_match(',[<],', (string)$_REQUEST['recherche']) |
|
| 357 | 357 | ) { |
| 358 | - $ecran_securite_raison = "recherche"; |
|
| 358 | + $ecran_securite_raison = "recherche"; |
|
| 359 | 359 | } |
| 360 | 360 | if ( |
| 361 | - isset($_REQUEST['exec']) |
|
| 362 | - and $_REQUEST['exec'] == 'info_plugin' |
|
| 363 | - and isset($_REQUEST['plugin']) |
|
| 364 | - and preg_match(',[<],', (string)$_REQUEST['plugin']) |
|
| 361 | + isset($_REQUEST['exec']) |
|
| 362 | + and $_REQUEST['exec'] == 'info_plugin' |
|
| 363 | + and isset($_REQUEST['plugin']) |
|
| 364 | + and preg_match(',[<],', (string)$_REQUEST['plugin']) |
|
| 365 | 365 | ) { |
| 366 | - $ecran_securite_raison = "plugin"; |
|
| 366 | + $ecran_securite_raison = "plugin"; |
|
| 367 | 367 | } |
| 368 | 368 | if ( |
| 369 | - isset($_REQUEST['exec']) |
|
| 370 | - and $_REQUEST['exec'] == 'puce_statut' |
|
| 371 | - and isset($_REQUEST['id']) |
|
| 372 | - and !intval($_REQUEST['id']) |
|
| 369 | + isset($_REQUEST['exec']) |
|
| 370 | + and $_REQUEST['exec'] == 'puce_statut' |
|
| 371 | + and isset($_REQUEST['id']) |
|
| 372 | + and !intval($_REQUEST['id']) |
|
| 373 | 373 | ) { |
| 374 | - $ecran_securite_raison = "puce_statut"; |
|
| 374 | + $ecran_securite_raison = "puce_statut"; |
|
| 375 | 375 | } |
| 376 | 376 | if ( |
| 377 | - isset($_REQUEST['action']) |
|
| 378 | - and $_REQUEST['action'] == 'configurer' |
|
| 377 | + isset($_REQUEST['action']) |
|
| 378 | + and $_REQUEST['action'] == 'configurer' |
|
| 379 | 379 | ) { |
| 380 | - if ( |
|
| 381 | - @file_exists('inc_version.php') |
|
| 382 | - or @file_exists('ecrire/inc_version.php') |
|
| 383 | - ) { |
|
| 384 | - function action_configurer() { |
|
| 385 | - include_spip('inc/autoriser'); |
|
| 386 | - if (!autoriser('configurer', _request('configuration'))) { |
|
| 387 | - include_spip('inc/minipres'); |
|
| 388 | - echo minipres(_T('info_acces_interdit')); |
|
| 389 | - exit; |
|
| 390 | - } |
|
| 391 | - require _DIR_RESTREINT . 'action/configurer.php'; |
|
| 392 | - action_configurer_dist(); |
|
| 393 | - } |
|
| 394 | - } |
|
| 380 | + if ( |
|
| 381 | + @file_exists('inc_version.php') |
|
| 382 | + or @file_exists('ecrire/inc_version.php') |
|
| 383 | + ) { |
|
| 384 | + function action_configurer() { |
|
| 385 | + include_spip('inc/autoriser'); |
|
| 386 | + if (!autoriser('configurer', _request('configuration'))) { |
|
| 387 | + include_spip('inc/minipres'); |
|
| 388 | + echo minipres(_T('info_acces_interdit')); |
|
| 389 | + exit; |
|
| 390 | + } |
|
| 391 | + require _DIR_RESTREINT . 'action/configurer.php'; |
|
| 392 | + action_configurer_dist(); |
|
| 393 | + } |
|
| 394 | + } |
|
| 395 | 395 | } |
| 396 | 396 | if ( |
| 397 | - isset($_REQUEST['action']) |
|
| 398 | - and $_REQUEST['action'] == 'ordonner_liens_documents' |
|
| 399 | - and isset($_REQUEST['ordre']) |
|
| 400 | - and is_string($_REQUEST['ordre']) |
|
| 397 | + isset($_REQUEST['action']) |
|
| 398 | + and $_REQUEST['action'] == 'ordonner_liens_documents' |
|
| 399 | + and isset($_REQUEST['ordre']) |
|
| 400 | + and is_string($_REQUEST['ordre']) |
|
| 401 | 401 | ) { |
| 402 | - $ecran_securite_raison = "ordre a la chaine"; |
|
| 402 | + $ecran_securite_raison = "ordre a la chaine"; |
|
| 403 | 403 | } |
| 404 | 404 | |
| 405 | 405 | |
@@ -407,29 +407,29 @@ discard block |
||
| 407 | 407 | * Bloque les requêtes contenant %00 (manipulation d'include) |
| 408 | 408 | */ |
| 409 | 409 | if (strpos( |
| 410 | - (function_exists('get_magic_quotes_gpc') and @get_magic_quotes_gpc()) |
|
| 411 | - ? stripslashes(serialize($_REQUEST)) |
|
| 412 | - : serialize($_REQUEST), |
|
| 413 | - chr(0) |
|
| 410 | + (function_exists('get_magic_quotes_gpc') and @get_magic_quotes_gpc()) |
|
| 411 | + ? stripslashes(serialize($_REQUEST)) |
|
| 412 | + : serialize($_REQUEST), |
|
| 413 | + chr(0) |
|
| 414 | 414 | ) !== false) { |
| 415 | - $ecran_securite_raison = "%00"; |
|
| 415 | + $ecran_securite_raison = "%00"; |
|
| 416 | 416 | } |
| 417 | 417 | |
| 418 | 418 | /* |
| 419 | 419 | * Bloque les requêtes fond=formulaire_ |
| 420 | 420 | */ |
| 421 | 421 | if ( |
| 422 | - isset($_REQUEST['fond']) |
|
| 423 | - and preg_match(',^formulaire_,i', $_REQUEST['fond']) |
|
| 422 | + isset($_REQUEST['fond']) |
|
| 423 | + and preg_match(',^formulaire_,i', $_REQUEST['fond']) |
|
| 424 | 424 | ) { |
| 425 | - $ecran_securite_raison = "fond=formulaire_"; |
|
| 425 | + $ecran_securite_raison = "fond=formulaire_"; |
|
| 426 | 426 | } |
| 427 | 427 | |
| 428 | 428 | /* |
| 429 | 429 | * Bloque les requêtes du type ?GLOBALS[type_urls]=toto (bug vieux php) |
| 430 | 430 | */ |
| 431 | 431 | if (isset($_REQUEST['GLOBALS'])) { |
| 432 | - $ecran_securite_raison = "GLOBALS[GLOBALS]"; |
|
| 432 | + $ecran_securite_raison = "GLOBALS[GLOBALS]"; |
|
| 433 | 433 | } |
| 434 | 434 | |
| 435 | 435 | /* |
@@ -438,14 +438,14 @@ discard block |
||
| 438 | 438 | * les paginations entremélées |
| 439 | 439 | */ |
| 440 | 440 | if (_IS_BOT) { |
| 441 | - if ( |
|
| 442 | - (isset($_REQUEST['echelle']) and isset($_REQUEST['partie_cal']) and isset($_REQUEST['type'])) |
|
| 443 | - or (strpos((string)$_SERVER['REQUEST_URI'], 'debut_') and preg_match(',[?&]debut_.*&debut_,', (string)$_SERVER['REQUEST_URI'])) |
|
| 444 | - or (isset($_REQUEST['calendrier_annee']) and strpos((string)$_SERVER['REQUEST_URI'], 'debut_')) |
|
| 445 | - or (isset($_REQUEST['calendrier_annee']) and preg_match(',[?&]calendrier_annee=.*&calendrier_annee=,', (string)$_SERVER['REQUEST_URI'])) |
|
| 446 | - ) { |
|
| 447 | - $ecran_securite_raison = "robot agenda/double pagination"; |
|
| 448 | - } |
|
| 441 | + if ( |
|
| 442 | + (isset($_REQUEST['echelle']) and isset($_REQUEST['partie_cal']) and isset($_REQUEST['type'])) |
|
| 443 | + or (strpos((string)$_SERVER['REQUEST_URI'], 'debut_') and preg_match(',[?&]debut_.*&debut_,', (string)$_SERVER['REQUEST_URI'])) |
|
| 444 | + or (isset($_REQUEST['calendrier_annee']) and strpos((string)$_SERVER['REQUEST_URI'], 'debut_')) |
|
| 445 | + or (isset($_REQUEST['calendrier_annee']) and preg_match(',[?&]calendrier_annee=.*&calendrier_annee=,', (string)$_SERVER['REQUEST_URI'])) |
|
| 446 | + ) { |
|
| 447 | + $ecran_securite_raison = "robot agenda/double pagination"; |
|
| 448 | + } |
|
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | /* |
@@ -453,82 +453,82 @@ discard block |
||
| 453 | 453 | * Bloque un XSS sur une page inexistante |
| 454 | 454 | */ |
| 455 | 455 | if (isset($_REQUEST['page'])) { |
| 456 | - if ($_REQUEST['page'] == 'test_cfg') { |
|
| 457 | - $ecran_securite_raison = "test_cfg"; |
|
| 458 | - } |
|
| 459 | - if ($_REQUEST['page'] !== htmlspecialchars((string)$_REQUEST['page'])) { |
|
| 460 | - $ecran_securite_raison = "xsspage"; |
|
| 461 | - } |
|
| 462 | - if ( |
|
| 463 | - $_REQUEST['page'] == '404' |
|
| 464 | - and isset($_REQUEST['erreur']) |
|
| 465 | - ) { |
|
| 466 | - $ecran_securite_raison = "xss404"; |
|
| 467 | - } |
|
| 456 | + if ($_REQUEST['page'] == 'test_cfg') { |
|
| 457 | + $ecran_securite_raison = "test_cfg"; |
|
| 458 | + } |
|
| 459 | + if ($_REQUEST['page'] !== htmlspecialchars((string)$_REQUEST['page'])) { |
|
| 460 | + $ecran_securite_raison = "xsspage"; |
|
| 461 | + } |
|
| 462 | + if ( |
|
| 463 | + $_REQUEST['page'] == '404' |
|
| 464 | + and isset($_REQUEST['erreur']) |
|
| 465 | + ) { |
|
| 466 | + $ecran_securite_raison = "xss404"; |
|
| 467 | + } |
|
| 468 | 468 | } |
| 469 | 469 | |
| 470 | 470 | /* |
| 471 | 471 | * XSS par array |
| 472 | 472 | */ |
| 473 | 473 | foreach (array('var_login') as $var) { |
| 474 | - if (isset($_REQUEST[$var]) and is_array($_REQUEST[$var])) { |
|
| 475 | - $ecran_securite_raison = "xss " . $var; |
|
| 476 | - } |
|
| 474 | + if (isset($_REQUEST[$var]) and is_array($_REQUEST[$var])) { |
|
| 475 | + $ecran_securite_raison = "xss " . $var; |
|
| 476 | + } |
|
| 477 | 477 | } |
| 478 | 478 | |
| 479 | 479 | /* |
| 480 | 480 | * Parade antivirale contre un cheval de troie |
| 481 | 481 | */ |
| 482 | 482 | if (!function_exists('tmp_lkojfghx')) { |
| 483 | - function tmp_lkojfghx() {} |
|
| 484 | - function tmp_lkojfghx2($a = 0, $b = 0, $c = 0, $d = 0) { |
|
| 485 | - // si jamais on est arrivé ici sur une erreur php |
|
| 486 | - // et qu'un autre gestionnaire d'erreur est défini, l'appeller |
|
| 487 | - if ($b && $GLOBALS['tmp_xhgfjokl']) { |
|
| 488 | - call_user_func($GLOBALS['tmp_xhgfjokl'], $a, $b, $c, $d); |
|
| 489 | - } |
|
| 490 | - } |
|
| 483 | + function tmp_lkojfghx() {} |
|
| 484 | + function tmp_lkojfghx2($a = 0, $b = 0, $c = 0, $d = 0) { |
|
| 485 | + // si jamais on est arrivé ici sur une erreur php |
|
| 486 | + // et qu'un autre gestionnaire d'erreur est défini, l'appeller |
|
| 487 | + if ($b && $GLOBALS['tmp_xhgfjokl']) { |
|
| 488 | + call_user_func($GLOBALS['tmp_xhgfjokl'], $a, $b, $c, $d); |
|
| 489 | + } |
|
| 490 | + } |
|
| 491 | 491 | } |
| 492 | 492 | if (isset($_POST['tmp_lkojfghx3'])) { |
| 493 | - $ecran_securite_raison = "gumblar"; |
|
| 493 | + $ecran_securite_raison = "gumblar"; |
|
| 494 | 494 | } |
| 495 | 495 | |
| 496 | 496 | /* |
| 497 | 497 | * Outils XML mal sécurisés < 2.0.9 |
| 498 | 498 | */ |
| 499 | 499 | if (isset($_REQUEST['transformer_xml'])) { |
| 500 | - $ecran_securite_raison = "transformer_xml"; |
|
| 500 | + $ecran_securite_raison = "transformer_xml"; |
|
| 501 | 501 | } |
| 502 | 502 | |
| 503 | 503 | /* |
| 504 | 504 | * Outils XML mal sécurisés again |
| 505 | 505 | */ |
| 506 | 506 | if (isset($_REQUEST['var_url']) and $_REQUEST['var_url'] and isset($_REQUEST['exec']) and $_REQUEST['exec'] == 'valider_xml') { |
| 507 | - $url = trim($_REQUEST['var_url']); |
|
| 508 | - if ( |
|
| 509 | - strncmp($url, '/', 1) == 0 |
|
| 510 | - or (($p = strpos($url, '..')) !== false and strpos($url, '..', $p + 3) !== false) |
|
| 511 | - or (($p = strpos($url, '..')) !== false and strpos($url, 'IMG', $p + 3) !== false) |
|
| 512 | - or (strpos($url, '://') !== false or strpos($url, ':\\') !== false) |
|
| 513 | - ) { |
|
| 514 | - $ecran_securite_raison = 'URL interdite pour var_url'; |
|
| 515 | - } |
|
| 507 | + $url = trim($_REQUEST['var_url']); |
|
| 508 | + if ( |
|
| 509 | + strncmp($url, '/', 1) == 0 |
|
| 510 | + or (($p = strpos($url, '..')) !== false and strpos($url, '..', $p + 3) !== false) |
|
| 511 | + or (($p = strpos($url, '..')) !== false and strpos($url, 'IMG', $p + 3) !== false) |
|
| 512 | + or (strpos($url, '://') !== false or strpos($url, ':\\') !== false) |
|
| 513 | + ) { |
|
| 514 | + $ecran_securite_raison = 'URL interdite pour var_url'; |
|
| 515 | + } |
|
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 | /* |
| 519 | 519 | * Sauvegarde mal securisée < 2.0.9 |
| 520 | 520 | */ |
| 521 | 521 | if ( |
| 522 | - isset($_REQUEST['nom_sauvegarde']) |
|
| 523 | - and strstr((string)$_REQUEST['nom_sauvegarde'], '/') |
|
| 522 | + isset($_REQUEST['nom_sauvegarde']) |
|
| 523 | + and strstr((string)$_REQUEST['nom_sauvegarde'], '/') |
|
| 524 | 524 | ) { |
| 525 | - $ecran_securite_raison = 'nom_sauvegarde manipulee'; |
|
| 525 | + $ecran_securite_raison = 'nom_sauvegarde manipulee'; |
|
| 526 | 526 | } |
| 527 | 527 | if ( |
| 528 | - isset($_REQUEST['znom_sauvegarde']) |
|
| 529 | - and strstr((string)$_REQUEST['znom_sauvegarde'], '/') |
|
| 528 | + isset($_REQUEST['znom_sauvegarde']) |
|
| 529 | + and strstr((string)$_REQUEST['znom_sauvegarde'], '/') |
|
| 530 | 530 | ) { |
| 531 | - $ecran_securite_raison = 'znom_sauvegarde manipulee'; |
|
| 531 | + $ecran_securite_raison = 'znom_sauvegarde manipulee'; |
|
| 532 | 532 | } |
| 533 | 533 | |
| 534 | 534 | |
@@ -537,57 +537,57 @@ discard block |
||
| 537 | 537 | * on vérifie 'page' pour ne pas bloquer ... drupal |
| 538 | 538 | */ |
| 539 | 539 | if ( |
| 540 | - isset($_REQUEST['op']) and isset($_REQUEST['page']) |
|
| 541 | - and $_REQUEST['op'] !== preg_replace('/[^\\-\w]/', '', $_REQUEST['op']) |
|
| 540 | + isset($_REQUEST['op']) and isset($_REQUEST['page']) |
|
| 541 | + and $_REQUEST['op'] !== preg_replace('/[^\\-\w]/', '', $_REQUEST['op']) |
|
| 542 | 542 | ) { |
| 543 | - $ecran_securite_raison = 'op'; |
|
| 543 | + $ecran_securite_raison = 'op'; |
|
| 544 | 544 | } |
| 545 | 545 | |
| 546 | 546 | /* |
| 547 | 547 | * Forms & Table ne se méfiait pas assez des uploads de fichiers |
| 548 | 548 | */ |
| 549 | 549 | if (count($_FILES)) { |
| 550 | - foreach ($_FILES as $k => $v) { |
|
| 551 | - if ( |
|
| 552 | - preg_match(',^fichier_\d+$,', $k) |
|
| 553 | - and preg_match(',\.php,i', $v['name']) |
|
| 554 | - ) { |
|
| 555 | - unset($_FILES[$k]); |
|
| 556 | - } |
|
| 557 | - } |
|
| 550 | + foreach ($_FILES as $k => $v) { |
|
| 551 | + if ( |
|
| 552 | + preg_match(',^fichier_\d+$,', $k) |
|
| 553 | + and preg_match(',\.php,i', $v['name']) |
|
| 554 | + ) { |
|
| 555 | + unset($_FILES[$k]); |
|
| 556 | + } |
|
| 557 | + } |
|
| 558 | 558 | } |
| 559 | 559 | /* |
| 560 | 560 | * et Contact trop laxiste avec une variable externe |
| 561 | 561 | * on bloque pas le post pour eviter de perdre des donnees mais on unset la variable et c'est tout |
| 562 | 562 | */ |
| 563 | 563 | if (isset($_REQUEST['pj_enregistrees_nom']) and $_REQUEST['pj_enregistrees_nom']) { |
| 564 | - unset($_REQUEST['pj_enregistrees_nom']); |
|
| 565 | - unset($_GET['pj_enregistrees_nom']); |
|
| 566 | - unset($_POST['pj_enregistrees_nom']); |
|
| 564 | + unset($_REQUEST['pj_enregistrees_nom']); |
|
| 565 | + unset($_GET['pj_enregistrees_nom']); |
|
| 566 | + unset($_POST['pj_enregistrees_nom']); |
|
| 567 | 567 | } |
| 568 | 568 | |
| 569 | 569 | /* |
| 570 | 570 | * reinstall=oui un peu trop permissif |
| 571 | 571 | */ |
| 572 | 572 | if ( |
| 573 | - isset($_REQUEST['reinstall']) |
|
| 574 | - and $_REQUEST['reinstall'] == 'oui' |
|
| 573 | + isset($_REQUEST['reinstall']) |
|
| 574 | + and $_REQUEST['reinstall'] == 'oui' |
|
| 575 | 575 | ) { |
| 576 | - $ecran_securite_raison = 'reinstall=oui'; |
|
| 576 | + $ecran_securite_raison = 'reinstall=oui'; |
|
| 577 | 577 | } |
| 578 | 578 | |
| 579 | 579 | /* |
| 580 | 580 | * Pas d'action pendant l'install |
| 581 | 581 | */ |
| 582 | 582 | if (isset($_REQUEST['exec']) and $_REQUEST['exec'] === 'install' and isset($_REQUEST['action'])) { |
| 583 | - $ecran_securite_raison = 'install&action impossibles'; |
|
| 583 | + $ecran_securite_raison = 'install&action impossibles'; |
|
| 584 | 584 | } |
| 585 | 585 | |
| 586 | 586 | /* |
| 587 | 587 | * Échappement xss referer |
| 588 | 588 | */ |
| 589 | 589 | if (isset($_SERVER['HTTP_REFERER'])) { |
| 590 | - $_SERVER['HTTP_REFERER'] = strtr($_SERVER['HTTP_REFERER'], '<>"\'', '[]##'); |
|
| 590 | + $_SERVER['HTTP_REFERER'] = strtr($_SERVER['HTTP_REFERER'], '<>"\'', '[]##'); |
|
| 591 | 591 | } |
| 592 | 592 | |
| 593 | 593 | |
@@ -595,7 +595,7 @@ discard block |
||
| 595 | 595 | * Echappement HTTP_X_FORWARDED_HOST |
| 596 | 596 | */ |
| 597 | 597 | if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { |
| 598 | - $_SERVER['HTTP_X_FORWARDED_HOST'] = strtr($_SERVER['HTTP_X_FORWARDED_HOST'], "<>?\"\{\}\$'` \r\n", '____________'); |
|
| 598 | + $_SERVER['HTTP_X_FORWARDED_HOST'] = strtr($_SERVER['HTTP_X_FORWARDED_HOST'], "<>?\"\{\}\$'` \r\n", '____________'); |
|
| 599 | 599 | } |
| 600 | 600 | |
| 601 | 601 | |
@@ -603,9 +603,9 @@ discard block |
||
| 603 | 603 | * Pas d'erreur dans l'erreur |
| 604 | 604 | */ |
| 605 | 605 | if (isset($_REQUEST['var_erreur']) and isset($_REQUEST['page']) and $_REQUEST['page'] === 'login') { |
| 606 | - if (strlen($_REQUEST['var_erreur']) !== strcspn($_REQUEST['var_erreur'], '<>')) { |
|
| 607 | - $ecran_securite_raison = 'var_erreur incorrecte'; |
|
| 608 | - } |
|
| 606 | + if (strlen($_REQUEST['var_erreur']) !== strcspn($_REQUEST['var_erreur'], '<>')) { |
|
| 607 | + $ecran_securite_raison = 'var_erreur incorrecte'; |
|
| 608 | + } |
|
| 609 | 609 | } |
| 610 | 610 | |
| 611 | 611 | |
@@ -613,30 +613,30 @@ discard block |
||
| 613 | 613 | * Réinjection des clés en html dans l'admin r19561 |
| 614 | 614 | */ |
| 615 | 615 | if ( |
| 616 | - (isset($_SERVER['REQUEST_URI']) and strpos($_SERVER['REQUEST_URI'], "ecrire/") !== false) |
|
| 617 | - or isset($_REQUEST['var_memotri']) |
|
| 616 | + (isset($_SERVER['REQUEST_URI']) and strpos($_SERVER['REQUEST_URI'], "ecrire/") !== false) |
|
| 617 | + or isset($_REQUEST['var_memotri']) |
|
| 618 | 618 | ) { |
| 619 | - $zzzz = implode("", array_keys($_REQUEST)); |
|
| 620 | - if (strlen($zzzz) != strcspn($zzzz, '<>"\'')) { |
|
| 621 | - $ecran_securite_raison = 'Cle incorrecte en $_REQUEST'; |
|
| 622 | - } |
|
| 619 | + $zzzz = implode("", array_keys($_REQUEST)); |
|
| 620 | + if (strlen($zzzz) != strcspn($zzzz, '<>"\'')) { |
|
| 621 | + $ecran_securite_raison = 'Cle incorrecte en $_REQUEST'; |
|
| 622 | + } |
|
| 623 | 623 | } |
| 624 | 624 | |
| 625 | 625 | /* |
| 626 | 626 | * Injection par connect |
| 627 | 627 | */ |
| 628 | 628 | if ( |
| 629 | - isset($_REQUEST['connect']) |
|
| 630 | - // cas qui permettent de sortir d'un commentaire PHP |
|
| 631 | - and ( |
|
| 632 | - strpos($_REQUEST['connect'], "?") !== false |
|
| 633 | - or strpos($_REQUEST['connect'], "<") !== false |
|
| 634 | - or strpos($_REQUEST['connect'], ">") !== false |
|
| 635 | - or strpos($_REQUEST['connect'], "\n") !== false |
|
| 636 | - or strpos($_REQUEST['connect'], "\r") !== false |
|
| 637 | - ) |
|
| 629 | + isset($_REQUEST['connect']) |
|
| 630 | + // cas qui permettent de sortir d'un commentaire PHP |
|
| 631 | + and ( |
|
| 632 | + strpos($_REQUEST['connect'], "?") !== false |
|
| 633 | + or strpos($_REQUEST['connect'], "<") !== false |
|
| 634 | + or strpos($_REQUEST['connect'], ">") !== false |
|
| 635 | + or strpos($_REQUEST['connect'], "\n") !== false |
|
| 636 | + or strpos($_REQUEST['connect'], "\r") !== false |
|
| 637 | + ) |
|
| 638 | 638 | ) { |
| 639 | - $ecran_securite_raison = "malformed connect argument"; |
|
| 639 | + $ecran_securite_raison = "malformed connect argument"; |
|
| 640 | 640 | } |
| 641 | 641 | |
| 642 | 642 | |
@@ -644,9 +644,9 @@ discard block |
||
| 644 | 644 | * _oups donc |
| 645 | 645 | */ |
| 646 | 646 | if ( |
| 647 | - isset($_REQUEST['_oups']) |
|
| 648 | - and base64_decode($_REQUEST['_oups'], true) === false) { |
|
| 649 | - $ecran_securite_raison = "malformed _oups argument"; |
|
| 647 | + isset($_REQUEST['_oups']) |
|
| 648 | + and base64_decode($_REQUEST['_oups'], true) === false) { |
|
| 649 | + $ecran_securite_raison = "malformed _oups argument"; |
|
| 650 | 650 | } |
| 651 | 651 | |
| 652 | 652 | |
@@ -654,23 +654,23 @@ discard block |
||
| 654 | 654 | * S'il y a une raison de mourir, mourons |
| 655 | 655 | */ |
| 656 | 656 | if (isset($ecran_securite_raison)) { |
| 657 | - header("HTTP/1.0 403 Forbidden"); |
|
| 658 | - header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); |
|
| 659 | - header("Cache-Control: no-cache, must-revalidate"); |
|
| 660 | - header("Pragma: no-cache"); |
|
| 661 | - header("Content-Type: text/html"); |
|
| 662 | - header("Connection: close"); |
|
| 663 | - die("<html><title>Error 403: Forbidden</title><body><h1>Error 403</h1><p>You are not authorized to view this page ($ecran_securite_raison)</p></body></html>"); |
|
| 657 | + header("HTTP/1.0 403 Forbidden"); |
|
| 658 | + header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); |
|
| 659 | + header("Cache-Control: no-cache, must-revalidate"); |
|
| 660 | + header("Pragma: no-cache"); |
|
| 661 | + header("Content-Type: text/html"); |
|
| 662 | + header("Connection: close"); |
|
| 663 | + die("<html><title>Error 403: Forbidden</title><body><h1>Error 403</h1><p>You are not authorized to view this page ($ecran_securite_raison)</p></body></html>"); |
|
| 664 | 664 | } |
| 665 | 665 | |
| 666 | 666 | /* |
| 667 | 667 | * Un filtre filtrer_entites securise |
| 668 | 668 | */ |
| 669 | 669 | if (!function_exists('filtre_filtrer_entites_dist')) { |
| 670 | - function filtre_filtrer_entites_dist($t) { |
|
| 671 | - include_spip('inc/texte'); |
|
| 672 | - return interdire_scripts(filtrer_entites($t)); |
|
| 673 | - } |
|
| 670 | + function filtre_filtrer_entites_dist($t) { |
|
| 671 | + include_spip('inc/texte'); |
|
| 672 | + return interdire_scripts(filtrer_entites($t)); |
|
| 673 | + } |
|
| 674 | 674 | } |
| 675 | 675 | |
| 676 | 676 | |
@@ -684,35 +684,35 @@ discard block |
||
| 684 | 684 | * Bloque les bots quand le load déborde |
| 685 | 685 | */ |
| 686 | 686 | if (!defined('_ECRAN_SECURITE_LOAD')) { |
| 687 | - define('_ECRAN_SECURITE_LOAD', 4); |
|
| 687 | + define('_ECRAN_SECURITE_LOAD', 4); |
|
| 688 | 688 | } |
| 689 | 689 | |
| 690 | 690 | if ( |
| 691 | - defined('_ECRAN_SECURITE_LOAD') |
|
| 692 | - and _ECRAN_SECURITE_LOAD > 0 |
|
| 693 | - and _IS_BOT |
|
| 694 | - and !_IS_BOT_FRIEND |
|
| 695 | - and $_SERVER['REQUEST_METHOD'] === 'GET' |
|
| 696 | - and ( |
|
| 697 | - (function_exists('sys_getloadavg') |
|
| 698 | - and $load = sys_getloadavg() |
|
| 699 | - and is_array($load) |
|
| 700 | - and $load = array_shift($load)) |
|
| 701 | - or |
|
| 702 | - (@is_readable('/proc/loadavg') |
|
| 703 | - and $load = file_get_contents('/proc/loadavg') |
|
| 704 | - and $load = floatval($load)) |
|
| 705 | - ) |
|
| 706 | - and $load > _ECRAN_SECURITE_LOAD // eviter l'evaluation suivante si de toute facon le load est inferieur a la limite |
|
| 707 | - and rand(0, $load * $load) > _ECRAN_SECURITE_LOAD * _ECRAN_SECURITE_LOAD |
|
| 691 | + defined('_ECRAN_SECURITE_LOAD') |
|
| 692 | + and _ECRAN_SECURITE_LOAD > 0 |
|
| 693 | + and _IS_BOT |
|
| 694 | + and !_IS_BOT_FRIEND |
|
| 695 | + and $_SERVER['REQUEST_METHOD'] === 'GET' |
|
| 696 | + and ( |
|
| 697 | + (function_exists('sys_getloadavg') |
|
| 698 | + and $load = sys_getloadavg() |
|
| 699 | + and is_array($load) |
|
| 700 | + and $load = array_shift($load)) |
|
| 701 | + or |
|
| 702 | + (@is_readable('/proc/loadavg') |
|
| 703 | + and $load = file_get_contents('/proc/loadavg') |
|
| 704 | + and $load = floatval($load)) |
|
| 705 | + ) |
|
| 706 | + and $load > _ECRAN_SECURITE_LOAD // eviter l'evaluation suivante si de toute facon le load est inferieur a la limite |
|
| 707 | + and rand(0, $load * $load) > _ECRAN_SECURITE_LOAD * _ECRAN_SECURITE_LOAD |
|
| 708 | 708 | ) { |
| 709 | - //https://webmasters.stackexchange.com/questions/65674/should-i-return-a-429-or-503-status-code-to-a-bot |
|
| 710 | - header("HTTP/1.0 429 Too Many Requests"); |
|
| 711 | - header("Retry-After: 300"); |
|
| 712 | - header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); |
|
| 713 | - header("Cache-Control: no-cache, must-revalidate"); |
|
| 714 | - header("Pragma: no-cache"); |
|
| 715 | - header("Content-Type: text/html"); |
|
| 716 | - header("Connection: close"); |
|
| 717 | - die("<html><title>Status 429: Too Many Requests</title><body><h1>Status 429</h1><p>Too Many Requests (try again soon)</p></body></html>"); |
|
| 709 | + //https://webmasters.stackexchange.com/questions/65674/should-i-return-a-429-or-503-status-code-to-a-bot |
|
| 710 | + header("HTTP/1.0 429 Too Many Requests"); |
|
| 711 | + header("Retry-After: 300"); |
|
| 712 | + header("Expires: Wed, 11 Jan 1984 05:00:00 GMT"); |
|
| 713 | + header("Cache-Control: no-cache, must-revalidate"); |
|
| 714 | + header("Pragma: no-cache"); |
|
| 715 | + header("Content-Type: text/html"); |
|
| 716 | + header("Connection: close"); |
|
| 717 | + die("<html><title>Status 429: Too Many Requests</title><body><h1>Status 429</h1><p>Too Many Requests (try again soon)</p></body></html>"); |
|
| 718 | 718 | } |
@@ -14,171 +14,171 @@ |
||
| 14 | 14 | |
| 15 | 15 | /** Gestion des clés d’authentification / chiffrement de SPIP */ |
| 16 | 16 | final class SpipCles { |
| 17 | - private static array $instances = []; |
|
| 18 | - |
|
| 19 | - private string $file = _DIR_ETC . 'cles.php'; |
|
| 20 | - private Cles $cles; |
|
| 21 | - |
|
| 22 | - public static function instance(string $file = ''): self { |
|
| 23 | - if (empty(self::$instances[$file])) { |
|
| 24 | - self::$instances[$file] = new self($file); |
|
| 25 | - } |
|
| 26 | - return self::$instances[$file]; |
|
| 27 | - } |
|
| 28 | - |
|
| 29 | - /** |
|
| 30 | - * Retourne le secret du site (shorthand) |
|
| 31 | - * @uses self::getSecretSite() |
|
| 32 | - */ |
|
| 33 | - public static function secret_du_site(): ?string { |
|
| 34 | - return (self::instance())->getSecretSite(); |
|
| 35 | - } |
|
| 36 | - |
|
| 37 | - private function __construct(string $file = '') { |
|
| 38 | - if ($file) { |
|
| 39 | - $this->file = $file; |
|
| 40 | - } |
|
| 41 | - $this->cles = new Cles($this->read()); |
|
| 42 | - } |
|
| 43 | - |
|
| 44 | - /** |
|
| 45 | - * Renvoyer le secret du site |
|
| 46 | - * |
|
| 47 | - * Le secret du site doit rester aussi secret que possible, et est eternel |
|
| 48 | - * On ne doit pas l'exporter |
|
| 49 | - * |
|
| 50 | - * Le secret est partagé entre une clé disque et une clé bdd |
|
| 51 | - * |
|
| 52 | - * @return string |
|
| 53 | - */ |
|
| 54 | - public function getSecretSite(bool $autoInit = true): ?string { |
|
| 55 | - $key = $this->getKey('secret_du_site', $autoInit); |
|
| 56 | - $meta = $this->getMetaKey('secret_du_site', $autoInit); |
|
| 57 | - // conserve la même longeur. |
|
| 58 | - return $key ^ $meta; |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - /** Renvoyer le secret des authentifications */ |
|
| 62 | - public function getSecretAuth(bool $autoInit = false): ?string { |
|
| 63 | - return $this->getKey('secret_des_auth', $autoInit); |
|
| 64 | - } |
|
| 65 | - public function save(): bool { |
|
| 66 | - return ecrire_fichier_securise($this->file, $this->cles->toJson()); |
|
| 67 | - } |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * Fournir une sauvegarde chiffree des cles (a l'aide d'une autre clé, comme le pass d'un auteur) |
|
| 71 | - * |
|
| 72 | - * @param string $withKey Clé de chiffrage de la sauvegarde |
|
| 73 | - * @return string Contenu de la sauvegarde chiffrée générée |
|
| 74 | - */ |
|
| 75 | - public function backup( |
|
| 76 | - #[\SensitiveParameter] |
|
| 77 | - string $withKey |
|
| 78 | - ): string { |
|
| 79 | - if (count($this->cles)) { |
|
| 80 | - return Chiffrement::chiffrer($this->cles->toJson(), $withKey); |
|
| 81 | - } |
|
| 82 | - return ''; |
|
| 83 | - } |
|
| 84 | - |
|
| 85 | - /** |
|
| 86 | - * Restaurer les cles manquantes depuis une sauvegarde chiffree des cles |
|
| 87 | - * (si la sauvegarde est bien valide) |
|
| 88 | - * |
|
| 89 | - * @param string $backup Sauvegarde chiffrée (générée par backup()) |
|
| 90 | - * @param int $id_auteur |
|
| 91 | - * @param string $pass |
|
| 92 | - * @return void |
|
| 93 | - */ |
|
| 94 | - public function restore( |
|
| 95 | - string $backup, |
|
| 96 | - #[\SensitiveParameter] |
|
| 97 | - string $password_clair, |
|
| 98 | - #[\SensitiveParameter] |
|
| 99 | - string $password_hash, |
|
| 100 | - int $id_auteur |
|
| 101 | - ): bool { |
|
| 102 | - if (empty($backup)) { |
|
| 103 | - return false; |
|
| 104 | - } |
|
| 105 | - |
|
| 106 | - $sauvegarde = Chiffrement::dechiffrer($backup, $password_clair); |
|
| 107 | - $json = json_decode($sauvegarde, true); |
|
| 108 | - if (!$json) { |
|
| 109 | - return false; |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - // cela semble une sauvegarde valide |
|
| 113 | - $cles_potentielles = array_map('base64_decode', $json); |
|
| 114 | - |
|
| 115 | - // il faut faire une double verif sur secret_des_auth |
|
| 116 | - // pour s'assurer qu'elle permet bien de decrypter le pass de l'auteur qui fournit la sauvegarde |
|
| 117 | - // et par extension tous les passwords |
|
| 118 | - if (!empty($cles_potentielles['secret_des_auth'])) { |
|
| 119 | - if (!Password::verifier($password_clair, $password_hash, $cles_potentielles['secret_des_auth'])) { |
|
| 120 | - spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 121 | - unset($cles_potentielles['secret_des_auth']); |
|
| 122 | - } |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - // on merge les cles pour recuperer les cles manquantes |
|
| 126 | - $restauration = false; |
|
| 127 | - foreach ($cles_potentielles as $name => $key) { |
|
| 128 | - if (!$this->cles->has($name)) { |
|
| 129 | - $this->cles->set($name, $key); |
|
| 130 | - spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 131 | - $restauration = true; |
|
| 132 | - } |
|
| 133 | - } |
|
| 134 | - return $restauration; |
|
| 135 | - } |
|
| 136 | - |
|
| 137 | - private function getKey(string $name, bool $autoInit): ?string { |
|
| 138 | - if ($this->cles->has($name)) { |
|
| 139 | - return $this->cles->get($name); |
|
| 140 | - } |
|
| 141 | - if ($autoInit) { |
|
| 142 | - $this->cles->generate($name); |
|
| 143 | - // si l'ecriture de fichier a bien marche on peut utiliser la cle |
|
| 144 | - if ($this->save()) { |
|
| 145 | - return $this->cles->get($name); |
|
| 146 | - } |
|
| 147 | - // sinon loger et annule la cle generee car il ne faut pas l'utiliser |
|
| 148 | - spip_log('Echec ecriture du fichier cle ' . $this->file . " ; impossible de generer une cle $name", 'chiffrer' . _LOG_ERREUR); |
|
| 149 | - $this->cles->delete($name); |
|
| 150 | - } |
|
| 151 | - return null; |
|
| 152 | - } |
|
| 153 | - |
|
| 154 | - private function getMetaKey(string $name, bool $autoInit = true): ?string { |
|
| 155 | - if (!isset($GLOBALS['meta'][$name])) { |
|
| 156 | - include_spip('base/abstract_sql'); |
|
| 157 | - $GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = ' . sql_quote($name, '', 'string')); |
|
| 158 | - } |
|
| 159 | - $key = base64_decode($GLOBALS['meta'][$name] ?? ''); |
|
| 160 | - if (strlen($key) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { |
|
| 161 | - return $key; |
|
| 162 | - } |
|
| 163 | - if (!$autoInit) { |
|
| 164 | - return null; |
|
| 165 | - } |
|
| 166 | - $key = Chiffrement::keygen(); |
|
| 167 | - ecrire_meta($name, base64_encode($key), 'non'); |
|
| 168 | - lire_metas(); // au cas ou ecrire_meta() ne fonctionne pas |
|
| 169 | - |
|
| 170 | - return $key; |
|
| 171 | - } |
|
| 172 | - |
|
| 173 | - private function read(): array { |
|
| 174 | - lire_fichier_securise($this->file, $json); |
|
| 175 | - if ( |
|
| 176 | - $json |
|
| 177 | - and $json = \json_decode($json, true) |
|
| 178 | - and is_array($json) |
|
| 179 | - ) { |
|
| 180 | - return array_map('base64_decode', $json); |
|
| 181 | - } |
|
| 182 | - return []; |
|
| 183 | - } |
|
| 17 | + private static array $instances = []; |
|
| 18 | + |
|
| 19 | + private string $file = _DIR_ETC . 'cles.php'; |
|
| 20 | + private Cles $cles; |
|
| 21 | + |
|
| 22 | + public static function instance(string $file = ''): self { |
|
| 23 | + if (empty(self::$instances[$file])) { |
|
| 24 | + self::$instances[$file] = new self($file); |
|
| 25 | + } |
|
| 26 | + return self::$instances[$file]; |
|
| 27 | + } |
|
| 28 | + |
|
| 29 | + /** |
|
| 30 | + * Retourne le secret du site (shorthand) |
|
| 31 | + * @uses self::getSecretSite() |
|
| 32 | + */ |
|
| 33 | + public static function secret_du_site(): ?string { |
|
| 34 | + return (self::instance())->getSecretSite(); |
|
| 35 | + } |
|
| 36 | + |
|
| 37 | + private function __construct(string $file = '') { |
|
| 38 | + if ($file) { |
|
| 39 | + $this->file = $file; |
|
| 40 | + } |
|
| 41 | + $this->cles = new Cles($this->read()); |
|
| 42 | + } |
|
| 43 | + |
|
| 44 | + /** |
|
| 45 | + * Renvoyer le secret du site |
|
| 46 | + * |
|
| 47 | + * Le secret du site doit rester aussi secret que possible, et est eternel |
|
| 48 | + * On ne doit pas l'exporter |
|
| 49 | + * |
|
| 50 | + * Le secret est partagé entre une clé disque et une clé bdd |
|
| 51 | + * |
|
| 52 | + * @return string |
|
| 53 | + */ |
|
| 54 | + public function getSecretSite(bool $autoInit = true): ?string { |
|
| 55 | + $key = $this->getKey('secret_du_site', $autoInit); |
|
| 56 | + $meta = $this->getMetaKey('secret_du_site', $autoInit); |
|
| 57 | + // conserve la même longeur. |
|
| 58 | + return $key ^ $meta; |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + /** Renvoyer le secret des authentifications */ |
|
| 62 | + public function getSecretAuth(bool $autoInit = false): ?string { |
|
| 63 | + return $this->getKey('secret_des_auth', $autoInit); |
|
| 64 | + } |
|
| 65 | + public function save(): bool { |
|
| 66 | + return ecrire_fichier_securise($this->file, $this->cles->toJson()); |
|
| 67 | + } |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * Fournir une sauvegarde chiffree des cles (a l'aide d'une autre clé, comme le pass d'un auteur) |
|
| 71 | + * |
|
| 72 | + * @param string $withKey Clé de chiffrage de la sauvegarde |
|
| 73 | + * @return string Contenu de la sauvegarde chiffrée générée |
|
| 74 | + */ |
|
| 75 | + public function backup( |
|
| 76 | + #[\SensitiveParameter] |
|
| 77 | + string $withKey |
|
| 78 | + ): string { |
|
| 79 | + if (count($this->cles)) { |
|
| 80 | + return Chiffrement::chiffrer($this->cles->toJson(), $withKey); |
|
| 81 | + } |
|
| 82 | + return ''; |
|
| 83 | + } |
|
| 84 | + |
|
| 85 | + /** |
|
| 86 | + * Restaurer les cles manquantes depuis une sauvegarde chiffree des cles |
|
| 87 | + * (si la sauvegarde est bien valide) |
|
| 88 | + * |
|
| 89 | + * @param string $backup Sauvegarde chiffrée (générée par backup()) |
|
| 90 | + * @param int $id_auteur |
|
| 91 | + * @param string $pass |
|
| 92 | + * @return void |
|
| 93 | + */ |
|
| 94 | + public function restore( |
|
| 95 | + string $backup, |
|
| 96 | + #[\SensitiveParameter] |
|
| 97 | + string $password_clair, |
|
| 98 | + #[\SensitiveParameter] |
|
| 99 | + string $password_hash, |
|
| 100 | + int $id_auteur |
|
| 101 | + ): bool { |
|
| 102 | + if (empty($backup)) { |
|
| 103 | + return false; |
|
| 104 | + } |
|
| 105 | + |
|
| 106 | + $sauvegarde = Chiffrement::dechiffrer($backup, $password_clair); |
|
| 107 | + $json = json_decode($sauvegarde, true); |
|
| 108 | + if (!$json) { |
|
| 109 | + return false; |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + // cela semble une sauvegarde valide |
|
| 113 | + $cles_potentielles = array_map('base64_decode', $json); |
|
| 114 | + |
|
| 115 | + // il faut faire une double verif sur secret_des_auth |
|
| 116 | + // pour s'assurer qu'elle permet bien de decrypter le pass de l'auteur qui fournit la sauvegarde |
|
| 117 | + // et par extension tous les passwords |
|
| 118 | + if (!empty($cles_potentielles['secret_des_auth'])) { |
|
| 119 | + if (!Password::verifier($password_clair, $password_hash, $cles_potentielles['secret_des_auth'])) { |
|
| 120 | + spip_log("Restauration de la cle `secret_des_auth` par id_auteur $id_auteur erronnee, on ignore", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 121 | + unset($cles_potentielles['secret_des_auth']); |
|
| 122 | + } |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + // on merge les cles pour recuperer les cles manquantes |
|
| 126 | + $restauration = false; |
|
| 127 | + foreach ($cles_potentielles as $name => $key) { |
|
| 128 | + if (!$this->cles->has($name)) { |
|
| 129 | + $this->cles->set($name, $key); |
|
| 130 | + spip_log("Restauration de la cle $name par id_auteur $id_auteur", 'chiffrer' . _LOG_INFO_IMPORTANTE); |
|
| 131 | + $restauration = true; |
|
| 132 | + } |
|
| 133 | + } |
|
| 134 | + return $restauration; |
|
| 135 | + } |
|
| 136 | + |
|
| 137 | + private function getKey(string $name, bool $autoInit): ?string { |
|
| 138 | + if ($this->cles->has($name)) { |
|
| 139 | + return $this->cles->get($name); |
|
| 140 | + } |
|
| 141 | + if ($autoInit) { |
|
| 142 | + $this->cles->generate($name); |
|
| 143 | + // si l'ecriture de fichier a bien marche on peut utiliser la cle |
|
| 144 | + if ($this->save()) { |
|
| 145 | + return $this->cles->get($name); |
|
| 146 | + } |
|
| 147 | + // sinon loger et annule la cle generee car il ne faut pas l'utiliser |
|
| 148 | + spip_log('Echec ecriture du fichier cle ' . $this->file . " ; impossible de generer une cle $name", 'chiffrer' . _LOG_ERREUR); |
|
| 149 | + $this->cles->delete($name); |
|
| 150 | + } |
|
| 151 | + return null; |
|
| 152 | + } |
|
| 153 | + |
|
| 154 | + private function getMetaKey(string $name, bool $autoInit = true): ?string { |
|
| 155 | + if (!isset($GLOBALS['meta'][$name])) { |
|
| 156 | + include_spip('base/abstract_sql'); |
|
| 157 | + $GLOBALS['meta'][$name] = sql_getfetsel('valeur', 'spip_meta', 'nom = ' . sql_quote($name, '', 'string')); |
|
| 158 | + } |
|
| 159 | + $key = base64_decode($GLOBALS['meta'][$name] ?? ''); |
|
| 160 | + if (strlen($key) === \SODIUM_CRYPTO_SECRETBOX_KEYBYTES) { |
|
| 161 | + return $key; |
|
| 162 | + } |
|
| 163 | + if (!$autoInit) { |
|
| 164 | + return null; |
|
| 165 | + } |
|
| 166 | + $key = Chiffrement::keygen(); |
|
| 167 | + ecrire_meta($name, base64_encode($key), 'non'); |
|
| 168 | + lire_metas(); // au cas ou ecrire_meta() ne fonctionne pas |
|
| 169 | + |
|
| 170 | + return $key; |
|
| 171 | + } |
|
| 172 | + |
|
| 173 | + private function read(): array { |
|
| 174 | + lire_fichier_securise($this->file, $json); |
|
| 175 | + if ( |
|
| 176 | + $json |
|
| 177 | + and $json = \json_decode($json, true) |
|
| 178 | + and is_array($json) |
|
| 179 | + ) { |
|
| 180 | + return array_map('base64_decode', $json); |
|
| 181 | + } |
|
| 182 | + return []; |
|
| 183 | + } |
|
| 184 | 184 | } |