| @@ -1,33 +1,39 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | +defined('ABSPATH') || die('Restricted Access'); | |
| 4 | + | |
| 3 | 5 | use AcyMailing\Helpers\UpdatemeHelper; |
| 4 | 6 | |
| 7 | +/** | |
| 8 | + * @param mixed $default | |
| 9 | + * | |
| 10 | + * @return mixed | |
| 11 | + */ | |
| 5 | 12 | function acym_getVar(string $type, string $name, $default = null, string $source = 'REQUEST', int $mask = 0) |
| 6 | 13 | { |
| 7 | 14 | $source = strtoupper($source); |
| 8 | 15 | |
| 9 | 16 | switch ($source) { |
| 10 | - case 'GET': | |
| 11 | - $input = &$_GET; | |
| 12 | - break; | |
| 13 | - case 'POST': | |
| 14 | - $input = &$_POST; | |
| 15 | - break; | |
| 16 | 17 | case 'FILES': |
| 18 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is the caller's responsibility for this generic helper. | |
| 17 | 19 | $input = &$_FILES; |
| 18 | 20 | break; |
| 19 | 21 | case 'COOKIE': |
| 22 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is the caller's responsibility for this generic helper. | |
| 20 | 23 | $input = &$_COOKIE; |
| 21 | 24 | break; |
| 22 | - case 'ENV': | |
| 23 | - $input = &$_ENV; | |
| 24 | - break; | |
| 25 | 25 | case 'SERVER': |
| 26 | + // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification is the caller's responsibility for this generic helper. | |
| 26 | 27 | $input = &$_SERVER; |
| 27 | 28 | break; |
| 29 | + case 'SESSION': | |
| 30 | + acym_session(); | |
| 31 | + $input = &$_SESSION; | |
| 32 | + break; | |
| 28 | 33 | default: |
| 29 | 34 | $source = 'REQUEST'; |
| 35 | + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is the caller's responsibility for this generic helper. | |
| 30 | 36 | $input = &$_REQUEST; |
| 31 | 37 | break; |
| 32 | 38 | } |
| 33 | 39 | |
| @@ -40,8 +46,9 @@ | ||
| 40 | 46 | if ($type === 'array') { |
| 41 | 47 | $result = (array)$result; |
| 42 | 48 | } |
| 43 | 49 | |
| 50 | + // WP alters every variable in $_REQUEST... Seriously... | |
| 44 | 51 | if (in_array($source, ['POST', 'REQUEST', 'GET', 'COOKIE'])) { |
| 45 | 52 | $result = acym_stripslashes($result); |
| 46 | 53 | } |
| 47 | 54 | |
| @@ -106,8 +113,9 @@ | ||
| 106 | 113 | return $var; |
| 107 | 114 | } |
| 108 | 115 | |
| 109 | 116 | if (!preg_match('//u', $var)) { |
| 117 | + // String contains invalid byte sequence, remove it | |
| 110 | 118 | $var = htmlspecialchars_decode(htmlspecialchars($var, ENT_IGNORE, 'UTF-8')); |
| 111 | 119 | } |
| 112 | 120 | |
| 113 | 121 | if (!($mask & ACYM_ALLOWHTML)) { |
| @@ -116,50 +124,26 @@ | ||
| 116 | 124 | |
| 117 | 125 | return $var; |
| 118 | 126 | } |
| 119 | 127 | |
| 120 | -function acym_setVar(string $name, $value = null, string $hash = 'REQUEST', bool $overwrite = true): void | |
| 128 | +function acym_setVar(string $name, $value): void | |
| 121 | 129 | { |
| 122 | - $hash = strtoupper($hash); | |
| 123 | - | |
| 124 | - switch ($hash) { | |
| 125 | - case 'GET': | |
| 126 | - $input = &$_GET; | |
| 127 | - break; | |
| 128 | - case 'POST': | |
| 129 | - $input = &$_POST; | |
| 130 | - break; | |
| 131 | - case 'FILES': | |
| 132 | - $input = &$_FILES; | |
| 133 | - break; | |
| 134 | - case 'COOKIE': | |
| 135 | - $input = &$_COOKIE; | |
| 136 | - break; | |
| 137 | - case 'ENV': | |
| 138 | - $input = &$_ENV; | |
| 139 | - break; | |
| 140 | - case 'SERVER': | |
| 141 | - $input = &$_SERVER; | |
| 142 | - break; | |
| 143 | - default: | |
| 144 | - $input = &$_REQUEST; | |
| 145 | - break; | |
| 146 | - } | |
| 147 | - | |
| 148 | - if (!isset($input[$name]) || $overwrite) { | |
| 149 | - $input[$name] = $value; | |
| 150 | - } | |
| 130 | + $_REQUEST[$name] = $value; | |
| 151 | 131 | } |
| 152 | 132 | |
| 133 | +/** | |
| 134 | + * Function detecting the context of a request, not related to security checks | |
| 135 | + */ | |
| 153 | 136 | function acym_isAdmin(): bool |
| 154 | 137 | { |
| 138 | + // Outside of /wp-admin we are on the front-end, whatever the request parameters say | |
| 139 | + if (!is_admin()) { | |
| 140 | + return false; | |
| 141 | + } | |
| 142 | + | |
| 155 | 143 | $page = acym_getVar('string', 'page', ''); |
| 156 | 144 | |
| 157 | - if (!empty($page)) { | |
| 158 | - return !in_array($page, [ACYM_COMPONENT.'_front', 'front']); | |
| 159 | - } else { | |
| 160 | - return is_admin(); | |
| 161 | - } | |
| 145 | + return !in_array($page, [ACYM_COMPONENT.'_front', 'front'], true); | |
| 162 | 146 | } |
| 163 | 147 | |
| 164 | 148 | function acym_cmsLoaded(): void |
| 165 | 149 | { |
| @@ -172,8 +156,9 @@ | ||
| 172 | 156 | } |
| 173 | 157 | |
| 174 | 158 | function acym_askLog(bool $current = true, string $message = 'ACYM_NOTALLOWED', string $type = 'error'): void |
| 175 | 159 | { |
| 160 | + //If the user is not logged in, we just redirect him to the login page.... | |
| 176 | 161 | $url = acym_rootURI().'wp-login.php'; |
| 177 | 162 | if ($current) { |
| 178 | 163 | $url .= '&redirect_to='.base64_encode(acym_currentURL()); |
| 179 | 164 | } |
| @@ -200,40 +185,69 @@ | ||
| 200 | 185 | |
| 201 | 186 | return $allPref; |
| 202 | 187 | } |
| 203 | 188 | |
| 204 | -function acym_cmsPermission(): string | |
| 189 | +function acym_hasAdminPermissions(): bool | |
| 205 | 190 | { |
| 206 | - if (!current_user_can('manage_options')) return ''; | |
| 191 | + return current_user_can('manage_options'); | |
| 192 | +} | |
| 207 | 193 | |
| 194 | +/** | |
| 195 | + * May the user reach the AcyMailing back-end at all? Same rule as the menu visibility (Menu::addMenus). | |
| 196 | + */ | |
| 197 | +function acym_hasBackofficeAccess(): bool | |
| 198 | +{ | |
| 208 | 199 | $config = acym_config(); |
| 200 | + $allowedGroups = explode(',', $config->get('wp_access', 'administrator')); | |
| 201 | + | |
| 202 | + $userGroups = acym_getGroupsByUser(); | |
| 203 | + foreach ($userGroups as $oneGroup) { | |
| 204 | + if ($oneGroup == 'administrator' || in_array($oneGroup, $allowedGroups)) { | |
| 205 | + return true; | |
| 206 | + } | |
| 207 | + } | |
| 208 | + | |
| 209 | + return false; | |
| 210 | +} | |
| 211 | + | |
| 212 | +function acym_cmsPermission(): void | |
| 213 | +{ | |
| 214 | + if (!acym_hasAdminPermissions()) { | |
| 215 | + return; | |
| 216 | + } | |
| 217 | + | |
| 218 | + $config = acym_config(); | |
| 209 | 219 | $roles = acym_getGroups(); |
| 210 | 220 | $options = []; |
| 211 | 221 | $selected = explode(',', $config->get('wp_access', 'administrator')); |
| 212 | 222 | |
| 213 | 223 | foreach ($roles as $name => $oneRole) { |
| 214 | - if ($name === 'administrator') continue; | |
| 224 | + if ($name === 'administrator') { | |
| 225 | + continue; | |
| 226 | + } | |
| 215 | 227 | $options[$name] = $oneRole->text; |
| 216 | 228 | } |
| 217 | 229 | |
| 218 | 230 | asort($options); |
| 219 | 231 | |
| 220 | - $option = ' | |
| 221 | - <div class="cell grid-x"> | |
| 222 | - <label class="cell large-3 medium-5 small-9">'.acym_translation('ACYM_ACCESS').' '.acym_info(['textShownInTooltip' => 'ACYM_ACCESS_DESC']).'</label> | |
| 232 | + echo '<div class="cell grid-x"> | |
| 233 | + <label class="cell large-3 medium-5 small-9">'.esc_html(acym_translation('ACYM_ACCESS')).' '; | |
| 234 | + acym_info(['textShownInTooltip' => 'ACYM_ACCESS_DESC']); | |
| 235 | + echo '</label> | |
| 223 | 236 | <div class="cell auto">'; |
| 224 | 237 | |
| 225 | - $option .= acym_selectMultiple( | |
| 238 | + acym_selectMultiple( | |
| 226 | 239 | $options, |
| 227 | 240 | 'config[wp_access]', |
| 228 | 241 | $selected, |
| 229 | - ['class' => 'acym__select'] | |
| 242 | + ['class' => 'acym__select'], | |
| 243 | + 'value', | |
| 244 | + 'text', | |
| 245 | + true, | |
| 230 | 246 | ); |
| 231 | 247 | |
| 232 | - $option .= '</div> | |
| 248 | + echo '</div> | |
| 233 | 249 | </div>'; |
| 234 | - | |
| 235 | - return $option; | |
| 236 | 250 | } |
| 237 | 251 | |
| 238 | 252 | function acym_triggerCmsHook(string $action, array $args = [], bool $isAction = true) |
| 239 | 253 | { |
| @@ -246,11 +260,10 @@ | ||
| 246 | 260 | { |
| 247 | 261 | return []; |
| 248 | 262 | } |
| 249 | 263 | |
| 250 | -function acym_loadCaptcha(string $captchaPluginName, string $id): string | |
| 264 | +function acym_loadCaptcha(string $captchaPluginName, string $id): void | |
| 251 | 265 | { |
| 252 | - return ''; | |
| 253 | 266 | } |
| 254 | 267 | |
| 255 | 268 | function acym_checkCaptcha(string $captchaPluginName, ?string $response = null): bool |
| 256 | 269 | { |
| @@ -259,5 +272,21 @@ | ||
| 259 | 272 | |
| 260 | 273 | function acym_getSiteSalt(): string |
| 261 | 274 | { |
| 262 | 275 | return wp_salt('auth'); |
| 276 | +} | |
| 277 | + | |
| 278 | +function acym_stripTags(string $text): string | |
| 279 | +{ | |
| 280 | + return wp_strip_all_tags($text); | |
| 281 | +} | |
| 282 | + | |
| 283 | +function acym_setSession(string $name, $value, bool $remove = false): void | |
| 284 | +{ | |
| 285 | + acym_session(); | |
| 286 | + | |
| 287 | + if ($remove) { | |
| 288 | + unset($_SESSION[$name]); | |
| 289 | + } else { | |
| 290 | + $_SESSION[$name] = $value; | |
| 291 | + } | |
| 263 | 292 | } |