diff --git a/.github/workflows/wp-plugin-ci-full.yml b/.github/workflows/wp-plugin-ci-full.yml index 36290f5..acec683 100644 --- a/.github/workflows/wp-plugin-ci-full.yml +++ b/.github/workflows/wp-plugin-ci-full.yml @@ -27,4 +27,4 @@ jobs: - name: Run PHPCS on all files run: | - vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE | cs2pr + vendor/bin/phpcs -q -n --ignore=vendor --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE | cs2pr diff --git a/.github/workflows/wp-plugin-ci.yml b/.github/workflows/wp-plugin-ci.yml index 35ab7aa..299b378 100644 --- a/.github/workflows/wp-plugin-ci.yml +++ b/.github/workflows/wp-plugin-ci.yml @@ -32,4 +32,4 @@ jobs: run: | touch $GITHUB_WORKSPACE/tmp.php export CHANGED_FILES=$(git diff --name-only --diff-filter=AM remotes/origin/${{ github.base_ref }} | tr '\n' ' ') - vendor/bin/phpcs -q -n --ignore=vendor --runtime-set installed_paths vendor/wp-coding-standards/wpcs --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE/tmp.php $(echo $CHANGED_FILES) | cs2pr + vendor/bin/phpcs -q -n --ignore=vendor --standard=WordPress --report=checkstyle $GITHUB_WORKSPACE/tmp.php $(echo $CHANGED_FILES) | cs2pr diff --git a/assets/js/shibboleth_login_form.js b/assets/js/shibboleth_login_form.js index 370a335..646cc85 100644 --- a/assets/js/shibboleth_login_form.js +++ b/assets/js/shibboleth_login_form.js @@ -6,7 +6,7 @@ */ jQuery( document ).ready( - function( $ ) { + function ( $ ) { var body = $( 'body' ), userLogin = $( '#user_login' ), ssoWrap = $( '#shibboleth-wrap' ), diff --git a/composer.json b/composer.json index b928343..9071c4f 100644 --- a/composer.json +++ b/composer.json @@ -9,5 +9,10 @@ "require": {}, "require-dev" : { "wp-coding-standards/wpcs": "@stable" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/options-admin.php b/options-admin.php index e788012..39e727a 100644 --- a/options-admin.php +++ b/options-admin.php @@ -52,20 +52,13 @@ function shibboleth_network_admin_panels() { add_action( 'network_admin_menu', 'shibboleth_network_admin_panels' ); /** - * WordPress options page to configure the Shibboleth plugin. + * Shibboleth header fields. * - * @uses apply_filters() Calls 'shibboleth_plugin_path' - * @since ? + * @since 2.4.3 + * @return array */ -function shibboleth_options_page() { - global $wp_roles; - - $message = null; - $type = null; - - $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; - - $shib_header_fields = array( +function shibboleth_header_fields() { + return array( 'username' => __( 'Username' ), 'first_name' => __( 'First Name' ), 'last_name' => __( 'Last Name' ), @@ -73,789 +66,851 @@ function shibboleth_options_page() { 'display_name' => __( 'Display name', 'shibboleth' ), 'email' => __( 'Email' ), ); +} +/** + * Shibboleth options update helper. + * + * @since 2.4.3 + */ +function shibboleth_options_updated() { + $type = 'updated'; + $message = __( 'Settings saved.', 'shibboleth' ); + + if ( function_exists( 'add_settings_error' ) ) { + add_settings_error( 'shibboleth_settings_updated', esc_attr( 'shibboleth_settings_updated' ), $message, $type ); + settings_errors( 'shibboleth_settings_updated' ); + } + + /** + * Action shibboleth_form_submit + * + * @since 1.4 + * Hint: use global $_POST within the action. + */ + do_action( 'shibboleth_form_submit' ); +} + +/** + * Shibboleth - General options tab. + * + * @since 2.4.3 + */ +function shibboleth_options_general() { if ( isset( $_POST['submit'] ) ) { check_admin_referer( 'shibboleth_update_options' ); - switch ( $tab ) { - case 'general': - if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD' ) && isset( $_POST['attribute_access'] ) ) { - update_site_option( 'shibboleth_attribute_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_access'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD_FALLBACK' ) ) { - update_site_option( 'shibboleth_attribute_access_method_fallback', ! empty( $_POST['attribute_access_fallback'] ) ); - } - if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_CUSTOM_ACCESS_METHOD' ) && isset( $_POST['attribute_custom_access'] ) ) { - update_site_option( 'shibboleth_attribute_custom_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_custom_access'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_LOGIN_URL' ) && isset( $_POST['login_url'] ) ) { - update_site_option( 'shibboleth_login_url', esc_url_raw( wp_unslash( $_POST['login_url'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_LOGOUT_URL' ) && isset( $_POST['logout_url'] ) ) { - update_site_option( 'shibboleth_logout_url', esc_url_raw( wp_unslash( $_POST['logout_url'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_SPOOF_KEY' ) && isset( $_POST['spoofkey'] ) ) { - update_site_option( 'shibboleth_spoof_key', sanitize_text_field( wp_unslash( $_POST['spoofkey'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_PASSWORD_CHANGE_URL' ) && isset( $_POST['password_change_url'] ) ) { - update_site_option( 'shibboleth_password_change_url', esc_url_raw( wp_unslash( $_POST['password_change_url'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_PASSWORD_RESET_URL' ) && isset( $_POST['password_reset_url'] ) ) { - update_site_option( 'shibboleth_password_reset_url', esc_url_raw( wp_unslash( $_POST['password_reset_url'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_DEFAULT_TO_SHIB_LOGIN' ) ) { - update_site_option( 'shibboleth_default_to_shib_login', ! empty( $_POST['default_login'] ) ); - } - if ( ! defined( 'SHIBBOLETH_AUTO_LOGIN' ) ) { - update_site_option( 'shibboleth_auto_login', ! empty( $_POST['auto_login'] ) ); - } - if ( ! defined( 'SHIBBOLETH_BUTTON_TEXT' ) && isset( $_POST['button_text'] ) ) { - update_site_option( 'shibboleth_button_text', sanitize_text_field( wp_unslash( $_POST['button_text'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_DISABLE_LOCAL_AUTH' ) ) { - update_site_option( 'shibboleth_disable_local_auth', ! empty( $_POST['disable_local_auth'] ) ); - } - break; - - case 'user': - if ( ! defined( 'SHIBBOLETH_HEADERS' ) && isset( $_POST['headers'] ) ) { - $shib_headers = (array) get_site_option( 'shibboleth_headers' ); - $updated_headers = array(); - foreach ( $shib_header_fields as $header_field => $header_field_label ) { - if ( isset( $_POST['headers'][ $header_field ] ) ) { - $updated_headers[ $header_field ] = array_map( 'sanitize_text_field', wp_unslash( $_POST['headers'][ $header_field ] ) ); - } - } - $shib_headers = array_merge( $shib_headers, $updated_headers ); - /** - * Filter shibboleth_form_submit_headers - * - * @param $shib_headers array - * @since 1.4 - * Hint: access $_POST within the filter. - */ - $shib_headers = apply_filters( 'shibboleth_form_submit_headers', $shib_headers ); - update_site_option( 'shibboleth_headers', $shib_headers ); - } - if ( ! defined( 'SHIBBOLETH_CREATE_ACCOUNTS' ) ) { - update_site_option( 'shibboleth_create_accounts', ! empty( $_POST['create_accounts'] ) ); - } - if ( ! defined( 'SHIBBOLETH_AUTO_COMBINE_ACCOUNTS' ) && isset( $_POST['auto_combine_accounts'] ) ) { - update_site_option( 'shibboleth_auto_combine_accounts', sanitize_text_field( wp_unslash( $_POST['auto_combine_accounts'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_MANUALLY_COMBINE_ACCOUNTS' ) && isset( $_POST['manually_combine_accounts'] ) ) { - update_site_option( 'shibboleth_manually_combine_accounts', sanitize_text_field( wp_unslash( $_POST['manually_combine_accounts'] ) ) ); - } - break; - - case 'authorization': - if ( ! defined( 'SHIBBOLETH_ROLES' ) && isset( $_POST['shibboleth_roles'] ) ) { - $shib_roles = (array) get_site_option( 'shibboleth_roles' ); - $updated_roles = array(); - foreach ( $wp_roles->role_names as $key => $name ) { - if ( isset( $_POST['shibboleth_roles'][ $key ] ) ) { - $updated_roles[ $key ] = array_map( 'sanitize_text_field', wp_unslash( $_POST['shibboleth_roles'][ $key ] ) ); - } - } - $shib_roles = array_merge( $shib_roles, $updated_roles ); - /** - * Filter shibboleth_form_submit_roles - * - * @param $shib_roles array - * @since 1.4 - * Hint: access $_POST within the filter. - */ - $shib_roles = apply_filters( 'shibboleth_form_submit_roles', $shib_roles ); - update_site_option( 'shibboleth_roles', $shib_roles ); - } - if ( ! defined( 'SHIBBOLETH_DEFAULT_ROLE' ) && isset( $_POST['default_role'] ) ) { - update_site_option( 'shibboleth_default_role', sanitize_text_field( wp_unslash( $_POST['default_role'] ) ) ); - } - if ( ! defined( 'SHIBBOLETH_UPDATE_ROLES' ) ) { - update_site_option( 'shibboleth_update_roles', ! empty( $_POST['update_roles'] ) ); - } - break; - - case 'logging': - if ( ! defined( 'SHIBBOLETH_LOGGING' ) ) { - if ( isset( $_POST['logging'] ) ) { - update_site_option( 'shibboleth_logging', array_map( 'sanitize_text_field', wp_unslash( $_POST['logging'] ) ) ); - } else { - update_site_option( 'shibboleth_logging', array() ); - } - } - break; + if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD' ) && isset( $_POST['attribute_access'] ) ) { + update_site_option( 'shibboleth_attribute_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_access'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_ACCESS_METHOD_FALLBACK' ) ) { + update_site_option( 'shibboleth_attribute_access_method_fallback', ! empty( $_POST['attribute_access_fallback'] ) ); + } + if ( ! defined( 'SHIBBOLETH_ATTRIBUTE_CUSTOM_ACCESS_METHOD' ) && isset( $_POST['attribute_custom_access'] ) ) { + update_site_option( 'shibboleth_attribute_custom_access_method', sanitize_text_field( wp_unslash( $_POST['attribute_custom_access'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_LOGIN_URL' ) && isset( $_POST['login_url'] ) ) { + update_site_option( 'shibboleth_login_url', esc_url_raw( wp_unslash( $_POST['login_url'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_LOGOUT_URL' ) && isset( $_POST['logout_url'] ) ) { + update_site_option( 'shibboleth_logout_url', esc_url_raw( wp_unslash( $_POST['logout_url'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_SPOOF_KEY' ) && isset( $_POST['spoofkey'] ) ) { + update_site_option( 'shibboleth_spoof_key', sanitize_text_field( wp_unslash( $_POST['spoofkey'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_PASSWORD_CHANGE_URL' ) && isset( $_POST['password_change_url'] ) ) { + update_site_option( 'shibboleth_password_change_url', esc_url_raw( wp_unslash( $_POST['password_change_url'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_PASSWORD_RESET_URL' ) && isset( $_POST['password_reset_url'] ) ) { + update_site_option( 'shibboleth_password_reset_url', esc_url_raw( wp_unslash( $_POST['password_reset_url'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_DEFAULT_TO_SHIB_LOGIN' ) ) { + update_site_option( 'shibboleth_default_to_shib_login', ! empty( $_POST['default_login'] ) ); + } + if ( ! defined( 'SHIBBOLETH_AUTO_LOGIN' ) ) { + update_site_option( 'shibboleth_auto_login', ! empty( $_POST['auto_login'] ) ); + } + if ( ! defined( 'SHIBBOLETH_BUTTON_TEXT' ) && isset( $_POST['button_text'] ) ) { + update_site_option( 'shibboleth_button_text', sanitize_text_field( wp_unslash( $_POST['button_text'] ) ) ); + } + if ( ! defined( 'SHIBBOLETH_DISABLE_LOCAL_AUTH' ) ) { + update_site_option( 'shibboleth_disable_local_auth', ! empty( $_POST['disable_local_auth'] ) ); } - $type = 'updated'; - $message = __( 'Settings saved.', 'shibboleth' ); + shibboleth_options_updated(); + } - if ( function_exists( 'add_settings_error' ) ) { - add_settings_error( 'shibboleth_settings_updated', esc_attr( 'shibboleth_settings_updated' ), $message, $type ); - settings_errors( 'shibboleth_settings_updated' ); - } + $constant = false; + list( $login_url, $from_constant ) = shibboleth_getoption( 'shibboleth_login_url', false, false, true ); + $constant = $constant || $from_constant; + list( $logout_url, $from_constant ) = shibboleth_getoption( 'shibboleth_logout_url', false, false, true ); + $constant = $constant || $from_constant; + list( $password_change_url, $from_constant ) = shibboleth_getoption( 'shibboleth_password_change_url', false, false, true ); + $constant = $constant || $from_constant; + list( $password_reset_url, $from_constant ) = shibboleth_getoption( 'shibboleth_password_reset_url', false, false, true ); + $constant = $constant || $from_constant; + list( $attribute_access, $from_constant ) = shibboleth_getoption( 'shibboleth_attribute_access_method', false, false, true ); + $constant = $constant || $from_constant; + list( $attribute_access_fallback, $from_constant ) = shibboleth_getoption( 'shibboleth_attribute_access_method_fallback', false, false, true ); + $constant = $constant || $from_constant; + list( $attribute_custom_access, $from_constant ) = shibboleth_getoption( 'shibboleth_attribute_custom_access_method', false, false, true ); + $constant = $constant || $from_constant; + list( $spoofkey, $from_constant ) = shibboleth_getoption( 'shibboleth_spoof_key', false, false, true ); + $constant = $constant || $from_constant; + list( $default_login, $from_constant ) = shibboleth_getoption( 'shibboleth_default_to_shib_login', false, false, true ); + $constant = $constant || $from_constant; + list( $auto_login, $from_constant ) = shibboleth_getoption( 'shibboleth_auto_login', false, false, true ); + $constant = $constant || $from_constant; + list( $disable_local_auth, $from_constant ) = shibboleth_getoption( 'shibboleth_disable_local_auth', false, false, true ); + $constant = $constant || $from_constant; + list( $button_text, $from_constant ) = shibboleth_getoption( 'shibboleth_button_text', false, false, true ); + $constant = $constant || $from_constant; + ?> + +
+ +Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
+ |
+ /> + + : + Shibboleth SP v3 | + Shibboleth SP v2 + |
+
---|---|
+ |
+ /> + + : + Shibboleth SP v3 | + Shibboleth SP v2 + |
+
+ |
+ /> + + |
+
+ |
+ /> + ALL users here to reset their password.', 'shibboleth' ) ); ?> + |
+
+ |
+
+ + REDIRECT_, you should select the "Redirected Environment Variables" option. If you are running + your Shibboleth Service Provider on a reverse proxy, you should select the "HTTP Headers" option and, if at all possible, add a spoofkey below. + If you are running Shibboleth with a custom prefix, you should select the "Custom Prefix" option and complete the "Custom Attribute Access Prefix" field that appears below.', + 'shibboleth' + ) + ); + ?> + + |
+
+ |
+ /> + + WARNING: If you incorrectly set this option, you will force ALL attempts to authenticate with Shibboleth to fail.', + 'shibboleth' + ) + ); + ?> + + |
+
+ |
+ /> +
+ this wiki document.
+ |
+
+ |
+ />
+
+
+ + + + |
+
+ |
+ />
+
+
+ + + + |
+
+ |
+ />
+
+
+
+ wp_signon() call and |
+
+ |
+ />
+
+ + WARNING: Disabling local authentication can potentially lock you out of WordPress if you have misconfigured the plugin or have a non-functional Shibboleth Service Provider. + Make sure that you are confident your configuration is functional before enabling this option.', + 'shibboleth' + ) + ); + ?> + + |
+
+ |
+ /> + wp-login.php page.', 'shibboleth' ) ); ?> + |
+
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
- |
- /> - - : - Shibboleth SP v3 | - Shibboleth SP v2 - |
-
---|---|
- |
- /> - - : - Shibboleth SP v3 | - Shibboleth SP v2 - |
-
- |
- /> - - |
-
- |
- /> - ALL users here to reset their password.', 'shibboleth' ) ); ?> - |
-
- |
-
- - REDIRECT_, you should select the "Redirected Environment Variables" option. If you are running - your Shibboleth Service Provider on a reverse proxy, you should select the "HTTP Headers" option and, if at all possible, add a spoofkey below. - If you are running Shibboleth with a custom prefix, you should select the "Custom Prefix" option and complete the "Custom Attribute Access Prefix" field that appears below.', - 'shibboleth' - ) - ); - ?> - - |
-
- |
- /> - - WARNING: If you incorrectly set this option, you will force ALL attempts to authenticate with Shibboleth to fail.', - 'shibboleth' - ) - ); - ?> - - |
-
- |
- /> -
- this wiki document.
- |
-
- |
- />
-
-
- - - - |
-
- |
- />
-
-
- - - - |
-
- |
- />
-
-
-
- wp_signon() call and |
-
- |
- />
-
- - WARNING: Disabling local authentication can potentially lock you out of WordPress if you have misconfigured the plugin or have a non-functional Shibboleth Service Provider. - Make sure that you are confident your configuration is functional before enabling this option.', - 'shibboleth' - ) - ); - ?> - - |
-
- |
- /> - wp-login.php page.', 'shibboleth' ) ); ?> - |
-
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
- attribute-map.xml (for Shibboleth 2.x) or
- AAP.xml
(for Shibboleth 1.x).',
- 'shibboleth'
- )
- );
+
+ attribute-map.xml (for Shibboleth 2.x) or
+ AAP.xml
(for Shibboleth 1.x).',
+ 'shibboleth'
+ )
+ );
+ ?>
+
+ : + Shibboleth SP v3 | + Shibboleth SP v2 +
+ ++ + | ++ /> + | ++ /> + | +
---|
+ |
+ />
+
+ $header_field_label ) { - $header_field_id = 'shibboleth_' . $header_field; - $header_field_managed_id = 'shibboleth_managed_' . $header_field; - $header_field_value = isset( $shib_headers[ $header_field ]['name'] ) ? $shib_headers[ $header_field ]['name'] : ''; - $header_field_managed = ! empty( $shib_headers[ $header_field ]['managed'] ); - $header_field_managed_disabled = $shib_headers_constant; - - // Username field is always managed and disabled. - if ( 'username' === $header_field ) { - $header_field_managed = true; - $header_field_managed_disabled = true; - } - ?> - | |
---|---|---|
- - | -- /> - | -- /> - | -
- Managed profile fields are updated each time the user logs in using the current - data provided by Shibboleth. Additionally, users will be prevented from manually updating these - fields from within WordPress. Note that Shibboleth data is always used to populate the user - profile during initial account creation.', - 'shibboleth' - ) - ); - ?> -
+ + + +
+
+ Prevent Automatic Account Merging
: This option prevents automatic merging of accounts.
+ Allow Automatic Account Merging
: This option prevents users from experiencing an error if they share a username with both a local and a Shibboleth account.
+ This option WILL NOT prevent an error if another user shares the email passed via Shibboleth attributes.
+ Allow Automatic Account Merging (Bypass Username Management)
: Occasionally, users have pre-existing local WordPress user accounts with a different username than that provided via Shibboleth attributes.
+ This option prevents users from experiencing an error in this case by bypassing the username management requirement.',
+ 'shibboleth'
+ )
+ );
+ ?>
+
+
+ Prevent Manual Account Merging
: This option does not allow users to manually link accounts.
+ Allow Manual Account Merging
: This option allows users to manually link accounts if they share a username with both a local and a Shibboleth account.
+ This option WILL NOT prevent an error if another user shares the email passed via Shibboleth attributes.
+ Allow Manual Account Merging (Bypass Username Management)
: Occasionally, users have pre-existing local WordPress user accounts with a different username than that provided via Shibboleth attributes.
+ This option allows users to manually link accounts by bypassing the username management requirement.',
+ 'shibboleth'
+ )
+ );
+ ?>
+
- |
- />
-
- - Authorization tab. - If a user does not match any mappings, they will be placed into the role selected under "Default Role" on the Authorization tab.', - 'shibboleth' - ) - ); - ?> - - |
-
---|---|
- |
-
-
- |
-
- |
-
-
- |
-
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
+ +
+ ++ Current Limitations: While WordPress supports users having + multiple roles, the Shibboleth plugin will only place the user in the highest ranking + role. Only a single header/value pair is supported for each user role. This may be + expanded in the future to support multiple header/value pairs or regular expression + values. In the meantime, you can use the shibboleth_roles and + shibboleth_user_role WordPress filters to provide your own logic for assigning + user roles.', + 'shibboleth' + ) + ); + ?> +
+ + + + ++ | + | + |
---|---|---|
' . esc_html( $name ) . ' | ++ | + |
+ |
+
+
+ - - -+ + |
+
---|---|
+ |
+
+ />
+
+
+ Current Limitations: While WordPress supports users having - multiple roles, the Shibboleth plugin will only place the user in the highest ranking - role. Only a single header/value pair is supported for each user role. This may be - expanded in the future to support multiple header/value pairs or regular expression - values. In the meantime, you can use the shibboleth_roles and - shibboleth_user_role WordPress filters to provide your own logic for assigning - user roles.', + 'Be aware that if you use this option, you should not update user roles manually, + since they will be overwritten from Shibboleth the next time the user logs in. Note that Shibboleth data + is always used to populate the initial user role during account creation.', 'shibboleth' ) ); ?> - + + |
+
- | - | - |
---|---|---|
' . esc_html( $name ) . ' | -- | - |
- |
-
-
- - - - |
-
---|---|
- |
-
- />
-
-
- - not update user roles manually, - since they will be overwritten from Shibboleth the next time the user logs in. Note that Shibboleth data - is always used to populate the initial user role during account creation.', - 'shibboleth' - ) - ); - ?> - - |
-
Note: Some options below are defined in the wp-config.php
file as constants and cannot be modified from this page.', 'shibboleth' ) ); ?>
+ | + /> + + | +
---|---|
+ | + /> + + | +
+ | + /> + + | +
+ | + /> + + | +