1<?php 2/** 3 * DokuWiki Avatar Plugin: displays avatar images with syntax, see: 4 * <https://www.dokuwiki.org/plugin:avatar>. 5 * 6 * Copyright (C) 2005-2007 by Esther Brunner <wikidesign@gmail.com> 7 * Copyright (C) 2008-2009 by Gina Häußge, Michael Klier <dokuwiki@chimeric.de> 8 * Copyright (C) 2013 by Michael Hamann <michael@content-space.de> 9 * Copyright (C) 2023 by Daniel Dias Rodrigues <danieldiasr@gmail.com> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with this program; if not, see <https://www.gnu.org/licenses/>. 23 */ 24 25if(!defined('DOKU_INC')) die(); 26 27class syntax_plugin_avatar extends DokuWiki_Syntax_Plugin { 28 29 const SIZE_SMALL = 20; 30 const SIZE_MEDIUM = 40; 31 const SIZE_LARGE = 80; 32 const SIZE_XLARGE = 120; 33 34 public function getType(): string { return 'substition'; } 35 public function getSort(): int { return 315; } 36 37 public function connectTo($mode): void { 38 $this->Lexer->addSpecialPattern("{{(?:gr|)avatar>.+?}}", $mode, 'plugin_avatar'); 39 } 40 41 public function handle($match, $state, $pos, Doku_Handler $handler): ?array { 42 $parts = explode('>', substr($match, 2, -2), 2); 43 44 if (count($parts) !== 2) { 45 return null; // Malformed input → discards and interrupts handle() 46 } 47 48 $match = $parts[1]; // $parts[0] = 'avatar' or 'gravatar' 49 50 if (!preg_match('/^([^?|]+)(?:\?([^|]*))?(?:\|(.*))?$/', $match, $matches)) { 51 return null; 52 } 53 54 $user = $matches[1]; 55 56 /* Final check: 57 * Even if something strange slipped through the first regex, here the 58 * string is checked in isolation. This ensures that the renderer will 59 * only receive a clean username or a valid email, preventing parsing 60 * problems, CSS errors, HTML injection, etc. 61 */ 62 if (filter_var($user, FILTER_VALIDATE_EMAIL) === false && 63 !preg_match('/^\s*[a-zA-Z0-9._-]+\s*$/', $user)) { 64 return null; 65 } 66 67 $param = isset($matches[2]) ? trim(strtolower($matches[2])) : ''; 68 $title = isset($matches[3]) ? trim($matches[3]) : ''; 69 70 // Determine alignment 71 $align = null; 72 if ($user !== ltrim($user)) $align = 'right'; 73 if ($user !== rtrim($user)) $align = $align ? 'center' : 'left'; 74 $user = trim($user); 75 76 // Determine size 77 switch ($param) { 78 case 's': $size = self::SIZE_SMALL; break; 79 case 'm': $size = self::SIZE_MEDIUM; break; 80 case 'l': $size = self::SIZE_LARGE; break; 81 case 'xl': $size = self::SIZE_XLARGE; break; 82 default: 83 $size = max(1, (int) $this->getConf('size')) ?: self::SIZE_MEDIUM; 84 break; 85 } 86 87 return [$user, $title, $align, $size]; 88 } 89 90 public function render($mode, Doku_Renderer $renderer, $data): bool { 91 if ($mode !== 'xhtml') return false; 92 93 if ($data === null) { 94 $renderer->doc .= '<span style="color:red;font-family:monospace;' . 95 'font-weight:bold;">' . 96 'Error: Avatar plugin: Invalid username or' . 97 ' email</span>'; 98 return true; 99 } 100 101 if ($my = plugin_load('helper', 'avatar')) { 102 $renderer->doc .= '<span class="vcard">' . 103 $my->renderXhtml($data[0], $data[1], $data[2], $data[3]) . 104 '</span>'; 105 } 106 return true; 107 } 108} 109