Version Description
- Fixing issues with latests WordPress Version
- Cleaning of code, enhancements.
- Localizing all the strings.
Download this release
Release Info
Developer | sean212 |
Plugin | Lockdown WP Admin |
Version | 2.3 |
Comparing to | |
See all releases |
Code changes from version 2.2 to 2.3
- README.md +6 -1
- admin-private-users.php +0 -67
- admin.php +0 -77
- bin/install-wp-tests.sh +0 -78
- composer.lock +550 -0
- lockdown-wp-admin.php +50 -164
- no-wpmu.php +4 -4
- phpunit.xml +0 -14
- readme.txt +8 -3
- src/Lockdown/Admin.php +150 -126
- src/Lockdown/Application.php +305 -237
- tests/bootstrap.php +0 -14
- tests/test-application.php +0 -63
- tests/test-core.php +0 -89
- tests/test-hideadmin.php +0 -34
- tests/test-sample.php +0 -10
- views/settings.php +47 -52
README.md
CHANGED
@@ -106,4 +106,9 @@ A very late update, sorry! Worked to fix many issues with the admin bar and the
|
|
106 |
2.2
|
107 |
* Fixing issues with other plugins
|
108 |
* Support tested for 3.9
|
109 |
-
* Large code structure changes. If you are extending the `
|
|
|
|
|
|
|
|
|
|
106 |
2.2
|
107 |
* Fixing issues with other plugins
|
108 |
* Support tested for 3.9
|
109 |
+
* Large code structure changes. If you are extending the `Lockdown_Manager` at all, you should basically check the class anew since it was seperated into Admin and Application services.
|
110 |
+
|
111 |
+
2.3
|
112 |
+
* Fixing issues with latests WordPress Version
|
113 |
+
* Cleaning of code, enhancements.
|
114 |
+
* Localizing all the strings.
|
admin-private-users.php
DELETED
@@ -1,67 +0,0 @@
|
|
1 |
-
<?php if (! defined('ABSPATH')) exit; ?>
|
2 |
-
<div class="wrap">
|
3 |
-
<div id="icon-options-general" class="icon32"></div><h2>HTTP Authentication Private Users</h2>
|
4 |
-
|
5 |
-
<?php if ( defined('LD_WP_ADMIN') && LD_WP_ADMIN == TRUE ) : ?>
|
6 |
-
<div class="updated fade"><p>Updated!</p></div>
|
7 |
-
<?php endif;
|
8 |
-
|
9 |
-
// Error message?
|
10 |
-
if ( defined('LD_ERROR') && LD_ERROR == 'delete-self') : ?>
|
11 |
-
<div class="error fade"><p>You can't delete yourself!</p></div>
|
12 |
-
<?php elseif (defined('LD_ERROR') AND LD_ERROR == 'username-exists') : ?>
|
13 |
-
<div class="error fade"><p>Username already taken.</p></div>
|
14 |
-
<?php endif; ?>
|
15 |
-
|
16 |
-
<form method="POST" action="<?php echo admin_url('admin.php?page=lockdown-private-users'); ?>">
|
17 |
-
<?php wp_nonce_field('lockdown-wp-admin'); ?>
|
18 |
-
<p>Adding users below will <em>only</em> work if you have "Private Usernames/Passwords" selected for HTTP Authentication.</p>
|
19 |
-
|
20 |
-
<p><strong>Please note a few things:</strong>
|
21 |
-
<ul>
|
22 |
-
<li>1. If you are ever locked out, you can just delete the plugin files via FTP (<code>/wp-content/plugins/lockdown-wp-admin/</code>) and you will be able to login again.</li>
|
23 |
-
<li>2. You cannot delete the current HTTP Authentication username you are using right now.</li>
|
24 |
-
|
25 |
-
<li>3. Private user HTTP Authentication will not work if you don't have a username added below.</li>
|
26 |
-
</ul>
|
27 |
-
</p>
|
28 |
-
|
29 |
-
<table class="widefat">
|
30 |
-
<thead>
|
31 |
-
<tr>
|
32 |
-
<th>Username</th>
|
33 |
-
<th>Action</th>
|
34 |
-
</tr>
|
35 |
-
</thead>
|
36 |
-
|
37 |
-
<tfoot>
|
38 |
-
|
39 |
-
<tr>
|
40 |
-
<th>Username</th>
|
41 |
-
<th>Action</th>
|
42 |
-
</tr>
|
43 |
-
|
44 |
-
</tfoot>
|
45 |
-
<tbody>
|
46 |
-
<?php if ( isset( $private_users ) && count( $private_users ) > 0 ) : ?>
|
47 |
-
<?php $nonce = wp_create_nonce('lockdown-wp-admin'); ?>
|
48 |
-
|
49 |
-
<?php foreach( $private_users as $key => $user ) : ?>
|
50 |
-
<tr>
|
51 |
-
<td><?php echo $user['user']; ?></td>
|
52 |
-
<td><a href="admin.php?page=<?php echo $_GET['page']; ?>&delete=<?php echo $key; ?>&_wpnonce=<?php echo $nonce; ?>">Delete</a></td>
|
53 |
-
</tr><?php endforeach; endif; ?>
|
54 |
-
</tbody>
|
55 |
-
</table>
|
56 |
-
|
57 |
-
<h4>Add a Private User</h4>
|
58 |
-
<p>To add a user, fill out the username and password below and click "Save Options" below.</p>
|
59 |
-
<label><input type="text" name="private_username" /> New Username</label><br />
|
60 |
-
<label><input type="password" name="private_password" /> New Password</label>
|
61 |
-
|
62 |
-
<div class="clear"></div><br />
|
63 |
-
<input type="hidden" name="did_update" value="yes_we_did">
|
64 |
-
<input class='button-primary' type='submit' name='Save' value='<?php _e('Save Options'); ?>' id='submitbutton' />
|
65 |
-
|
66 |
-
</form>
|
67 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
admin.php
DELETED
@@ -1,77 +0,0 @@
|
|
1 |
-
<?php if (! defined('ABSPATH')) exit; ?>
|
2 |
-
<div class="wrap">
|
3 |
-
<div id="icon-options-general" class="icon32"></div>
|
4 |
-
<h2>Lockdown WordPress Admin</h2>
|
5 |
-
<?php if ( defined('LD_WP_ADMIN') && LD_WP_ADMIN == TRUE ) : ?>
|
6 |
-
<div class="updated fade">
|
7 |
-
<p>Options updated!</p>
|
8 |
-
</div>
|
9 |
-
<?php endif;
|
10 |
-
if ( defined('LD_DIS_BASE') && LD_DIS_BASE == TRUE ) : ?>
|
11 |
-
<div class="updated error fade">
|
12 |
-
<p>You can't make that your URL Base! </p>
|
13 |
-
</div>
|
14 |
-
<?php endif; ?>
|
15 |
-
|
16 |
-
<p>We are going to help make WordPress a bit more secure.</p>
|
17 |
-
<p><a href="https://twitter.com/srtfisher" class="twitter-follow-button" data-show-count="false">Follow @srtfisher</a>
|
18 |
-
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script><br />
|
19 |
-
I tweet a lot of things and often post whenever I update this plugin. You should follow me <a href="http://twitter.com/srtfisher">@srtfisher</a></p>
|
20 |
-
|
21 |
-
<form method="POST" action="<?php echo admin_url('admin.php?page=lockdown-wp-admin'); ?>">
|
22 |
-
|
23 |
-
<?php wp_nonce_field('lockdown-wp-admin'); ?>
|
24 |
-
<h3>Hide WP Admin</h3>
|
25 |
-
<p>We can "hide" WordPress's administration interface from the public. If you enable this, when you access <code><?php echo admin_url(); ?></code> when you <strong>aren't</strong> logged in, you will recieve a <a href="http://en.wikipedia.org/wiki/HTTP_404">404 error page</a> instead of redirecting to the login page.</p>
|
26 |
-
<label>
|
27 |
-
<input type="checkbox" name="hide_wp_admin" value="yep" <?php if ( get_option('ld_hide_wp_admin') === 'yep' ) { ?> checked <?php } ?>>
|
28 |
-
Yes, please hide WP Admin from the user when they aren't logged in.</label>
|
29 |
-
<br />
|
30 |
-
<br />
|
31 |
-
<h3>WordPress Login URL</h3>
|
32 |
-
<label> Change the WordPress Login URL? <?php echo wp_guess_url().'/'; ?>
|
33 |
-
<input type="text" name="login_base" value="<?php echo $this->login_base; ?>" />
|
34 |
-
<br />
|
35 |
-
<em>This will change it from <?php echo wp_guess_url(); ?>/wp-login.php to whatever you put in this box. If you leave it <strong>blank</strong>, it will be disabled.<br />
|
36 |
-
Say if you put "<strong>login</strong>" into the box, your new login URL will be <?php echo home_url(); ?>/login/.</em></label>
|
37 |
-
<?php
|
38 |
-
global $auth_obj;
|
39 |
-
$url = home_url() . '/'. $this->login_base;
|
40 |
-
?>
|
41 |
-
<p>Your current login URL is <code><a href="<?php echo $url; ?>"><?php echo $url; ?></a></code>.</p>
|
42 |
-
|
43 |
-
<?php if ($this->isSuggestedAgainst()) : ?>
|
44 |
-
<div class="updated error"><p>
|
45 |
-
Your login base <strong><?php echo $this->login_base; ?></strong> is highly insecure!
|
46 |
-
We strongly reccomend using another login URL to ensure maximum security.
|
47 |
-
</p>
|
48 |
-
</div>
|
49 |
-
<?php endif; ?>
|
50 |
-
<blockquote>
|
51 |
-
<h4>Please Note Something!</h4>
|
52 |
-
<p>If you are using a cache plugin (WTC, WP Super Cache, etc), you need to enable it
|
53 |
-
to not cache the above base. That means (for most caching plugins) adding
|
54 |
-
whatever you enter into the box above into your plugins Caching Whitelist, that
|
55 |
-
is the list of URLs that your plugin doesn't cache. If you have any questions, tweet
|
56 |
-
me <a href="http://twitter.com/srtfisher">@srtfisher</a>.</p>
|
57 |
-
</blockquote>
|
58 |
-
<h3>HTTP Authentication</h3>
|
59 |
-
<p>Please read about HTTP Authentication on <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">http://en.wikipedia.org/wiki/Basic_access_authentication</a>.</p>
|
60 |
-
<?php $http_auth_type = get_option('ld_http_auth'); ?>
|
61 |
-
<label>
|
62 |
-
<input name="http_auth" type="radio" value="none" <?php if ( $http_auth_type === '' || $http_auth_type === 'none' || !$http_auth_type ) { ?>checked<?php } ?>>
|
63 |
-
Disable HTTP Auth.</label>
|
64 |
-
<div class="clear"></div>
|
65 |
-
<label>
|
66 |
-
<input type="radio" name="http_auth" <?php if ( $http_auth_type === 'wp_creds' ) { ?>checked<?php } ?> value="wp_creds">
|
67 |
-
WordPress Login Credentials</label>
|
68 |
-
<div class="clear"></div>
|
69 |
-
<label>
|
70 |
-
<input type="radio" name="http_auth" <?php if ( $http_auth_type === 'private' ) { ?>checked<?php } ?> value="private">
|
71 |
-
Private Usernames/Passwords</label>
|
72 |
-
<div class="clear"></div>
|
73 |
-
<br>
|
74 |
-
<input type="hidden" name="did_update" value="yes_we_did">
|
75 |
-
<input class='button-primary' type='submit' name='Save' value='<?php _e('Save Options'); ?>' id='submitbutton' />
|
76 |
-
</form>
|
77 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bin/install-wp-tests.sh
DELETED
@@ -1,78 +0,0 @@
|
|
1 |
-
#!/usr/bin/env bash
|
2 |
-
|
3 |
-
if [ $# -lt 3 ]; then
|
4 |
-
echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version]"
|
5 |
-
exit 1
|
6 |
-
fi
|
7 |
-
|
8 |
-
DB_NAME=$1
|
9 |
-
DB_USER=$2
|
10 |
-
DB_PASS=$3
|
11 |
-
DB_HOST=${4-localhost}
|
12 |
-
WP_VERSION=${5-latest}
|
13 |
-
|
14 |
-
WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
|
15 |
-
WP_CORE_DIR=/tmp/wordpress/
|
16 |
-
|
17 |
-
set -ex
|
18 |
-
|
19 |
-
install_wp() {
|
20 |
-
mkdir -p $WP_CORE_DIR
|
21 |
-
|
22 |
-
if [ $WP_VERSION == 'latest' ]; then
|
23 |
-
local ARCHIVE_NAME='latest'
|
24 |
-
else
|
25 |
-
local ARCHIVE_NAME="wordpress-$WP_VERSION"
|
26 |
-
fi
|
27 |
-
|
28 |
-
wget -nv -O /tmp/wordpress.tar.gz http://wordpress.org/${ARCHIVE_NAME}.tar.gz
|
29 |
-
tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
|
30 |
-
|
31 |
-
wget -nv -O $WP_CORE_DIR/wp-content/db.php https://raw.github.com/markoheijnen/wp-mysqli/master/db.php
|
32 |
-
}
|
33 |
-
|
34 |
-
install_test_suite() {
|
35 |
-
# portable in-place argument for both GNU sed and Mac OSX sed
|
36 |
-
if [[ $(uname -s) == 'Darwin' ]]; then
|
37 |
-
local ioption='-i .bak'
|
38 |
-
else
|
39 |
-
local ioption='-i'
|
40 |
-
fi
|
41 |
-
|
42 |
-
# set up testing suite
|
43 |
-
mkdir -p $WP_TESTS_DIR
|
44 |
-
cd $WP_TESTS_DIR
|
45 |
-
svn co --quiet http://develop.svn.wordpress.org/trunk/tests/phpunit/includes/
|
46 |
-
|
47 |
-
wget -nv -O wp-tests-config.php http://develop.svn.wordpress.org/trunk/wp-tests-config-sample.php
|
48 |
-
sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" wp-tests-config.php
|
49 |
-
sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" wp-tests-config.php
|
50 |
-
sed $ioption "s/yourusernamehere/$DB_USER/" wp-tests-config.php
|
51 |
-
sed $ioption "s/yourpasswordhere/$DB_PASS/" wp-tests-config.php
|
52 |
-
sed $ioption "s|localhost|${DB_HOST}|" wp-tests-config.php
|
53 |
-
}
|
54 |
-
|
55 |
-
install_db() {
|
56 |
-
# parse DB_HOST for port or socket references
|
57 |
-
local PARTS=(${DB_HOST//\:/ })
|
58 |
-
local DB_HOSTNAME=${PARTS[0]};
|
59 |
-
local DB_SOCK_OR_PORT=${PARTS[1]};
|
60 |
-
local EXTRA=""
|
61 |
-
|
62 |
-
if ! [ -z $DB_HOSTNAME ] ; then
|
63 |
-
if [[ "$DB_SOCK_OR_PORT" =~ ^[0-9]+$ ]] ; then
|
64 |
-
EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
|
65 |
-
elif ! [ -z $DB_SOCK_OR_PORT ] ; then
|
66 |
-
EXTRA=" --socket=$DB_SOCK_OR_PORT"
|
67 |
-
elif ! [ -z $DB_HOSTNAME ] ; then
|
68 |
-
EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
|
69 |
-
fi
|
70 |
-
fi
|
71 |
-
|
72 |
-
# create database
|
73 |
-
mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
|
74 |
-
}
|
75 |
-
|
76 |
-
install_wp
|
77 |
-
install_test_suite
|
78 |
-
install_db
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
composer.lock
ADDED
@@ -0,0 +1,550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_readme": [
|
3 |
+
"This file locks the dependencies of your project to a known state",
|
4 |
+
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
5 |
+
"This file is @generated automatically"
|
6 |
+
],
|
7 |
+
"hash": "480ba9924f784d7fa649fedd193acbc4",
|
8 |
+
"packages": [
|
9 |
+
{
|
10 |
+
"name": "hamcrest/hamcrest-php",
|
11 |
+
"version": "v1.2.2",
|
12 |
+
"source": {
|
13 |
+
"type": "git",
|
14 |
+
"url": "https://github.com/hamcrest/hamcrest-php.git",
|
15 |
+
"reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c"
|
16 |
+
},
|
17 |
+
"dist": {
|
18 |
+
"type": "zip",
|
19 |
+
"url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c",
|
20 |
+
"reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c",
|
21 |
+
"shasum": ""
|
22 |
+
},
|
23 |
+
"require": {
|
24 |
+
"php": ">=5.3.2"
|
25 |
+
},
|
26 |
+
"replace": {
|
27 |
+
"cordoval/hamcrest-php": "*",
|
28 |
+
"davedevelopment/hamcrest-php": "*",
|
29 |
+
"kodova/hamcrest-php": "*"
|
30 |
+
},
|
31 |
+
"require-dev": {
|
32 |
+
"phpunit/php-file-iterator": "1.3.3",
|
33 |
+
"satooshi/php-coveralls": "dev-master"
|
34 |
+
},
|
35 |
+
"type": "library",
|
36 |
+
"autoload": {
|
37 |
+
"classmap": [
|
38 |
+
"hamcrest"
|
39 |
+
],
|
40 |
+
"files": [
|
41 |
+
"hamcrest/Hamcrest.php"
|
42 |
+
]
|
43 |
+
},
|
44 |
+
"notification-url": "https://packagist.org/downloads/",
|
45 |
+
"license": [
|
46 |
+
"BSD"
|
47 |
+
],
|
48 |
+
"description": "This is the PHP port of Hamcrest Matchers",
|
49 |
+
"keywords": [
|
50 |
+
"test"
|
51 |
+
],
|
52 |
+
"time": "2015-05-11 14:41:42"
|
53 |
+
},
|
54 |
+
{
|
55 |
+
"name": "mockery/mockery",
|
56 |
+
"version": "dev-master",
|
57 |
+
"source": {
|
58 |
+
"type": "git",
|
59 |
+
"url": "https://github.com/padraic/mockery.git",
|
60 |
+
"reference": "22b57c778cfd1fc46e14bff071c5126d9cd50820"
|
61 |
+
},
|
62 |
+
"dist": {
|
63 |
+
"type": "zip",
|
64 |
+
"url": "https://api.github.com/repos/padraic/mockery/zipball/22b57c778cfd1fc46e14bff071c5126d9cd50820",
|
65 |
+
"reference": "22b57c778cfd1fc46e14bff071c5126d9cd50820",
|
66 |
+
"shasum": ""
|
67 |
+
},
|
68 |
+
"require": {
|
69 |
+
"hamcrest/hamcrest-php": "~1.1",
|
70 |
+
"lib-pcre": ">=7.0",
|
71 |
+
"php": ">=5.4.0"
|
72 |
+
},
|
73 |
+
"require-dev": {
|
74 |
+
"phpunit/phpunit": "~4.0"
|
75 |
+
},
|
76 |
+
"type": "library",
|
77 |
+
"extra": {
|
78 |
+
"branch-alias": {
|
79 |
+
"dev-master": "1.0.x-dev"
|
80 |
+
}
|
81 |
+
},
|
82 |
+
"autoload": {
|
83 |
+
"psr-0": {
|
84 |
+
"Mockery": "library/"
|
85 |
+
}
|
86 |
+
},
|
87 |
+
"notification-url": "https://packagist.org/downloads/",
|
88 |
+
"license": [
|
89 |
+
"BSD-3-Clause"
|
90 |
+
],
|
91 |
+
"authors": [
|
92 |
+
{
|
93 |
+
"name": "Pádraic Brady",
|
94 |
+
"email": "padraic.brady@gmail.com",
|
95 |
+
"homepage": "http://blog.astrumfutura.com"
|
96 |
+
},
|
97 |
+
{
|
98 |
+
"name": "Dave Marshall",
|
99 |
+
"email": "dave.marshall@atstsolutions.co.uk",
|
100 |
+
"homepage": "http://davedevelopment.co.uk"
|
101 |
+
}
|
102 |
+
],
|
103 |
+
"description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
|
104 |
+
"homepage": "http://github.com/padraic/mockery",
|
105 |
+
"keywords": [
|
106 |
+
"BDD",
|
107 |
+
"TDD",
|
108 |
+
"library",
|
109 |
+
"mock",
|
110 |
+
"mock objects",
|
111 |
+
"mockery",
|
112 |
+
"stub",
|
113 |
+
"test",
|
114 |
+
"test double",
|
115 |
+
"testing"
|
116 |
+
],
|
117 |
+
"time": "2015-09-10 18:19:39"
|
118 |
+
}
|
119 |
+
],
|
120 |
+
"packages-dev": [
|
121 |
+
{
|
122 |
+
"name": "phpunit/php-code-coverage",
|
123 |
+
"version": "1.2.x-dev",
|
124 |
+
"source": {
|
125 |
+
"type": "git",
|
126 |
+
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
127 |
+
"reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b"
|
128 |
+
},
|
129 |
+
"dist": {
|
130 |
+
"type": "zip",
|
131 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
|
132 |
+
"reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
|
133 |
+
"shasum": ""
|
134 |
+
},
|
135 |
+
"require": {
|
136 |
+
"php": ">=5.3.3",
|
137 |
+
"phpunit/php-file-iterator": ">=1.3.0@stable",
|
138 |
+
"phpunit/php-text-template": ">=1.2.0@stable",
|
139 |
+
"phpunit/php-token-stream": ">=1.1.3,<1.3.0"
|
140 |
+
},
|
141 |
+
"require-dev": {
|
142 |
+
"phpunit/phpunit": "3.7.*@dev"
|
143 |
+
},
|
144 |
+
"suggest": {
|
145 |
+
"ext-dom": "*",
|
146 |
+
"ext-xdebug": ">=2.0.5"
|
147 |
+
},
|
148 |
+
"type": "library",
|
149 |
+
"extra": {
|
150 |
+
"branch-alias": {
|
151 |
+
"dev-master": "1.2.x-dev"
|
152 |
+
}
|
153 |
+
},
|
154 |
+
"autoload": {
|
155 |
+
"classmap": [
|
156 |
+
"PHP/"
|
157 |
+
]
|
158 |
+
},
|
159 |
+
"notification-url": "https://packagist.org/downloads/",
|
160 |
+
"include-path": [
|
161 |
+
""
|
162 |
+
],
|
163 |
+
"license": [
|
164 |
+
"BSD-3-Clause"
|
165 |
+
],
|
166 |
+
"authors": [
|
167 |
+
{
|
168 |
+
"name": "Sebastian Bergmann",
|
169 |
+
"email": "sb@sebastian-bergmann.de",
|
170 |
+
"role": "lead"
|
171 |
+
}
|
172 |
+
],
|
173 |
+
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
174 |
+
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
|
175 |
+
"keywords": [
|
176 |
+
"coverage",
|
177 |
+
"testing",
|
178 |
+
"xunit"
|
179 |
+
],
|
180 |
+
"time": "2014-09-02 10:13:14"
|
181 |
+
},
|
182 |
+
{
|
183 |
+
"name": "phpunit/php-file-iterator",
|
184 |
+
"version": "dev-master",
|
185 |
+
"source": {
|
186 |
+
"type": "git",
|
187 |
+
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
188 |
+
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
|
189 |
+
},
|
190 |
+
"dist": {
|
191 |
+
"type": "zip",
|
192 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
|
193 |
+
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
|
194 |
+
"shasum": ""
|
195 |
+
},
|
196 |
+
"require": {
|
197 |
+
"php": ">=5.3.3"
|
198 |
+
},
|
199 |
+
"type": "library",
|
200 |
+
"extra": {
|
201 |
+
"branch-alias": {
|
202 |
+
"dev-master": "1.4.x-dev"
|
203 |
+
}
|
204 |
+
},
|
205 |
+
"autoload": {
|
206 |
+
"classmap": [
|
207 |
+
"src/"
|
208 |
+
]
|
209 |
+
},
|
210 |
+
"notification-url": "https://packagist.org/downloads/",
|
211 |
+
"license": [
|
212 |
+
"BSD-3-Clause"
|
213 |
+
],
|
214 |
+
"authors": [
|
215 |
+
{
|
216 |
+
"name": "Sebastian Bergmann",
|
217 |
+
"email": "sb@sebastian-bergmann.de",
|
218 |
+
"role": "lead"
|
219 |
+
}
|
220 |
+
],
|
221 |
+
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
|
222 |
+
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
|
223 |
+
"keywords": [
|
224 |
+
"filesystem",
|
225 |
+
"iterator"
|
226 |
+
],
|
227 |
+
"time": "2015-06-21 13:08:43"
|
228 |
+
},
|
229 |
+
{
|
230 |
+
"name": "phpunit/php-text-template",
|
231 |
+
"version": "1.2.1",
|
232 |
+
"source": {
|
233 |
+
"type": "git",
|
234 |
+
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
235 |
+
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
|
236 |
+
},
|
237 |
+
"dist": {
|
238 |
+
"type": "zip",
|
239 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
240 |
+
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
241 |
+
"shasum": ""
|
242 |
+
},
|
243 |
+
"require": {
|
244 |
+
"php": ">=5.3.3"
|
245 |
+
},
|
246 |
+
"type": "library",
|
247 |
+
"autoload": {
|
248 |
+
"classmap": [
|
249 |
+
"src/"
|
250 |
+
]
|
251 |
+
},
|
252 |
+
"notification-url": "https://packagist.org/downloads/",
|
253 |
+
"license": [
|
254 |
+
"BSD-3-Clause"
|
255 |
+
],
|
256 |
+
"authors": [
|
257 |
+
{
|
258 |
+
"name": "Sebastian Bergmann",
|
259 |
+
"email": "sebastian@phpunit.de",
|
260 |
+
"role": "lead"
|
261 |
+
}
|
262 |
+
],
|
263 |
+
"description": "Simple template engine.",
|
264 |
+
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
|
265 |
+
"keywords": [
|
266 |
+
"template"
|
267 |
+
],
|
268 |
+
"time": "2015-06-21 13:50:34"
|
269 |
+
},
|
270 |
+
{
|
271 |
+
"name": "phpunit/php-timer",
|
272 |
+
"version": "1.0.7",
|
273 |
+
"source": {
|
274 |
+
"type": "git",
|
275 |
+
"url": "https://github.com/sebastianbergmann/php-timer.git",
|
276 |
+
"reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
|
277 |
+
},
|
278 |
+
"dist": {
|
279 |
+
"type": "zip",
|
280 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
|
281 |
+
"reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
|
282 |
+
"shasum": ""
|
283 |
+
},
|
284 |
+
"require": {
|
285 |
+
"php": ">=5.3.3"
|
286 |
+
},
|
287 |
+
"type": "library",
|
288 |
+
"autoload": {
|
289 |
+
"classmap": [
|
290 |
+
"src/"
|
291 |
+
]
|
292 |
+
},
|
293 |
+
"notification-url": "https://packagist.org/downloads/",
|
294 |
+
"license": [
|
295 |
+
"BSD-3-Clause"
|
296 |
+
],
|
297 |
+
"authors": [
|
298 |
+
{
|
299 |
+
"name": "Sebastian Bergmann",
|
300 |
+
"email": "sb@sebastian-bergmann.de",
|
301 |
+
"role": "lead"
|
302 |
+
}
|
303 |
+
],
|
304 |
+
"description": "Utility class for timing",
|
305 |
+
"homepage": "https://github.com/sebastianbergmann/php-timer/",
|
306 |
+
"keywords": [
|
307 |
+
"timer"
|
308 |
+
],
|
309 |
+
"time": "2015-06-21 08:01:12"
|
310 |
+
},
|
311 |
+
{
|
312 |
+
"name": "phpunit/php-token-stream",
|
313 |
+
"version": "1.2.2",
|
314 |
+
"source": {
|
315 |
+
"type": "git",
|
316 |
+
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
317 |
+
"reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
|
318 |
+
},
|
319 |
+
"dist": {
|
320 |
+
"type": "zip",
|
321 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
|
322 |
+
"reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
|
323 |
+
"shasum": ""
|
324 |
+
},
|
325 |
+
"require": {
|
326 |
+
"ext-tokenizer": "*",
|
327 |
+
"php": ">=5.3.3"
|
328 |
+
},
|
329 |
+
"type": "library",
|
330 |
+
"extra": {
|
331 |
+
"branch-alias": {
|
332 |
+
"dev-master": "1.2-dev"
|
333 |
+
}
|
334 |
+
},
|
335 |
+
"autoload": {
|
336 |
+
"classmap": [
|
337 |
+
"PHP/"
|
338 |
+
]
|
339 |
+
},
|
340 |
+
"notification-url": "https://packagist.org/downloads/",
|
341 |
+
"include-path": [
|
342 |
+
""
|
343 |
+
],
|
344 |
+
"license": [
|
345 |
+
"BSD-3-Clause"
|
346 |
+
],
|
347 |
+
"authors": [
|
348 |
+
{
|
349 |
+
"name": "Sebastian Bergmann",
|
350 |
+
"email": "sb@sebastian-bergmann.de",
|
351 |
+
"role": "lead"
|
352 |
+
}
|
353 |
+
],
|
354 |
+
"description": "Wrapper around PHP's tokenizer extension.",
|
355 |
+
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
|
356 |
+
"keywords": [
|
357 |
+
"tokenizer"
|
358 |
+
],
|
359 |
+
"time": "2014-03-03 05:10:30"
|
360 |
+
},
|
361 |
+
{
|
362 |
+
"name": "phpunit/phpunit",
|
363 |
+
"version": "3.7.x-dev",
|
364 |
+
"source": {
|
365 |
+
"type": "git",
|
366 |
+
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
367 |
+
"reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6"
|
368 |
+
},
|
369 |
+
"dist": {
|
370 |
+
"type": "zip",
|
371 |
+
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6",
|
372 |
+
"reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6",
|
373 |
+
"shasum": ""
|
374 |
+
},
|
375 |
+
"require": {
|
376 |
+
"ext-ctype": "*",
|
377 |
+
"ext-dom": "*",
|
378 |
+
"ext-json": "*",
|
379 |
+
"ext-pcre": "*",
|
380 |
+
"ext-reflection": "*",
|
381 |
+
"ext-spl": "*",
|
382 |
+
"php": ">=5.3.3",
|
383 |
+
"phpunit/php-code-coverage": "~1.2",
|
384 |
+
"phpunit/php-file-iterator": "~1.3",
|
385 |
+
"phpunit/php-text-template": "~1.1",
|
386 |
+
"phpunit/php-timer": "~1.0",
|
387 |
+
"phpunit/phpunit-mock-objects": "~1.2",
|
388 |
+
"symfony/yaml": "~2.0"
|
389 |
+
},
|
390 |
+
"require-dev": {
|
391 |
+
"pear-pear.php.net/pear": "1.9.4"
|
392 |
+
},
|
393 |
+
"suggest": {
|
394 |
+
"phpunit/php-invoker": "~1.1"
|
395 |
+
},
|
396 |
+
"bin": [
|
397 |
+
"composer/bin/phpunit"
|
398 |
+
],
|
399 |
+
"type": "library",
|
400 |
+
"extra": {
|
401 |
+
"branch-alias": {
|
402 |
+
"dev-master": "3.7.x-dev"
|
403 |
+
}
|
404 |
+
},
|
405 |
+
"autoload": {
|
406 |
+
"classmap": [
|
407 |
+
"PHPUnit/"
|
408 |
+
]
|
409 |
+
},
|
410 |
+
"notification-url": "https://packagist.org/downloads/",
|
411 |
+
"include-path": [
|
412 |
+
"",
|
413 |
+
"../../symfony/yaml/"
|
414 |
+
],
|
415 |
+
"license": [
|
416 |
+
"BSD-3-Clause"
|
417 |
+
],
|
418 |
+
"authors": [
|
419 |
+
{
|
420 |
+
"name": "Sebastian Bergmann",
|
421 |
+
"email": "sebastian@phpunit.de",
|
422 |
+
"role": "lead"
|
423 |
+
}
|
424 |
+
],
|
425 |
+
"description": "The PHP Unit Testing framework.",
|
426 |
+
"homepage": "http://www.phpunit.de/",
|
427 |
+
"keywords": [
|
428 |
+
"phpunit",
|
429 |
+
"testing",
|
430 |
+
"xunit"
|
431 |
+
],
|
432 |
+
"time": "2014-10-17 09:04:17"
|
433 |
+
},
|
434 |
+
{
|
435 |
+
"name": "phpunit/phpunit-mock-objects",
|
436 |
+
"version": "1.2.x-dev",
|
437 |
+
"source": {
|
438 |
+
"type": "git",
|
439 |
+
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
|
440 |
+
"reference": "c39c4511c3b007539eb170c32cbc2af49a07351a"
|
441 |
+
},
|
442 |
+
"dist": {
|
443 |
+
"type": "zip",
|
444 |
+
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c39c4511c3b007539eb170c32cbc2af49a07351a",
|
445 |
+
"reference": "c39c4511c3b007539eb170c32cbc2af49a07351a",
|
446 |
+
"shasum": ""
|
447 |
+
},
|
448 |
+
"require": {
|
449 |
+
"php": ">=5.3.3",
|
450 |
+
"phpunit/php-text-template": ">=1.1.1@stable"
|
451 |
+
},
|
452 |
+
"require-dev": {
|
453 |
+
"phpunit/phpunit": "3.7.*@dev"
|
454 |
+
},
|
455 |
+
"suggest": {
|
456 |
+
"ext-soap": "*"
|
457 |
+
},
|
458 |
+
"type": "library",
|
459 |
+
"extra": {
|
460 |
+
"branch-alias": {
|
461 |
+
"dev-master": "1.2.x-dev"
|
462 |
+
}
|
463 |
+
},
|
464 |
+
"autoload": {
|
465 |
+
"classmap": [
|
466 |
+
"PHPUnit/"
|
467 |
+
]
|
468 |
+
},
|
469 |
+
"notification-url": "https://packagist.org/downloads/",
|
470 |
+
"include-path": [
|
471 |
+
""
|
472 |
+
],
|
473 |
+
"license": [
|
474 |
+
"BSD-3-Clause"
|
475 |
+
],
|
476 |
+
"authors": [
|
477 |
+
{
|
478 |
+
"name": "Sebastian Bergmann",
|
479 |
+
"email": "sb@sebastian-bergmann.de",
|
480 |
+
"role": "lead"
|
481 |
+
}
|
482 |
+
],
|
483 |
+
"description": "Mock Object library for PHPUnit",
|
484 |
+
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
|
485 |
+
"keywords": [
|
486 |
+
"mock",
|
487 |
+
"xunit"
|
488 |
+
],
|
489 |
+
"time": "2014-02-16 12:43:56"
|
490 |
+
},
|
491 |
+
{
|
492 |
+
"name": "symfony/yaml",
|
493 |
+
"version": "2.8.x-dev",
|
494 |
+
"source": {
|
495 |
+
"type": "git",
|
496 |
+
"url": "https://github.com/symfony/Yaml.git",
|
497 |
+
"reference": "d196cb1ac36901bde7d7fbed74ee31fdb85fd119"
|
498 |
+
},
|
499 |
+
"dist": {
|
500 |
+
"type": "zip",
|
501 |
+
"url": "https://api.github.com/repos/symfony/Yaml/zipball/d196cb1ac36901bde7d7fbed74ee31fdb85fd119",
|
502 |
+
"reference": "d196cb1ac36901bde7d7fbed74ee31fdb85fd119",
|
503 |
+
"shasum": ""
|
504 |
+
},
|
505 |
+
"require": {
|
506 |
+
"php": ">=5.3.9"
|
507 |
+
},
|
508 |
+
"require-dev": {
|
509 |
+
"symfony/phpunit-bridge": "~2.7|~3.0.0"
|
510 |
+
},
|
511 |
+
"type": "library",
|
512 |
+
"extra": {
|
513 |
+
"branch-alias": {
|
514 |
+
"dev-master": "2.8-dev"
|
515 |
+
}
|
516 |
+
},
|
517 |
+
"autoload": {
|
518 |
+
"psr-4": {
|
519 |
+
"Symfony\\Component\\Yaml\\": ""
|
520 |
+
}
|
521 |
+
},
|
522 |
+
"notification-url": "https://packagist.org/downloads/",
|
523 |
+
"license": [
|
524 |
+
"MIT"
|
525 |
+
],
|
526 |
+
"authors": [
|
527 |
+
{
|
528 |
+
"name": "Fabien Potencier",
|
529 |
+
"email": "fabien@symfony.com"
|
530 |
+
},
|
531 |
+
{
|
532 |
+
"name": "Symfony Community",
|
533 |
+
"homepage": "https://symfony.com/contributors"
|
534 |
+
}
|
535 |
+
],
|
536 |
+
"description": "Symfony Yaml Component",
|
537 |
+
"homepage": "https://symfony.com",
|
538 |
+
"time": "2015-09-14 14:15:17"
|
539 |
+
}
|
540 |
+
],
|
541 |
+
"aliases": [],
|
542 |
+
"minimum-stability": "dev",
|
543 |
+
"stability-flags": {
|
544 |
+
"mockery/mockery": 20
|
545 |
+
},
|
546 |
+
"prefer-stable": false,
|
547 |
+
"prefer-lowest": false,
|
548 |
+
"platform": [],
|
549 |
+
"platform-dev": []
|
550 |
+
}
|
lockdown-wp-admin.php
CHANGED
@@ -1,164 +1,50 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
Plugin Name: Lockdown WP Admin
|
4 |
-
Plugin URI: http://seanfisher.co/lockdown-wp-admin/
|
5 |
-
Donate link: http://seanfisher.co/donate/
|
6 |
-
Description: Securing the WordPress Administration interface by concealing the administration dashboard and changing the login page URL.
|
7 |
-
Version: 2.
|
8 |
-
Author: Sean Fisher
|
9 |
-
Author URI: http://seanfisher.co/
|
10 |
-
License: GPL
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
*
|
22 |
-
*
|
23 |
-
|
24 |
-
class
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
* Check if the Auth passed
|
52 |
-
* See {@link WP_LockAuth::getAuthPassed()}
|
53 |
-
*
|
54 |
-
* @type boolean
|
55 |
-
*/
|
56 |
-
protected $passed = FALSE;
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Admin Instance
|
60 |
-
*
|
61 |
-
* @type Lockdown_Admin
|
62 |
-
*/
|
63 |
-
public $admin;
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Application Instance
|
67 |
-
*
|
68 |
-
* @type Lockdown_Application
|
69 |
-
*/
|
70 |
-
public $application;
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Constructor
|
74 |
-
*
|
75 |
-
* @return void
|
76 |
-
*/
|
77 |
-
public function __construct()
|
78 |
-
{
|
79 |
-
// We don't like adding network wide WordPress plugins.
|
80 |
-
if (! class_exists('Disable_WPMS_Plugin_LD'))
|
81 |
-
require_once( dirname( __FILE__ ) .'/no-wpmu.php' );
|
82 |
-
|
83 |
-
require_once(LD_PLUGIN_DIR.'/src/Lockdown/Application.php');
|
84 |
-
require_once(LD_PLUGIN_DIR.'/src/Lockdown/Admin.php');
|
85 |
-
|
86 |
-
// Instantiate objects
|
87 |
-
$this->admin = new Lockdown_Admin($this);
|
88 |
-
$this->application = new Lockdown_Application($this);
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Get the users for the private creds
|
93 |
-
*
|
94 |
-
* @deprecated Moved to `Lockdown_Application::getPrivateUsers()`
|
95 |
-
**/
|
96 |
-
public function get_private_users()
|
97 |
-
{
|
98 |
-
return $this->application->getPrivateUsers();
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Set the current user
|
103 |
-
*
|
104 |
-
* @deprecated Moved to {@see Lockdown_Application::setUser()}
|
105 |
-
**/
|
106 |
-
protected function set_current_user( $array, $user )
|
107 |
-
{
|
108 |
-
return $this->application->setUser($array, $user);
|
109 |
-
}
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Retrieve the Login Base
|
113 |
-
* @return string
|
114 |
-
*/
|
115 |
-
public function getLoginBase()
|
116 |
-
{
|
117 |
-
return $this->application->getLoginBase();
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* See if the auth passed
|
122 |
-
*
|
123 |
-
* @return boolean
|
124 |
-
*/
|
125 |
-
public function getAuthPassed()
|
126 |
-
{
|
127 |
-
return (bool) $this->passed;
|
128 |
-
}
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Update the Passed Auth Value
|
132 |
-
* See {@link WP_LockAuth::getAuthPassed()}
|
133 |
-
*
|
134 |
-
* @access public
|
135 |
-
* @param boolean
|
136 |
-
*/
|
137 |
-
public function passed($value)
|
138 |
-
{
|
139 |
-
$this->passed = (bool) $value;
|
140 |
-
}
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* The function called at 'init'.
|
145 |
-
* Sets up the object
|
146 |
-
*
|
147 |
-
* @return object
|
148 |
-
* @access private
|
149 |
-
* @since 1.0
|
150 |
-
* @see do_action() Called by the 'init' action.
|
151 |
-
**/
|
152 |
-
function ld_setup_auth()
|
153 |
-
{
|
154 |
-
// Instantiate the object
|
155 |
-
$class = apply_filters('ld_class', 'WP_LockAuth');
|
156 |
-
$auth_obj = new $class();
|
157 |
-
|
158 |
-
return $auth_obj;
|
159 |
-
}
|
160 |
-
|
161 |
-
add_action('init', 'ld_setup_auth', 20);
|
162 |
-
|
163 |
-
/* End of file: lockdown-wp-admin.php */
|
164 |
-
/* Code is poetry. */
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: Lockdown WP Admin
|
4 |
+
Plugin URI: http://seanfisher.co/lockdown-wp-admin/
|
5 |
+
Donate link: http://seanfisher.co/donate/
|
6 |
+
Description: Securing the WordPress Administration interface by concealing the administration dashboard and changing the login page URL.
|
7 |
+
Version: 2.3
|
8 |
+
Author: Sean Fisher
|
9 |
+
Author URI: http://seanfisher.co/
|
10 |
+
License: GPL
|
11 |
+
Text Domain: lockdown-wp-admin
|
12 |
+
*/
|
13 |
+
|
14 |
+
if ( ! defined( 'ABSPATH' ) ) { exit; }
|
15 |
+
|
16 |
+
// Lockdown WP Admin File Name.
|
17 |
+
define( 'LD_FILE_NAME', __FILE__ );
|
18 |
+
define( 'LD_PLUGIN_DIR', dirname( __FILE__ ) );
|
19 |
+
|
20 |
+
/**
|
21 |
+
* The function called at 'init'.
|
22 |
+
* Sets up the object
|
23 |
+
*
|
24 |
+
* One can overwrite the class used by Lockdown WP Admin by filtering `ld_class`.
|
25 |
+
* Adding a filter must be done before `init`.
|
26 |
+
*
|
27 |
+
* @return object
|
28 |
+
* @access private
|
29 |
+
* @since 1.0
|
30 |
+
* @see do_action() Called by the 'init' action.
|
31 |
+
* @throws Exception
|
32 |
+
*/
|
33 |
+
function ld_setup_auth() {
|
34 |
+
// Include Manager
|
35 |
+
require_once( LD_PLUGIN_DIR . '/src/Lockdown/Manager.php' );
|
36 |
+
|
37 |
+
// Instantiate the object
|
38 |
+
$class = apply_filters( 'ld_class', 'Lockdown_Manager' );
|
39 |
+
$object = call_user_func( $class.'::instance' );
|
40 |
+
|
41 |
+
// Ensure application integrity
|
42 |
+
if ( ! ( $object instanceof Lockdown_Manager ) ) {
|
43 |
+
throw new Exception( __( 'Lockdown Manager Class must be instance of Lockdown_Manager.', 'lockdown-wp-admin' ) );
|
44 |
+
}
|
45 |
+
|
46 |
+
return $object;
|
47 |
+
}
|
48 |
+
|
49 |
+
// Add default action to `init`
|
50 |
+
add_action( 'init', 'ld_setup_auth', 20 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
no-wpmu.php
CHANGED
@@ -3,14 +3,14 @@
|
|
3 |
* We don't want to allow for this plugin to be used in WP-MS or network wide.
|
4 |
*
|
5 |
* @author Sean Fisher
|
6 |
-
|
7 |
class Disable_WPMS_Plugin_LD
|
8 |
{
|
9 |
/**
|
10 |
* Object Constructor
|
11 |
*
|
12 |
* @return void
|
13 |
-
|
14 |
function __construct()
|
15 |
{
|
16 |
register_activation_hook(LD_FILE_NAME, array( &$this, 'on_activate') );
|
@@ -20,7 +20,7 @@ class Disable_WPMS_Plugin_LD
|
|
20 |
* Called when activating the plugin
|
21 |
*
|
22 |
* @access private
|
23 |
-
|
24 |
function on_activate()
|
25 |
{
|
26 |
// Disable buggy sitewide activation in WPMU and WP 3.0
|
@@ -36,7 +36,7 @@ class Disable_WPMS_Plugin_LD
|
|
36 |
* De-activate a plugin
|
37 |
*
|
38 |
* @access private
|
39 |
-
|
40 |
public function network_activate_error()
|
41 |
{
|
42 |
// De-activate the plugin
|
3 |
* We don't want to allow for this plugin to be used in WP-MS or network wide.
|
4 |
*
|
5 |
* @author Sean Fisher
|
6 |
+
*/
|
7 |
class Disable_WPMS_Plugin_LD
|
8 |
{
|
9 |
/**
|
10 |
* Object Constructor
|
11 |
*
|
12 |
* @return void
|
13 |
+
*/
|
14 |
function __construct()
|
15 |
{
|
16 |
register_activation_hook(LD_FILE_NAME, array( &$this, 'on_activate') );
|
20 |
* Called when activating the plugin
|
21 |
*
|
22 |
* @access private
|
23 |
+
*/
|
24 |
function on_activate()
|
25 |
{
|
26 |
// Disable buggy sitewide activation in WPMU and WP 3.0
|
36 |
* De-activate a plugin
|
37 |
*
|
38 |
* @access private
|
39 |
+
*/
|
40 |
public function network_activate_error()
|
41 |
{
|
42 |
// De-activate the plugin
|
phpunit.xml
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
<phpunit
|
2 |
-
bootstrap="tests/bootstrap.php"
|
3 |
-
backupGlobals="false"
|
4 |
-
colors="true"
|
5 |
-
convertErrorsToExceptions="true"
|
6 |
-
convertNoticesToExceptions="true"
|
7 |
-
convertWarningsToExceptions="true"
|
8 |
-
>
|
9 |
-
<testsuites>
|
10 |
-
<testsuite>
|
11 |
-
<directory prefix="test-" suffix=".php">./tests/</directory>
|
12 |
-
</testsuite>
|
13 |
-
</testsuites>
|
14 |
-
</phpunit>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -4,8 +4,8 @@ Donate link: http://seanfisher.co/donate/
|
|
4 |
Link: http://seanfisher.co/lockdown-wp-admin/
|
5 |
Tags: security, secure, lockdown, vulnerability, website security, wp-admin, login, hide login, rename login, http auth, 404, lockdown, srtfisher, secure
|
6 |
Requires at least: 3.6
|
7 |
-
Tested up to: 3.
|
8 |
-
Stable tag: 2.
|
9 |
|
10 |
Lockdown WP Admin conceals the administration and login screen from intruders. It can hide WordPress Admin (/wp-admin/) and and login (/wp-login.php) as well as add HTTP authentication to the login system. We can also change the login URL from wp-login.php to whatever you'd like: /login, /log-in-here, etc.
|
11 |
|
@@ -106,4 +106,9 @@ A very late update, sorry! Worked to fix many issues with the admin bar and the
|
|
106 |
= 2.2 =
|
107 |
* Fixing issues with other plugins
|
108 |
* Support tested for 3.9
|
109 |
-
* Large code structure changes. If you are extending the `
|
|
|
|
|
|
|
|
|
|
4 |
Link: http://seanfisher.co/lockdown-wp-admin/
|
5 |
Tags: security, secure, lockdown, vulnerability, website security, wp-admin, login, hide login, rename login, http auth, 404, lockdown, srtfisher, secure
|
6 |
Requires at least: 3.6
|
7 |
+
Tested up to: 4.3.1
|
8 |
+
Stable tag: 2.3
|
9 |
|
10 |
Lockdown WP Admin conceals the administration and login screen from intruders. It can hide WordPress Admin (/wp-admin/) and and login (/wp-login.php) as well as add HTTP authentication to the login system. We can also change the login URL from wp-login.php to whatever you'd like: /login, /log-in-here, etc.
|
11 |
|
106 |
= 2.2 =
|
107 |
* Fixing issues with other plugins
|
108 |
* Support tested for 3.9
|
109 |
+
* Large code structure changes. If you are extending the `Lockdown_Manager` at all, you should basically check the class anew since it was separated into Admin and Application services.
|
110 |
+
|
111 |
+
= 2.3 =
|
112 |
+
* Fixing issues with latests WordPress Version
|
113 |
+
* Cleaning of code, enhancements.
|
114 |
+
* Localizing all the strings.
|
src/Lockdown/Admin.php
CHANGED
@@ -1,193 +1,217 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
class Lockdown_Admin {
|
3 |
/**
|
4 |
* Main Instance Storage
|
5 |
*
|
6 |
-
* @var
|
7 |
*/
|
8 |
protected $instance;
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
/**
|
11 |
* Admin Constructor
|
12 |
-
*
|
13 |
-
* @param
|
14 |
*/
|
15 |
-
public function __construct(
|
16 |
-
{
|
17 |
$this->instance = $instance;
|
18 |
|
19 |
// Add the action to setup the menu.
|
20 |
-
add_action('admin_menu', array( $this, 'add_admin_menu'));
|
21 |
}
|
22 |
|
23 |
/**
|
24 |
* Adds the admin menu
|
25 |
*
|
26 |
-
* @
|
27 |
-
|
28 |
-
public function add_admin_menu()
|
29 |
-
|
30 |
-
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
-
|
34 |
/**
|
35 |
* The callback for the admin area
|
36 |
*
|
37 |
* You need the 'manage_options' capability to get here.
|
38 |
-
|
39 |
-
public function
|
40 |
-
{
|
41 |
// Update the options
|
42 |
-
$this->
|
43 |
-
|
44 |
// The UI
|
45 |
require_once( LD_PLUGIN_DIR . '/views/settings.php' );
|
46 |
-
}
|
47 |
-
|
48 |
/**
|
49 |
* The callback for ther private users management.
|
50 |
*
|
51 |
* You need the 'manage_options' capability to get here.
|
52 |
-
|
53 |
-
public function
|
54 |
-
{
|
55 |
// Update the users options
|
56 |
-
$this->
|
57 |
-
|
58 |
// The UI
|
59 |
$private_users = $this->instance->application->getPrivateUsers();
|
60 |
-
require_once( LD_PLUGIN_DIR . '/
|
61 |
}
|
62 |
|
63 |
/**
|
64 |
* Update the options
|
65 |
*
|
66 |
* @access private
|
67 |
-
|
68 |
-
public function
|
69 |
-
|
70 |
-
if ( !isset( $_GET['page'] ) || $_GET['page'] !== 'lockdown-wp-admin' || !isset( $_POST['did_update'] ))
|
71 |
return;
|
72 |
-
|
|
|
73 |
// Nonce
|
74 |
$nonce = $_POST['_wpnonce'];
|
75 |
-
if ( ! wp_verify_nonce($nonce, 'lockdown-wp-admin') )
|
76 |
-
wp_die('Security error, please try again.');
|
77 |
-
|
|
|
78 |
// ---------------------------------------------------
|
79 |
// They're updating.
|
80 |
// ---------------------------------------------------
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
update_option('ld_http_auth', 'none' );
|
85 |
-
|
86 |
-
if ( ! isset( $_POST['hide_wp_admin'] ) )
|
87 |
-
{
|
88 |
-
update_option('ld_hide_wp_admin', 'nope');
|
89 |
-
}
|
90 |
-
else
|
91 |
-
{
|
92 |
-
if ( $_POST['hide_wp_admin'] === 'yep' )
|
93 |
-
update_option('ld_hide_wp_admin', 'yep');
|
94 |
-
else
|
95 |
-
update_option('ld_hide_wp_admin', 'nope');
|
96 |
}
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
$base =
|
102 |
-
|
|
|
103 |
$disallowed = array(
|
104 |
-
'user',
|
105 |
-
'wp-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
);
|
107 |
-
|
108 |
-
{
|
109 |
-
return
|
110 |
-
}
|
111 |
-
|
112 |
-
{
|
113 |
-
|
114 |
-
update_option('ld_login_base', $base);
|
115 |
-
$this->instance->application->setLoginBase(sanitize_title_with_dashes ( $base ));
|
116 |
}
|
117 |
}
|
118 |
-
|
119 |
-
|
120 |
-
return define('LD_WP_ADMIN', TRUE);
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
* Update the users
|
125 |
*
|
126 |
* @access private
|
127 |
-
|
128 |
-
public function
|
129 |
-
|
130 |
-
if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'lockdown-private-users')
|
131 |
-
return;
|
132 |
-
|
133 |
-
// Nonce
|
134 |
-
if ( ! isset( $_REQUEST['_wpnonce'] ) )
|
135 |
return;
|
136 |
-
|
137 |
-
|
138 |
-
if ( ! wp_verify_nonce( $
|
139 |
-
wp_die('Security error, please try again.');
|
140 |
-
|
|
|
141 |
// Add a user
|
142 |
-
if (
|
143 |
-
|
144 |
-
|
145 |
-
{
|
146 |
-
|
147 |
-
$users = $this->instance->application->getPrivateUsers();
|
148 |
-
$add['user'] = sanitize_user( $_POST['private_username'] );
|
149 |
-
$add['pass'] = trim( md5( $_POST['private_password'] ) );
|
150 |
-
|
151 |
-
// See if it exists
|
152 |
-
if ($this->instance->application->userExists($users, $add['user']))
|
153 |
-
return define('LD_ERROR', 'username-exists');
|
154 |
-
else
|
155 |
-
$users[] = $add;
|
156 |
-
|
157 |
-
update_option('ld_private_users', $users);
|
158 |
-
|
159 |
-
return define('LD_WP_ADMIN', TRUE);
|
160 |
}
|
|
|
|
|
161 |
}
|
162 |
-
|
163 |
-
// Deleting a user
|
164 |
-
if ( isset( $_GET['delete'] ) )
|
165 |
-
{
|
166 |
-
// Delete the user.
|
167 |
-
unset( $users );
|
168 |
$users = $this->instance->application->getPrivateUsers();
|
169 |
$to_delete = (int) $_GET['delete'];
|
170 |
-
|
171 |
-
if (
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
{
|
178 |
-
|
179 |
-
return define('LD_ERROR', 'delete-self');
|
180 |
}
|
181 |
-
|
182 |
-
|
183 |
-
endif;
|
184 |
-
}
|
185 |
}
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
define('LD_WP_ADMIN', TRUE);
|
190 |
-
return;
|
191 |
}
|
192 |
}
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Admin Interface for Lockdown WP Admin
|
4 |
+
*
|
5 |
+
* @package lockdown
|
6 |
+
* @codeCoverageIgnore
|
7 |
+
*/
|
8 |
class Lockdown_Admin {
|
9 |
/**
|
10 |
* Main Instance Storage
|
11 |
*
|
12 |
+
* @var Lockdown_Manager
|
13 |
*/
|
14 |
protected $instance;
|
15 |
|
16 |
+
/**
|
17 |
+
* Message Storage
|
18 |
+
*
|
19 |
+
* @var array
|
20 |
+
*/
|
21 |
+
protected $messages = array();
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Valid HTTP Auth Settings
|
25 |
+
*
|
26 |
+
* @var arry
|
27 |
+
*/
|
28 |
+
protected $valid_http_auth = array( 'none', 'wp_creds', 'private' );
|
29 |
+
|
30 |
/**
|
31 |
* Admin Constructor
|
32 |
+
*
|
33 |
+
* @param Lockdown_Manager
|
34 |
*/
|
35 |
+
public function __construct( Lockdown_Manager $instance ) {
|
|
|
36 |
$this->instance = $instance;
|
37 |
|
38 |
// Add the action to setup the menu.
|
39 |
+
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
|
40 |
}
|
41 |
|
42 |
/**
|
43 |
* Adds the admin menu
|
44 |
*
|
45 |
+
* @access private
|
46 |
+
*/
|
47 |
+
public function add_admin_menu() {
|
48 |
+
add_menu_page(
|
49 |
+
__( 'Lockdown WP', 'lockdown-wp-admin' ),
|
50 |
+
__( 'Lockdown WP', 'lockdown-wp-admin' ),
|
51 |
+
'manage_options',
|
52 |
+
'lockdown-wp-admin',
|
53 |
+
array( $this, 'display_settings_page' )
|
54 |
+
);
|
55 |
+
|
56 |
+
add_submenu_page(
|
57 |
+
'lockdown-wp-admin',
|
58 |
+
__( 'Private Users', 'lockdown-wp-admin' ),
|
59 |
+
__( 'Private Users', 'lockdown-wp-admin' ),
|
60 |
+
'manage_options',
|
61 |
+
'lockdown-private-users',
|
62 |
+
array( $this, 'display_settings_users_page' )
|
63 |
+
);
|
64 |
}
|
65 |
+
|
66 |
/**
|
67 |
* The callback for the admin area
|
68 |
*
|
69 |
* You need the 'manage_options' capability to get here.
|
70 |
+
*/
|
71 |
+
public function display_settings_page() {
|
|
|
72 |
// Update the options
|
73 |
+
$this->settings_page_update();
|
74 |
+
|
75 |
// The UI
|
76 |
require_once( LD_PLUGIN_DIR . '/views/settings.php' );
|
77 |
+
}
|
78 |
+
|
79 |
/**
|
80 |
* The callback for ther private users management.
|
81 |
*
|
82 |
* You need the 'manage_options' capability to get here.
|
83 |
+
*/
|
84 |
+
public function display_settings_users_page() {
|
|
|
85 |
// Update the users options
|
86 |
+
$this->users_page_update();
|
87 |
+
|
88 |
// The UI
|
89 |
$private_users = $this->instance->application->getPrivateUsers();
|
90 |
+
require_once( LD_PLUGIN_DIR . '/views/private-users.php' );
|
91 |
}
|
92 |
|
93 |
/**
|
94 |
* Update the options
|
95 |
*
|
96 |
* @access private
|
97 |
+
*/
|
98 |
+
public function settings_page_update() {
|
99 |
+
if ( ! isset( $_GET['page'] ) || 'lockdown-wp-admin' !== $_GET['page'] || empty( $_POST['did_update'] ) ) {
|
|
|
100 |
return;
|
101 |
+
}
|
102 |
+
|
103 |
// Nonce
|
104 |
$nonce = $_POST['_wpnonce'];
|
105 |
+
if ( ! wp_verify_nonce( $nonce, 'lockdown-wp-admin' ) ) {
|
106 |
+
wp_die( __( 'Security error, please try again.', 'lockdown-wp-admin' ) );
|
107 |
+
}
|
108 |
+
|
109 |
// ---------------------------------------------------
|
110 |
// They're updating.
|
111 |
// ---------------------------------------------------
|
112 |
+
$use_http_auth = 'none';
|
113 |
+
if ( ! empty( $_POST['http_auth'] ) && in_array( $_POST['http_auth'], $this->valid_http_auth ) ) {
|
114 |
+
$use_http_auth = $_POST['http_auth'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
+
$this->instance->application->setHttpAuth( $use_http_auth );
|
117 |
+
$this->instance->application->setHideWpAdmin( ( ! empty( $_POST['hide_wp_admin'] ) && 'yes' === $_POST['hide_wp_admin'] ) );
|
118 |
+
|
119 |
+
if ( isset( $_POST['login_base'] ) ) {
|
120 |
+
$base = sanitize_title_with_dashes( $_POST['login_base'] );
|
121 |
+
$base = str_replace( '/', '', $base );
|
122 |
+
|
123 |
$disallowed = array(
|
124 |
+
'user',
|
125 |
+
'wp-admin',
|
126 |
+
'wp-content',
|
127 |
+
'wp-includes',
|
128 |
+
'wp-feed.php',
|
129 |
+
'index',
|
130 |
+
'feed',
|
131 |
+
'rss',
|
132 |
+
'robots',
|
133 |
+
'robots.txt',
|
134 |
+
'wp-login.php',
|
135 |
+
'wp-login',
|
136 |
+
'wp-config',
|
137 |
+
'blog',
|
138 |
+
'sitemap',
|
139 |
+
'sitemap.xml',
|
140 |
);
|
141 |
+
|
142 |
+
if ( in_array( $base, $disallowed ) ) {
|
143 |
+
return $this->add_message( __( 'That login base is not permitted.', 'lockdown-wp-admin' ), 'error' );
|
144 |
+
} else {
|
145 |
+
$this->instance->application->setLoginBase( sanitize_title_with_dashes( $base ) );
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
}
|
148 |
+
|
149 |
+
$this->add_message( __( 'Settings saved.', 'lockdown-wp-admin' ) );
|
|
|
150 |
}
|
151 |
|
152 |
/**
|
153 |
* Update the users
|
154 |
*
|
155 |
* @access private
|
156 |
+
*/
|
157 |
+
public function users_page_update() {
|
158 |
+
if ( ! isset( $_GET['page'] ) || 'lockdown-private-users' !== $_GET['page'] || empty( $_REQUEST['_wpnonce'] ) ) {
|
|
|
|
|
|
|
|
|
|
|
159 |
return;
|
160 |
+
}
|
161 |
+
|
162 |
+
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'lockdown-wp-admin' ) ) {
|
163 |
+
wp_die( __( 'Security error, please try again.', 'lockdown-wp-admin' ) );
|
164 |
+
}
|
165 |
+
|
166 |
// Add a user
|
167 |
+
if ( ! empty( $_POST['private_username'] ) && ! empty( $_POST['private_password'] ) ) {
|
168 |
+
try {
|
169 |
+
$this->instance->application->addPrivateUser( $_POST['private_username'], $_POST['private_password'] );
|
170 |
+
} catch ( Exception $e ) {
|
171 |
+
return $this->add_message( $e->getMessage(), 'error' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
+
|
174 |
+
return $this->add_message( __( 'User added.', 'lockdown-wp-admin' ) );
|
175 |
}
|
176 |
+
|
177 |
+
// Deleting a user (have to use isset since 'delete' could be 0)
|
178 |
+
if ( isset( $_GET['delete'] ) ) {
|
|
|
|
|
|
|
179 |
$users = $this->instance->application->getPrivateUsers();
|
180 |
$to_delete = (int) $_GET['delete'];
|
181 |
+
|
182 |
+
if ( ! empty( $users ) ) {
|
183 |
+
foreach ( $users as $key => $val ) {
|
184 |
+
if ( $key === $to_delete ) {
|
185 |
+
if ( $to_delete === $this->instance->application->current_user ) {
|
186 |
+
// They can't delete themself.
|
187 |
+
return $this->add_message( __( 'You cannot delete yourself.', 'lockdown-wp-admin' ) );
|
188 |
+
} else {
|
189 |
+
unset( $users[ $key ] );
|
|
|
190 |
}
|
191 |
+
}
|
192 |
+
}
|
|
|
|
|
193 |
}
|
194 |
+
|
195 |
+
$this->instance->application->setPrivateUsers( $users );
|
196 |
+
$this->add_message( __( 'User deleted.', 'lockdown-wp-admin' ) );
|
|
|
|
|
197 |
}
|
198 |
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Add a message to display
|
202 |
+
*
|
203 |
+
* @param string $message
|
204 |
+
*/
|
205 |
+
public function add_message( $message, $type = 'normal' ) {
|
206 |
+
$this->messages[] = compact( 'message', 'type' );
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Retrive messages
|
211 |
+
*
|
212 |
+
* @return array
|
213 |
+
*/
|
214 |
+
public function get_messages() {
|
215 |
+
return $this->messages;
|
216 |
+
}
|
217 |
+
}
|
src/Lockdown/Application.php
CHANGED
@@ -1,9 +1,14 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
|
|
2 |
class Lockdown_Application {
|
3 |
/**
|
4 |
* Main Instance Storage
|
5 |
*
|
6 |
-
* @var
|
7 |
*/
|
8 |
protected $instance;
|
9 |
|
@@ -11,21 +16,20 @@ class Lockdown_Application {
|
|
11 |
* The base to get the login url
|
12 |
*
|
13 |
* @access private
|
14 |
-
|
15 |
protected $login_base;
|
16 |
|
17 |
/**
|
18 |
* Admin Constructor
|
19 |
-
*
|
20 |
-
* @param
|
21 |
*/
|
22 |
-
public function __construct(
|
23 |
-
{
|
24 |
$this->instance = $instance;
|
25 |
|
26 |
// Setup the plugin.
|
27 |
$this->ininitializeConceal();
|
28 |
-
|
29 |
// Hide the login form
|
30 |
$this->renameLogin();
|
31 |
}
|
@@ -33,37 +37,43 @@ class Lockdown_Application {
|
|
33 |
/**
|
34 |
* Setup hiding wp-admin
|
35 |
*/
|
36 |
-
protected function ininitializeConceal()
|
37 |
-
{
|
38 |
-
$opt = get_option('ld_hide_wp_admin');
|
39 |
-
|
40 |
// Nope, they didn't enable it.
|
41 |
-
if ( $
|
42 |
-
|
|
|
|
|
43 |
// We're gonna hide it.
|
44 |
-
$no_check_files =
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
// We only will hide it if we are in admin (/wp-admin/)
|
61 |
-
if ( is_admin() )
|
62 |
-
{
|
63 |
// Non logged in users.
|
64 |
-
if ( ! is_user_logged_in() )
|
65 |
$this->throw404();
|
66 |
-
|
|
|
67 |
// Setup HTTP auth.
|
68 |
$this->setupHttpCheck();
|
69 |
}
|
@@ -74,123 +84,126 @@ class Lockdown_Application {
|
|
74 |
*
|
75 |
* @param void
|
76 |
* @return void
|
77 |
-
|
78 |
-
public function throw404()
|
79 |
-
{
|
80 |
// Change WP Query
|
81 |
global $wp_query;
|
82 |
$wp_query->set_404();
|
83 |
-
status_header(404);
|
84 |
|
85 |
// Disable that pesky Admin Bar
|
86 |
-
add_filter('show_admin_bar', '__return_false', 900);
|
87 |
-
remove_action( 'admin_footer', 'wp_admin_bar_render', 10);
|
88 |
-
remove_action('wp_head', 'wp_admin_bar_header', 10);
|
89 |
-
remove_action('wp_head', '_admin_bar_bump_cb', 10);
|
90 |
wp_dequeue_script( 'admin-bar' );
|
91 |
wp_dequeue_style( 'admin-bar' );
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
// Template
|
94 |
-
$four_tpl = apply_filters('LD_404', get_404_template());
|
95 |
|
96 |
// Handle the admin bar
|
97 |
-
@define('APP_REQUEST',
|
98 |
-
@define('DOING_AJAX',
|
99 |
-
|
100 |
-
if ( empty($four_tpl)
|
101 |
-
{
|
102 |
// We're gonna try and get TwentyTen's one
|
103 |
-
$
|
104 |
-
|
105 |
-
if (file_exists($
|
106 |
-
require($
|
107 |
-
else
|
108 |
-
wp_die('404 - File not found!', '', array('response' => 404));
|
109 |
-
|
110 |
-
else
|
111 |
-
{
|
112 |
// Their theme has a template!
|
113 |
require( $four_tpl );
|
114 |
}
|
115 |
-
|
116 |
// Either way, it's gonna stop right here.
|
117 |
exit;
|
118 |
}
|
119 |
|
120 |
|
121 |
-
|
122 |
/**
|
123 |
* Rename the login URL
|
124 |
*
|
125 |
-
*
|
126 |
* @see do_action() Calls `ld_login_page` right before we call `wp-login.php`
|
127 |
* @access public
|
128 |
-
|
129 |
-
public function renameLogin()
|
130 |
-
|
131 |
-
$this->login_base = get_option('ld_login_base');
|
132 |
|
133 |
// It's not enabled.
|
134 |
-
if ( $this->login_base
|
135 |
-
|
136 |
-
|
137 |
// Setup the filters for the new login form
|
138 |
-
add_filter('wp_redirect', array( &$this, '
|
139 |
-
add_filter('network_site_url', array( &$this, '
|
140 |
-
add_filter('site_url', array( &$this, '
|
141 |
-
|
142 |
// We need to get the URL
|
143 |
// This means we need to take the current URL,
|
144 |
// strip it of an WordPress path (if the blog is located @ /blog/)
|
145 |
// And then remove the query string
|
146 |
// We also need to remove the index.php from the URL if it exists
|
147 |
-
|
148 |
// The blog's URL
|
149 |
-
$blog_url = trailingslashit( get_bloginfo('url') );
|
150 |
-
|
151 |
// The Current URL
|
152 |
$schema = is_ssl() ? 'https://' : 'http://';
|
153 |
$current_url = $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
154 |
-
|
155 |
$request_url = str_replace( $blog_url, '', $current_url );
|
156 |
-
$request_url = str_replace('index.php/', '', $request_url);
|
157 |
-
|
158 |
$url_parts = explode( '?', $request_url, 2 );
|
159 |
$base = $url_parts[0];
|
160 |
|
161 |
// Remove trailing slash
|
162 |
-
$base = rtrim($base,
|
163 |
$exp = explode( '/', $base, 2 );
|
164 |
$super_base = end( $exp );
|
165 |
|
166 |
// Are they visiting wp-login.php?
|
167 |
-
if (
|
168 |
$this->throw404();
|
169 |
-
|
|
|
170 |
// Is this the "login" url?
|
171 |
-
if ( $base !== $this->getLoginBase() )
|
172 |
-
return
|
|
|
173 |
|
174 |
// We dont' want a WP plugin caching this page
|
175 |
-
@define('NO_CACHE',
|
176 |
-
@define('WTC_IN_MINIFY',
|
177 |
-
@define('WP_CACHE',
|
178 |
-
|
179 |
// Hook onto this
|
180 |
-
do_action('ld_login_page');
|
181 |
-
|
|
|
|
|
|
|
182 |
include ABSPATH . '/wp-login.php';
|
183 |
exit;
|
184 |
}
|
185 |
-
|
186 |
/**
|
187 |
* Filters out wp-login to whatever they named it
|
188 |
*
|
189 |
* @access public
|
190 |
-
|
191 |
-
public function
|
192 |
-
|
193 |
-
return str_replace('wp-login.php', $this->getLoginBase(), $str);
|
194 |
}
|
195 |
|
196 |
/**
|
@@ -198,95 +211,92 @@ class Lockdown_Application {
|
|
198 |
* Here, we only check if it's enabled
|
199 |
*
|
200 |
* @access protected
|
201 |
-
|
202 |
-
protected function setupHttpCheck($option =
|
203 |
-
{
|
204 |
// We save what type of auth we're doing here.
|
205 |
-
if (! $option)
|
206 |
-
$option =
|
207 |
-
|
|
|
208 |
// What type of auth are we doing?
|
209 |
-
switch( $option )
|
210 |
-
{
|
211 |
// HTTP auth is going to ask for their WordPress creds.
|
212 |
case 'wp_creds' :
|
213 |
$creds = $this->retrieveAuthCredentials();
|
214 |
|
215 |
-
if (! $creds )
|
216 |
$this->unauthorizedArea(); // Invalid credentials
|
217 |
-
|
218 |
// Are they already logged in as this?
|
219 |
$current_uid = get_current_user_id();
|
220 |
-
|
221 |
// We fixed this for use with non WP-MS sites
|
222 |
-
$requested_user = get_user_by('login', $creds['username']);
|
223 |
-
|
224 |
// Not a valid user.
|
225 |
-
if (! $requested_user )
|
226 |
-
$this->unauthorizedArea();
|
227 |
-
|
228 |
// The correct User ID.
|
229 |
$requested_uid = (int) $requested_user->ID;
|
230 |
-
|
231 |
// Already logged in?
|
232 |
-
if ( $current_uid === $requested_uid )
|
233 |
-
return $this->instance->passed(true);
|
234 |
-
|
235 |
// Attempt to sign them in if they aren't already
|
236 |
-
if (! is_user_logged_in() ) :
|
237 |
// Try it via wp_signon
|
238 |
$creds = array();
|
239 |
$creds['user_login'] = $creds['username'];
|
240 |
$creds['user_password'] = $creds['password'];
|
241 |
$creds['remember'] = true;
|
242 |
$user = wp_signon( $creds, false );
|
243 |
-
|
244 |
// In error
|
245 |
-
if ( is_wp_error($user) )
|
246 |
-
return $this->unauthorizedArea();
|
247 |
endif;
|
248 |
-
|
249 |
// They passed!
|
250 |
-
$this->passed(true);
|
251 |
break;
|
252 |
-
|
253 |
// Private list of users to check
|
254 |
case 'private' :
|
255 |
$users = $this->getPrivateUsers();
|
256 |
-
|
257 |
// We want a user to exist.
|
258 |
// If nobody is found, we won't lock them out!
|
259 |
-
if ( ! $users || ! is_array( $users ) )
|
260 |
-
return;
|
261 |
-
|
262 |
// Let's NOT lock everybody out
|
263 |
-
if ( count( $users ) < 1 )
|
264 |
-
return;
|
265 |
-
|
266 |
// Get the HTTP auth creds
|
267 |
$creds = $this->retrieveAuthCredentials();
|
268 |
-
|
269 |
// Invalid creds
|
270 |
-
if (! $creds )
|
271 |
$this->unauthorizedArea();
|
272 |
-
|
273 |
-
// Did they enter a valid user?
|
274 |
-
if ( $this->matchUserToArray( $users, $creds['username'], $creds['password'] ) )
|
275 |
-
{
|
276 |
-
$this->instance->passed(true);
|
277 |
-
return $this->setUser( $users, $creds['username'] );
|
278 |
}
|
279 |
-
|
280 |
-
|
|
|
|
|
|
|
|
|
281 |
return $this->unauthorizedArea();
|
282 |
}
|
283 |
-
|
284 |
break;
|
285 |
-
|
286 |
// Unknown type of auth
|
287 |
default :
|
288 |
-
$this->instance->passed(true);
|
289 |
-
return
|
290 |
}
|
291 |
}
|
292 |
|
@@ -296,15 +306,15 @@ class Lockdown_Application {
|
|
296 |
*
|
297 |
* @access private
|
298 |
* @return void
|
299 |
-
|
300 |
-
protected function unauthorizedArea()
|
301 |
-
{
|
302 |
// Disable if there is a text file there.
|
303 |
-
if ( file_exists(LD_PLUGIN_DIR.'/disable_auth.txt'))
|
304 |
return;
|
305 |
-
|
306 |
-
|
307 |
-
header('
|
|
|
308 |
echo '<h1>Authorization Required.</h1>';
|
309 |
exit;
|
310 |
}
|
@@ -313,15 +323,15 @@ class Lockdown_Application {
|
|
313 |
* Set the current user
|
314 |
*
|
315 |
* @access private
|
316 |
-
* @param
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
{
|
323 |
-
if ( $val['user'] === $user )
|
324 |
$this->current_user = $key;
|
|
|
|
|
325 |
}
|
326 |
}
|
327 |
|
@@ -329,144 +339,202 @@ class Lockdown_Application {
|
|
329 |
* Get the current file name
|
330 |
*
|
331 |
* @return string JUST the file name
|
332 |
-
|
333 |
-
public function retrieveFile()
|
334 |
-
{
|
335 |
// We're gonna hide it.
|
336 |
-
$no_check_files = array('async-upload.php');
|
337 |
-
$no_check_files = apply_filters('no_check_files', $no_check_files);
|
338 |
-
|
339 |
-
$script_filename = empty($_SERVER['SCRIPT_FILENAME'])
|
340 |
? $_SERVER['PATH_TRANSLATED']
|
341 |
: $_SERVER['SCRIPT_FILENAME'];
|
342 |
-
$explode = explode('/', $script_filename );
|
343 |
return end( $explode );
|
344 |
}
|
345 |
-
|
346 |
/**
|
347 |
* Check an internal array of users against a passed user and pass
|
348 |
*
|
349 |
* @access protected
|
350 |
* @return bool
|
351 |
*
|
352 |
-
* @param array
|
353 |
* @param string $user The username to check for
|
354 |
* @param string $pass The password to check for (plain text)
|
355 |
-
|
356 |
-
protected function matchUserToArray( $array, $user, $pass )
|
357 |
-
|
358 |
-
|
359 |
-
{
|
360 |
-
if (! isset($val['user']) || ! isset($val['pass']))
|
361 |
continue;
|
|
|
362 |
|
363 |
-
if ( $val['user'] === $user && md5( $pass ) === $val['pass'] )
|
364 |
-
return
|
|
|
365 |
}
|
366 |
-
|
367 |
-
return FALSE;
|
368 |
-
}
|
369 |
-
|
370 |
-
/**
|
371 |
-
* See if a user exists in the array
|
372 |
-
*
|
373 |
-
* @access public
|
374 |
-
* @return boolean
|
375 |
-
* @param array Array of users
|
376 |
-
* @param string
|
377 |
-
*/
|
378 |
-
public function userExists($array, $user)
|
379 |
-
{
|
380 |
-
if (count($array) == 0) return FALSE;
|
381 |
-
|
382 |
-
foreach ($array as $k => $v) :
|
383 |
-
if ($v['user'] == $user)
|
384 |
-
return TRUE;
|
385 |
-
endforeach;
|
386 |
|
387 |
-
return
|
388 |
}
|
389 |
|
390 |
/**
|
391 |
-
* See if a login base is suggested
|
392 |
*
|
393 |
* @return boolean
|
394 |
*/
|
395 |
-
public function isSuggestedAgainst()
|
396 |
-
|
397 |
-
return (in_array($this->login_base, array(
|
398 |
'login',
|
399 |
'admin',
|
400 |
'user-login',
|
401 |
-
))
|
402 |
}
|
403 |
|
404 |
/**
|
405 |
* Retrieve the login base
|
406 |
*
|
407 |
* @return string
|
408 |
-
* @param
|
409 |
*/
|
410 |
-
public function getLoginBase($default = '')
|
411 |
-
|
412 |
-
return ($this->login_base) ? $this->login_base : $default;
|
413 |
}
|
414 |
|
415 |
/**
|
416 |
-
*
|
417 |
*
|
418 |
* @param string
|
419 |
*/
|
420 |
-
public function setLoginBase($base = '')
|
421 |
-
|
422 |
$this->login_base = $base;
|
423 |
return $this;
|
424 |
}
|
425 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
/**
|
427 |
* Get a username and password from the Basic HTTP auth
|
428 |
*
|
429 |
* @return array|bool
|
430 |
-
|
431 |
-
public function retrieveAuthCredentials()
|
432 |
-
{
|
433 |
// Since PHP saves the HTTP Password in a bunch of places, we have to be able to test for all of them
|
434 |
-
$username = $password =
|
435 |
-
|
436 |
-
// mod_php
|
437 |
-
if (isset($_SERVER['PHP_AUTH_USER']))
|
438 |
-
{
|
439 |
-
$username = (isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'] : NULL;
|
440 |
-
$password = (isset($_SERVER['PHP_AUTH_PW'])) ? $_SERVER['PHP_AUTH_PW'] : NULL;
|
441 |
-
}
|
442 |
|
443 |
-
//
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
|
|
|
|
449 |
}
|
450 |
}
|
451 |
-
|
452 |
// Check them - if they're null a/o empty, they're invalid.
|
453 |
-
if ( is_null($username) OR is_null($password) OR empty($username) OR empty($password))
|
454 |
-
return
|
455 |
-
else
|
456 |
-
return
|
|
|
457 |
}
|
458 |
|
459 |
/**
|
460 |
* Get the users for the private creds
|
461 |
*
|
462 |
* @access private
|
463 |
-
|
464 |
-
public function getPrivateUsers()
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
471 |
}
|
472 |
-
}
|
1 |
<?php
|
2 |
+
/**
|
3 |
+
* Application Layer of Lockdown WP Admin
|
4 |
+
*
|
5 |
+
* @package lockdown
|
6 |
+
*/
|
7 |
class Lockdown_Application {
|
8 |
/**
|
9 |
* Main Instance Storage
|
10 |
*
|
11 |
+
* @var Lockdown_Manager
|
12 |
*/
|
13 |
protected $instance;
|
14 |
|
16 |
* The base to get the login url
|
17 |
*
|
18 |
* @access private
|
19 |
+
*/
|
20 |
protected $login_base;
|
21 |
|
22 |
/**
|
23 |
* Admin Constructor
|
24 |
+
*
|
25 |
+
* @param Lockdown_Manager
|
26 |
*/
|
27 |
+
public function __construct( Lockdown_Manager $instance ) {
|
|
|
28 |
$this->instance = $instance;
|
29 |
|
30 |
// Setup the plugin.
|
31 |
$this->ininitializeConceal();
|
32 |
+
|
33 |
// Hide the login form
|
34 |
$this->renameLogin();
|
35 |
}
|
37 |
/**
|
38 |
* Setup hiding wp-admin
|
39 |
*/
|
40 |
+
protected function ininitializeConceal() {
|
|
|
|
|
|
|
41 |
// Nope, they didn't enable it.
|
42 |
+
if ( ! $this->is_hiding_admin() ) {
|
43 |
+
return;
|
44 |
+
}
|
45 |
+
|
46 |
// We're gonna hide it.
|
47 |
+
$no_check_files = apply_filters( 'no_check_files',
|
48 |
+
array( 'async-upload.php', 'admin-ajax.php', 'wp-app.php' )
|
49 |
+
);
|
50 |
+
|
51 |
+
if ( empty( $_SERVER['SCRIPT_FILENAME'] ) ) {
|
52 |
+
$script_filename = $_SERVER['PATH_TRANSLATED'];
|
53 |
+
} else {
|
54 |
+
$script_filename = $_SERVER['SCRIPT_FILENAME'];
|
55 |
+
}
|
56 |
+
|
57 |
+
$explode = explode( '/', $script_filename );
|
58 |
+
$file = array_pop( $explode );
|
59 |
+
|
60 |
+
// Disable for WP-CLI
|
61 |
+
if ( defined( 'WP_CLI' ) and WP_CLI ) {
|
62 |
+
return $this->instance->passed( true );
|
63 |
+
}
|
64 |
+
|
65 |
+
// If request is for a file we're ignoring
|
66 |
+
if ( in_array( $file, $no_check_files ) ) {
|
67 |
+
return $this->instance->passed( true );
|
68 |
+
}
|
69 |
+
|
70 |
// We only will hide it if we are in admin (/wp-admin/)
|
71 |
+
if ( is_admin() ) {
|
|
|
72 |
// Non logged in users.
|
73 |
+
if ( ! is_user_logged_in() ) {
|
74 |
$this->throw404();
|
75 |
+
}
|
76 |
+
|
77 |
// Setup HTTP auth.
|
78 |
$this->setupHttpCheck();
|
79 |
}
|
84 |
*
|
85 |
* @param void
|
86 |
* @return void
|
87 |
+
*/
|
88 |
+
public function throw404() {
|
|
|
89 |
// Change WP Query
|
90 |
global $wp_query;
|
91 |
$wp_query->set_404();
|
92 |
+
status_header( 404 );
|
93 |
|
94 |
// Disable that pesky Admin Bar
|
95 |
+
add_filter( 'show_admin_bar', '__return_false', 900 );
|
96 |
+
remove_action( 'admin_footer', 'wp_admin_bar_render', 10 );
|
97 |
+
remove_action( 'wp_head', 'wp_admin_bar_header', 10 );
|
98 |
+
remove_action( 'wp_head', '_admin_bar_bump_cb', 10 );
|
99 |
wp_dequeue_script( 'admin-bar' );
|
100 |
wp_dequeue_style( 'admin-bar' );
|
101 |
|
102 |
+
// Complete override of the 404 handling
|
103 |
+
if ( has_action( 'ld_on_invalid_access' ) ) {
|
104 |
+
do_action( 'ld_on_invalid_access', array( $this ) );
|
105 |
+
exit;
|
106 |
+
}
|
107 |
+
|
108 |
// Template
|
109 |
+
$four_tpl = apply_filters( 'LD_404', get_404_template() );
|
110 |
|
111 |
// Handle the admin bar
|
112 |
+
@define( 'APP_REQUEST', true );
|
113 |
+
@define( 'DOING_AJAX', true );
|
114 |
+
|
115 |
+
if ( empty( $four_tpl ) or ! file_exists( $four_tpl ) ) {
|
|
|
116 |
// We're gonna try and get TwentyTen's one
|
117 |
+
$wp_theme_404 = apply_filters( 'LD_404_FALLBACK', WP_CONTENT_DIR . '/themes/twentyfifteen/404.php' );
|
118 |
+
|
119 |
+
if ( file_exists( $wp_theme_404 ) ) {
|
120 |
+
require( $wp_theme_404 );
|
121 |
+
} else {
|
122 |
+
wp_die( '404 - File not found!', '', array( 'response' => 404 ) );
|
123 |
+
}
|
124 |
+
} else {
|
|
|
125 |
// Their theme has a template!
|
126 |
require( $four_tpl );
|
127 |
}
|
128 |
+
|
129 |
// Either way, it's gonna stop right here.
|
130 |
exit;
|
131 |
}
|
132 |
|
133 |
|
134 |
+
|
135 |
/**
|
136 |
* Rename the login URL
|
137 |
*
|
|
|
138 |
* @see do_action() Calls `ld_login_page` right before we call `wp-login.php`
|
139 |
* @access public
|
140 |
+
*/
|
141 |
+
public function renameLogin() {
|
142 |
+
$this->login_base = get_option( 'ld_login_base' );
|
|
|
143 |
|
144 |
// It's not enabled.
|
145 |
+
if ( empty( $this->login_base ) || ! $this->login_base ) { return; }
|
146 |
+
|
|
|
147 |
// Setup the filters for the new login form
|
148 |
+
add_filter( 'wp_redirect', array( &$this, 'filterLoginUrl' ) );
|
149 |
+
add_filter( 'network_site_url', array( &$this, 'filterLoginUrl' ) );
|
150 |
+
add_filter( 'site_url', array( &$this, 'filterLoginUrl' ) );
|
151 |
+
|
152 |
// We need to get the URL
|
153 |
// This means we need to take the current URL,
|
154 |
// strip it of an WordPress path (if the blog is located @ /blog/)
|
155 |
// And then remove the query string
|
156 |
// We also need to remove the index.php from the URL if it exists
|
|
|
157 |
// The blog's URL
|
158 |
+
$blog_url = trailingslashit( get_bloginfo( 'url' ) );
|
159 |
+
|
160 |
// The Current URL
|
161 |
$schema = is_ssl() ? 'https://' : 'http://';
|
162 |
$current_url = $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
163 |
+
|
164 |
$request_url = str_replace( $blog_url, '', $current_url );
|
165 |
+
$request_url = str_replace( 'index.php/', '', $request_url );
|
166 |
+
|
167 |
$url_parts = explode( '?', $request_url, 2 );
|
168 |
$base = $url_parts[0];
|
169 |
|
170 |
// Remove trailing slash
|
171 |
+
$base = rtrim( $base,'/' );
|
172 |
$exp = explode( '/', $base, 2 );
|
173 |
$super_base = end( $exp );
|
174 |
|
175 |
// Are they visiting wp-login.php?
|
176 |
+
if ( 'wp-login.php' === $super_base ) {
|
177 |
$this->throw404();
|
178 |
+
}
|
179 |
+
|
180 |
// Is this the "login" url?
|
181 |
+
if ( $base !== $this->getLoginBase() ) {
|
182 |
+
return false;
|
183 |
+
}
|
184 |
|
185 |
// We dont' want a WP plugin caching this page
|
186 |
+
@define( 'NO_CACHE', true );
|
187 |
+
@define( 'WTC_IN_MINIFY', true );
|
188 |
+
@define( 'WP_CACHE', false );
|
189 |
+
|
190 |
// Hook onto this
|
191 |
+
do_action( 'ld_login_page' );
|
192 |
+
|
193 |
+
// Prevent errors from defining constants again
|
194 |
+
error_reporting( E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR );
|
195 |
+
|
196 |
include ABSPATH . '/wp-login.php';
|
197 |
exit;
|
198 |
}
|
199 |
+
|
200 |
/**
|
201 |
* Filters out wp-login to whatever they named it
|
202 |
*
|
203 |
* @access public
|
204 |
+
*/
|
205 |
+
public function filterLoginUrl( $str = '' ) {
|
206 |
+
return str_replace( 'wp-login.php', $this->getLoginBase(), $str );
|
|
|
207 |
}
|
208 |
|
209 |
/**
|
211 |
* Here, we only check if it's enabled
|
212 |
*
|
213 |
* @access protected
|
214 |
+
*/
|
215 |
+
protected function setupHttpCheck( $option = null ) {
|
|
|
216 |
// We save what type of auth we're doing here.
|
217 |
+
if ( ! $option ) {
|
218 |
+
$option = $this->getHttpAuth();
|
219 |
+
}
|
220 |
+
|
221 |
// What type of auth are we doing?
|
222 |
+
switch ( $option ) {
|
|
|
223 |
// HTTP auth is going to ask for their WordPress creds.
|
224 |
case 'wp_creds' :
|
225 |
$creds = $this->retrieveAuthCredentials();
|
226 |
|
227 |
+
if ( ! $creds ) {
|
228 |
$this->unauthorizedArea(); // Invalid credentials
|
229 |
+
}
|
230 |
// Are they already logged in as this?
|
231 |
$current_uid = get_current_user_id();
|
232 |
+
|
233 |
// We fixed this for use with non WP-MS sites
|
234 |
+
$requested_user = get_user_by( 'login', $creds['username'] );
|
235 |
+
|
236 |
// Not a valid user.
|
237 |
+
if ( ! $requested_user ) {
|
238 |
+
$this->unauthorizedArea(); }
|
239 |
+
|
240 |
// The correct User ID.
|
241 |
$requested_uid = (int) $requested_user->ID;
|
242 |
+
|
243 |
// Already logged in?
|
244 |
+
if ( $current_uid === $requested_uid ) {
|
245 |
+
return $this->instance->passed( true ); }
|
246 |
+
|
247 |
// Attempt to sign them in if they aren't already
|
248 |
+
if ( ! is_user_logged_in() ) :
|
249 |
// Try it via wp_signon
|
250 |
$creds = array();
|
251 |
$creds['user_login'] = $creds['username'];
|
252 |
$creds['user_password'] = $creds['password'];
|
253 |
$creds['remember'] = true;
|
254 |
$user = wp_signon( $creds, false );
|
255 |
+
|
256 |
// In error
|
257 |
+
if ( is_wp_error( $user ) ) {
|
258 |
+
return $this->unauthorizedArea(); }
|
259 |
endif;
|
260 |
+
|
261 |
// They passed!
|
262 |
+
$this->passed( true );
|
263 |
break;
|
264 |
+
|
265 |
// Private list of users to check
|
266 |
case 'private' :
|
267 |
$users = $this->getPrivateUsers();
|
268 |
+
|
269 |
// We want a user to exist.
|
270 |
// If nobody is found, we won't lock them out!
|
271 |
+
if ( ! $users || ! is_array( $users ) ) {
|
272 |
+
return; }
|
273 |
+
|
274 |
// Let's NOT lock everybody out
|
275 |
+
if ( count( $users ) < 1 ) {
|
276 |
+
return; }
|
277 |
+
|
278 |
// Get the HTTP auth creds
|
279 |
$creds = $this->retrieveAuthCredentials();
|
280 |
+
|
281 |
// Invalid creds
|
282 |
+
if ( ! $creds ) {
|
283 |
$this->unauthorizedArea();
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
}
|
285 |
+
|
286 |
+
// Did they enter a valid user?
|
287 |
+
if ( $this->matchUserToArray( $users, $creds['username'], $creds['password'] ) ) {
|
288 |
+
$this->instance->passed( true );
|
289 |
+
return $this->setUser( $creds['username'] );
|
290 |
+
} else {
|
291 |
return $this->unauthorizedArea();
|
292 |
}
|
293 |
+
|
294 |
break;
|
295 |
+
|
296 |
// Unknown type of auth
|
297 |
default :
|
298 |
+
$this->instance->passed( true );
|
299 |
+
return false;
|
300 |
}
|
301 |
}
|
302 |
|
306 |
*
|
307 |
* @access private
|
308 |
* @return void
|
309 |
+
*/
|
310 |
+
protected function unauthorizedArea() {
|
|
|
311 |
// Disable if there is a text file there.
|
312 |
+
if ( file_exists( LD_PLUGIN_DIR . '/disable_auth.txt' ) ) {
|
313 |
return;
|
314 |
+
}
|
315 |
+
|
316 |
+
header( 'WWW-Authenticate: Basic realm="'. esc_attr( $this->instance->relm ) . '"' );
|
317 |
+
header( 'HTTP/1.0 401 Unauthorized' );
|
318 |
echo '<h1>Authorization Required.</h1>';
|
319 |
exit;
|
320 |
}
|
323 |
* Set the current user
|
324 |
*
|
325 |
* @access private
|
326 |
+
* @param string $username
|
327 |
+
*/
|
328 |
+
public function setUser( $username ) {
|
329 |
+
$users = $this->getPrivateUsers();
|
330 |
+
foreach ( $users as $key => $val ) {
|
331 |
+
if ( $val['user'] === $username ) {
|
|
|
|
|
332 |
$this->current_user = $key;
|
333 |
+
return $this->current_user;
|
334 |
+
}
|
335 |
}
|
336 |
}
|
337 |
|
339 |
* Get the current file name
|
340 |
*
|
341 |
* @return string JUST the file name
|
342 |
+
*/
|
343 |
+
public function retrieveFile() {
|
|
|
344 |
// We're gonna hide it.
|
345 |
+
$no_check_files = array( 'async-upload.php' );
|
346 |
+
$no_check_files = apply_filters( 'no_check_files', $no_check_files );
|
347 |
+
|
348 |
+
$script_filename = empty( $_SERVER['SCRIPT_FILENAME'] )
|
349 |
? $_SERVER['PATH_TRANSLATED']
|
350 |
: $_SERVER['SCRIPT_FILENAME'];
|
351 |
+
$explode = explode( '/', $script_filename );
|
352 |
return end( $explode );
|
353 |
}
|
354 |
+
|
355 |
/**
|
356 |
* Check an internal array of users against a passed user and pass
|
357 |
*
|
358 |
* @access protected
|
359 |
* @return bool
|
360 |
*
|
361 |
+
* @param array $array The array of users
|
362 |
* @param string $user The username to check for
|
363 |
* @param string $pass The password to check for (plain text)
|
364 |
+
*/
|
365 |
+
protected function matchUserToArray( $array, $user, $pass ) {
|
366 |
+
foreach ( $array as $key => $val ) {
|
367 |
+
if ( ! isset( $val['user'] ) || ! isset( $val['pass'] ) ) {
|
|
|
|
|
368 |
continue;
|
369 |
+
}
|
370 |
|
371 |
+
if ( $val['user'] === $user && md5( $pass ) === $val['pass'] ) {
|
372 |
+
return true;
|
373 |
+
}
|
374 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
|
376 |
+
return false;
|
377 |
}
|
378 |
|
379 |
/**
|
380 |
+
* See if a login base is suggested from being used
|
381 |
*
|
382 |
* @return boolean
|
383 |
*/
|
384 |
+
public function isSuggestedAgainst() {
|
385 |
+
return in_array( $this->login_base, array(
|
|
|
386 |
'login',
|
387 |
'admin',
|
388 |
'user-login',
|
389 |
+
) );
|
390 |
}
|
391 |
|
392 |
/**
|
393 |
* Retrieve the login base
|
394 |
*
|
395 |
* @return string
|
396 |
+
* @param string Default
|
397 |
*/
|
398 |
+
public function getLoginBase( $default = '' ) {
|
399 |
+
return ( $this->login_base ) ? $this->login_base : $default;
|
|
|
400 |
}
|
401 |
|
402 |
/**
|
403 |
+
* Update and save the login base
|
404 |
*
|
405 |
* @param string
|
406 |
*/
|
407 |
+
public function setLoginBase( $base = '' ) {
|
408 |
+
update_option( 'ld_login_base', $base );
|
409 |
$this->login_base = $base;
|
410 |
return $this;
|
411 |
}
|
412 |
|
413 |
+
/**
|
414 |
+
* Retrieve the HTTP Auth setting
|
415 |
+
*
|
416 |
+
* @return string
|
417 |
+
*/
|
418 |
+
public function getHttpAuth() {
|
419 |
+
return get_option( 'ld_http_auth' );
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Set the HTTP Auth usage
|
424 |
+
*
|
425 |
+
* @param string
|
426 |
+
*/
|
427 |
+
public function setHttpAuth( $type = 'none' ) {
|
428 |
+
update_option( 'ld_http_auth', $type );
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Set the option to hide WP Admin
|
433 |
+
*
|
434 |
+
* @param bool True for enabled, otherwise false
|
435 |
+
*/
|
436 |
+
public function setHideWpAdmin( $status ) {
|
437 |
+
update_option( 'ld_hide_wp_admin', (bool) $status );
|
438 |
+
}
|
439 |
+
|
440 |
/**
|
441 |
* Get a username and password from the Basic HTTP auth
|
442 |
*
|
443 |
* @return array|bool
|
444 |
+
*/
|
445 |
+
public function retrieveAuthCredentials() {
|
|
|
446 |
// Since PHP saves the HTTP Password in a bunch of places, we have to be able to test for all of them
|
447 |
+
$username = $password = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
|
449 |
+
// mod_php
|
450 |
+
if ( isset( $_SERVER['PHP_AUTH_USER'] ) ) {
|
451 |
+
$username = ( isset( $_SERVER['PHP_AUTH_USER'] ) ) ? $_SERVER['PHP_AUTH_USER'] : null;
|
452 |
+
$password = ( isset( $_SERVER['PHP_AUTH_PW'] ) ) ? $_SERVER['PHP_AUTH_PW'] : null;
|
453 |
+
} // most other servers
|
454 |
+
elseif ( $_SERVER['HTTP_AUTHENTICATION'] ) {
|
455 |
+
if ( 0 === strpos( strtolower( $_SERVER['HTTP_AUTHENTICATION'] ), 'basic' ) ) {
|
456 |
+
list( $username, $password ) = explode( ':', base64_decode( substr( $_SERVER['HTTP_AUTHENTICATION'], 6 ) ) );
|
457 |
}
|
458 |
}
|
459 |
+
|
460 |
// Check them - if they're null a/o empty, they're invalid.
|
461 |
+
if ( is_null( $username ) OR is_null( $password ) OR empty( $username ) OR empty( $password ) ) {
|
462 |
+
return false;
|
463 |
+
} else {
|
464 |
+
return compact( 'username', 'password' );
|
465 |
+
}
|
466 |
}
|
467 |
|
468 |
/**
|
469 |
* Get the users for the private creds
|
470 |
*
|
471 |
* @access private
|
472 |
+
*/
|
473 |
+
public function getPrivateUsers() {
|
474 |
+
return (array) get_option( 'ld_private_users' );
|
475 |
+
}
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Set the private users
|
479 |
+
*
|
480 |
+
* @param array $users
|
481 |
+
*/
|
482 |
+
public function setPrivateUsers( array $users ) {
|
483 |
+
return update_option( 'ld_private_users', $users );
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Add Private User
|
488 |
+
*
|
489 |
+
* @param string $username
|
490 |
+
* @param string $password
|
491 |
+
* @throws Exception
|
492 |
+
*/
|
493 |
+
public function addPrivateUser( $username, $password ) {
|
494 |
+
$users = $this->getPrivateUsers();
|
495 |
+
|
496 |
+
// Ensure the data is valid
|
497 |
+
if ( empty( $username ) || empty( $password ) ) {
|
498 |
+
throw new Exception( __( 'Username/password is empty.', 'lockdown-wp-admin' ) );
|
499 |
+
}
|
500 |
+
|
501 |
+
if ( $this->doesUsernameExist( $username ) ) {
|
502 |
+
throw new Exception( __( 'Username already exists.', 'lockdown-wp-admin' ) );
|
503 |
+
} else {
|
504 |
+
$users[] = array(
|
505 |
+
'user' => sanitize_user( $username ),
|
506 |
+
'pass' => trim( md5( $password ) ),
|
507 |
+
);
|
508 |
+
}
|
509 |
+
|
510 |
+
$this->setPrivateUsers( $users );
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* See if a user exists in the array
|
515 |
+
*
|
516 |
+
* @access public
|
517 |
+
* @return boolean
|
518 |
+
* @param string $username
|
519 |
+
*/
|
520 |
+
public function doesUsernameExist( $username ) {
|
521 |
+
$users = $this->getPrivateUsers();
|
522 |
+
|
523 |
+
if ( empty( $users ) ) {
|
524 |
+
return false;
|
525 |
+
} else {
|
526 |
+
return in_array( $username, wp_list_pluck( $users, 'user' ) );
|
527 |
+
}
|
528 |
+
}
|
529 |
+
|
530 |
+
/**
|
531 |
+
* Determine if we're hiding wp-admin
|
532 |
+
* The use of 'yep' is deprecated.
|
533 |
+
*
|
534 |
+
* @return bool
|
535 |
+
*/
|
536 |
+
public function is_hiding_admin() {
|
537 |
+
$opt = get_option( 'ld_hide_wp_admin' );
|
538 |
+
return ( 'yep' === $opt || '1' == $opt );
|
539 |
}
|
540 |
+
}
|
tests/bootstrap.php
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
$_tests_dir = getenv('WP_TESTS_DIR');
|
4 |
-
if ( !$_tests_dir ) $_tests_dir = '/tmp/wordpress-tests-lib';
|
5 |
-
|
6 |
-
require_once $_tests_dir . '/includes/functions.php';
|
7 |
-
|
8 |
-
function _manually_load_plugin() {
|
9 |
-
require dirname( __FILE__ ) . '/../lockdown-wp-admin.php';
|
10 |
-
}
|
11 |
-
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
|
12 |
-
|
13 |
-
require $_tests_dir . '/includes/bootstrap.php';
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test-application.php
DELETED
@@ -1,63 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
class LockdownApplicationTest extends PHPUnit_Framework_TestCase {
|
3 |
-
protected $object;
|
4 |
-
|
5 |
-
protected function setUp()
|
6 |
-
{
|
7 |
-
$this->object = ld_setup_auth();
|
8 |
-
}
|
9 |
-
|
10 |
-
public function testMatchUserToArray()
|
11 |
-
{
|
12 |
-
$users = array(
|
13 |
-
array(
|
14 |
-
'user' => 'admin',
|
15 |
-
'pass' => md5('password')
|
16 |
-
),
|
17 |
-
|
18 |
-
array(
|
19 |
-
'user' => 'stan',
|
20 |
-
'pass' => md5('marsh')
|
21 |
-
)
|
22 |
-
);
|
23 |
-
|
24 |
-
// Should pass
|
25 |
-
$this->assertTrue(
|
26 |
-
$this->invokeMethod($this->object->application, 'matchUserToArray', array($users, 'admin', 'password'))
|
27 |
-
);
|
28 |
-
|
29 |
-
// Both should fail
|
30 |
-
$this->assertFalse(
|
31 |
-
$this->invokeMethod($this->object->application, 'matchUserToArray', array($users, 'admin', 'notpassword'))
|
32 |
-
);
|
33 |
-
|
34 |
-
$this->assertFalse(
|
35 |
-
$this->invokeMethod($this->object->application, 'matchUserToArray', array(array(), 'admin', 'notpassword'))
|
36 |
-
);
|
37 |
-
}
|
38 |
-
|
39 |
-
public function testNoSettingsPassed()
|
40 |
-
{
|
41 |
-
$this->invokeMethod($this->object->application, 'setupHttpCheck', array(null));
|
42 |
-
|
43 |
-
$this->assertTrue($this->object->getAuthPassed());
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Call protected/private method of a class.
|
48 |
-
*
|
49 |
-
* @param object &$object Instantiated object that we will run method on.
|
50 |
-
* @param string $methodName Method name to call
|
51 |
-
* @param array $parameters Array of parameters to pass into method.
|
52 |
-
*
|
53 |
-
* @return mixed Method return.
|
54 |
-
*/
|
55 |
-
public function invokeMethod(&$object, $methodName, array $parameters = array())
|
56 |
-
{
|
57 |
-
$reflection = new \ReflectionClass(get_class($object));
|
58 |
-
$method = $reflection->getMethod($methodName);
|
59 |
-
$method->setAccessible(true);
|
60 |
-
|
61 |
-
return $method->invokeArgs($object, $parameters);
|
62 |
-
}
|
63 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test-core.php
DELETED
@@ -1,89 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
class LockdownTest extends PHPUnit_Framework_TestCase {
|
3 |
-
protected $object;
|
4 |
-
|
5 |
-
protected function setUp()
|
6 |
-
{
|
7 |
-
$this->object = ld_setup_auth();
|
8 |
-
}
|
9 |
-
|
10 |
-
public function testApplicationSetup()
|
11 |
-
{
|
12 |
-
$this->assertInstanceOf('Lockdown_Application', $this->object->application);
|
13 |
-
}
|
14 |
-
|
15 |
-
public function testAdminSetup()
|
16 |
-
{
|
17 |
-
$this->assertInstanceOf('Lockdown_Admin', $this->object->admin);
|
18 |
-
}
|
19 |
-
|
20 |
-
public function testRelm()
|
21 |
-
{
|
22 |
-
$this->assertTrue(is_string($this->object->relm));
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Test that the application has added an action to init
|
27 |
-
*/
|
28 |
-
public function testActionAdded()
|
29 |
-
{
|
30 |
-
$this->assertTrue(has_action('init'));
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* The ability to overwrite the Lockdown WP Admin Object
|
35 |
-
*/
|
36 |
-
public function testOverwriteLdObject()
|
37 |
-
{
|
38 |
-
add_filter('ld_class', function() { return 'LdProxyObject'; });
|
39 |
-
$setup = ld_setup_auth();
|
40 |
-
$this->assertEquals('LdProxyObject', get_class($setup));
|
41 |
-
$this->assertEquals('WP_LockAuth', get_class($this->object));
|
42 |
-
}
|
43 |
-
|
44 |
-
public function testFiltersWithoutBase()
|
45 |
-
{
|
46 |
-
remove_all_actions('wp_redirect');
|
47 |
-
remove_all_actions('network_site_url');
|
48 |
-
remove_all_actions('site_url');
|
49 |
-
|
50 |
-
update_option('ld_login_base', null);
|
51 |
-
$this->object->application->renameLogin();
|
52 |
-
|
53 |
-
$this->assertFalse(has_action('wp_redirect'));
|
54 |
-
$this->assertFalse(has_action('network_site_url'));
|
55 |
-
$this->assertFalse(has_action('site_url'));
|
56 |
-
}
|
57 |
-
|
58 |
-
public function testFiltersWithBase()
|
59 |
-
{
|
60 |
-
remove_all_actions('wp_redirect');
|
61 |
-
remove_all_actions('network_site_url');
|
62 |
-
remove_all_actions('site_url');
|
63 |
-
|
64 |
-
update_option('ld_login_base', 'login');
|
65 |
-
$this->object->application->renameLogin();
|
66 |
-
|
67 |
-
$this->assertTrue(has_action('wp_redirect'));
|
68 |
-
$this->assertTrue(has_action('network_site_url'));
|
69 |
-
$this->assertTrue(has_action('site_url'));
|
70 |
-
}
|
71 |
-
|
72 |
-
public function testLoginBase()
|
73 |
-
{
|
74 |
-
update_option('ld_login_base', 'login');
|
75 |
-
$this->object->application->renameLogin();
|
76 |
-
|
77 |
-
$this->assertEquals('login', $this->object->getLoginBase());
|
78 |
-
}
|
79 |
-
|
80 |
-
public function testRewriteUrl()
|
81 |
-
{
|
82 |
-
$this->assertEquals('http://localhost/login', $this->object->application->filterWpLogin('http://localhost/wp-login.php'));
|
83 |
-
}
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* @ignore
|
88 |
-
*/
|
89 |
-
class LdProxyObject extends WP_LockAuth { }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test-hideadmin.php
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
class LockdownAdminTest extends PHPUnit_Framework_TestCase {
|
3 |
-
protected $object;
|
4 |
-
|
5 |
-
protected function setUp()
|
6 |
-
{
|
7 |
-
$this->object = ld_setup_auth();
|
8 |
-
}
|
9 |
-
|
10 |
-
public function testWhitelist()
|
11 |
-
{
|
12 |
-
add_filter('no_check_files', function($a) { $a[] = 'wp-activate.php'; return $a; });
|
13 |
-
update_option('ld_hide_wp_admin', 'yep');
|
14 |
-
|
15 |
-
// Mocking a request to wp-activate.php
|
16 |
-
$_SERVER['SCRIPT_FILENAME'] = ABSPATH.'/wp-activate.php';
|
17 |
-
|
18 |
-
// Set it back up again so we can test if it passed
|
19 |
-
$this->setUp();
|
20 |
-
$this->assertTrue($this->object->getAuthPassed());
|
21 |
-
}
|
22 |
-
|
23 |
-
public function testWhitelistToBlock()
|
24 |
-
{
|
25 |
-
update_option('ld_hide_wp_admin', 'yep');
|
26 |
-
|
27 |
-
// Mocking a request to wp-activate.php
|
28 |
-
$_SERVER['SCRIPT_FILENAME'] = ABSPATH.'/wp-login.php';
|
29 |
-
|
30 |
-
// Set it back up again so we can test if it passed
|
31 |
-
$this->setUp();
|
32 |
-
$this->assertFalse($this->object->getAuthPassed());
|
33 |
-
}
|
34 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test-sample.php
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class SampleTest extends WP_UnitTestCase {
|
4 |
-
|
5 |
-
function testSample() {
|
6 |
-
// replace this with some actual testing code
|
7 |
-
$this->assertTrue( true );
|
8 |
-
}
|
9 |
-
}
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
views/settings.php
CHANGED
@@ -1,25 +1,14 @@
|
|
1 |
-
<?php if (! defined('ABSPATH')) exit; ?>
|
|
|
2 |
<div class="wrap">
|
3 |
-
<
|
4 |
-
|
5 |
-
<?php if ( defined('LD_WP_ADMIN') && LD_WP_ADMIN == TRUE ) : ?>
|
6 |
-
<div class="updated fade">
|
7 |
-
<p>Options updated!</p>
|
8 |
-
</div>
|
9 |
-
<?php endif;
|
10 |
-
if ( defined('LD_DIS_BASE') && LD_DIS_BASE == TRUE ) : ?>
|
11 |
-
<div class="updated error fade">
|
12 |
-
<p>You can't make that your URL Base.</p>
|
13 |
-
</div>
|
14 |
-
<?php endif; ?>
|
15 |
|
16 |
-
<p>
|
17 |
-
We are going to help make WordPress a bit more secure.
|
18 |
-
</p>
|
19 |
<p>
|
20 |
<a href="https://twitter.com/srtfisher" class="twitter-follow-button" data-show-count="false">Follow @srtfisher</a>
|
21 |
-
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script
|
22 |
-
|
23 |
<br>
|
24 |
<em>
|
25 |
(Also, I am a freelancer and would love to <a href="http://seanfisher.co/contact">hear from you about your project</a>!)
|
@@ -27,15 +16,13 @@
|
|
27 |
</p>
|
28 |
|
29 |
<p>
|
30 |
-
Follow Lockdown WP-Admin development on
|
|
|
31 |
</p>
|
32 |
|
33 |
<form method="POST" action="<?php echo admin_url('admin.php?page=lockdown-wp-admin'); ?>">
|
34 |
-
|
35 |
<?php wp_nonce_field('lockdown-wp-admin'); ?>
|
36 |
-
<h3>
|
37 |
-
Hide WP Admin
|
38 |
-
</h3>
|
39 |
<p>
|
40 |
We can "hide" WordPress's administration interface from the public.
|
41 |
If you enable this, when you access
|
@@ -45,66 +32,74 @@
|
|
45 |
instead of redirecting to the login page.
|
46 |
</p>
|
47 |
<label>
|
48 |
-
<input
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
53 |
</label>
|
54 |
-
|
55 |
<h3 style="margin-top: 30px;">
|
56 |
-
WordPress Login URL
|
57 |
</h3>
|
58 |
<label>
|
59 |
-
Change the WordPress Login URL
|
60 |
<?php echo wp_guess_url().'/'; ?>
|
61 |
<input type="text" name="login_base" value="<?php echo $this->instance->application->getLoginBase(); ?>" />
|
62 |
<br>
|
63 |
<em>
|
64 |
-
This will change it from
|
65 |
-
|
66 |
</em>
|
67 |
</label>
|
68 |
<?php
|
69 |
-
global $auth_obj;
|
70 |
$url = home_url() . '/'. $this->instance->application->getLoginBase();
|
71 |
?>
|
72 |
<p>
|
73 |
-
Your current login URL is
|
|
|
74 |
</p>
|
75 |
|
76 |
<?php if ($this->instance->application->isSuggestedAgainst()) : ?>
|
77 |
-
<div class="updated error"
|
78 |
-
|
79 |
-
|
80 |
</p>
|
81 |
</div>
|
82 |
<?php endif; ?>
|
83 |
<blockquote>
|
84 |
-
<h4
|
85 |
-
<p>
|
|
|
86 |
to not cache the above base. That means (for most caching plugins) adding
|
87 |
whatever you enter into the box above into your plugins Caching Whitelist, that
|
88 |
-
is the list of URLs that your plugin doesn't cache. If you have any questions, tweet
|
89 |
-
me
|
|
|
|
|
90 |
</blockquote>
|
91 |
-
<h3
|
92 |
-
<p>
|
93 |
-
|
|
|
94 |
<label>
|
95 |
-
<input name="http_auth" type="radio" value="none" <?php if ( $http_auth_type
|
96 |
-
Disable HTTP Auth
|
|
|
97 |
<div class="clear"></div>
|
98 |
<label>
|
99 |
-
<input type="radio" name="http_auth" <?php if (
|
100 |
-
WordPress Login Credentials
|
|
|
101 |
<div class="clear"></div>
|
102 |
<label>
|
103 |
-
<input type="radio" name="http_auth" <?php if (
|
104 |
-
Private Usernames/Passwords
|
|
|
105 |
<div class="clear"></div>
|
106 |
<br>
|
107 |
<input type="hidden" name="did_update" value="yes_we_did">
|
108 |
-
<input class='button-primary' type='submit'
|
109 |
</form>
|
110 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; ?>
|
2 |
+
<?php $manager = Lockdown_Manager::instance(); ?>
|
3 |
<div class="wrap">
|
4 |
+
<h2><?php esc_html_e( 'Lockdown WordPress Admin', 'lockdown-wp-admin' ); ?></h2>
|
5 |
+
<?php include LD_PLUGIN_DIR . '/views/errors.php'; ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
+
<p><?php esc_html_e( 'We are going to help make WordPress a bit more secure.', 'lockdown-wp-admin' ); ?></p>
|
|
|
|
|
8 |
<p>
|
9 |
<a href="https://twitter.com/srtfisher" class="twitter-follow-button" data-show-count="false">Follow @srtfisher</a>
|
10 |
+
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
11 |
+
<br />
|
12 |
<br>
|
13 |
<em>
|
14 |
(Also, I am a freelancer and would love to <a href="http://seanfisher.co/contact">hear from you about your project</a>!)
|
16 |
</p>
|
17 |
|
18 |
<p>
|
19 |
+
<?php esc_html_e( 'Follow Lockdown WP-Admin development on', 'lockdown-wp-admin' ); ?>
|
20 |
+
<a href="https://github.com/srtfisher/Lockdown-WPAdmin" target="_blank"><?php esc_html_e( 'GitHub', 'lockdown-wp-admin' ); ?></a>
|
21 |
</p>
|
22 |
|
23 |
<form method="POST" action="<?php echo admin_url('admin.php?page=lockdown-wp-admin'); ?>">
|
|
|
24 |
<?php wp_nonce_field('lockdown-wp-admin'); ?>
|
25 |
+
<h3><?php esc_html_e( 'Hide WP Admin', 'lockdown-wp-admin' ); ?></h3>
|
|
|
|
|
26 |
<p>
|
27 |
We can "hide" WordPress's administration interface from the public.
|
28 |
If you enable this, when you access
|
32 |
instead of redirecting to the login page.
|
33 |
</p>
|
34 |
<label>
|
35 |
+
<input
|
36 |
+
type="checkbox"
|
37 |
+
name="hide_wp_admin"
|
38 |
+
<?php if ( $manager->application->is_hiding_admin() ) echo 'checked'; ?>
|
39 |
+
value="yes">
|
40 |
+
<?php esc_html_e( 'Yes, please hide WP Admin from the user when they aren\'t logged in.', 'lockdown-wp-admin' ); ?>
|
41 |
</label>
|
42 |
+
|
43 |
<h3 style="margin-top: 30px;">
|
44 |
+
<?php esc_html_e( 'WordPress Login URL', 'lockdown-wp-admin' ); ?>
|
45 |
</h3>
|
46 |
<label>
|
47 |
+
<?php esc_html_e( 'Change the WordPress Login URL:', 'lockdown-wp-admin' ); ?>
|
48 |
<?php echo wp_guess_url().'/'; ?>
|
49 |
<input type="text" name="login_base" value="<?php echo $this->instance->application->getLoginBase(); ?>" />
|
50 |
<br>
|
51 |
<em>
|
52 |
+
<?php echo esc_html( sprintf( __( 'This will change it from %s/wp-login.php to whatever you put in this box. If you leave it blank, it will be disabled.', 'lockdown-wp-admin' ), wp_guess_url() ) ); ?>
|
53 |
+
<?php echo esc_html( sprintf( __( 'If you put \'login\' into the box, your new login URL will be %s/login/.', 'lockdown-wp-admin' ), wp_guess_url() ) ); ?>
|
54 |
</em>
|
55 |
</label>
|
56 |
<?php
|
|
|
57 |
$url = home_url() . '/'. $this->instance->application->getLoginBase();
|
58 |
?>
|
59 |
<p>
|
60 |
+
<?php echo esc_html_e( 'Your current login URL is', 'lockdown-wp-admin' ); ?>
|
61 |
+
<code><a href="<?php echo $url; ?>"><?php echo $url; ?></a></code>.
|
62 |
</p>
|
63 |
|
64 |
<?php if ($this->instance->application->isSuggestedAgainst()) : ?>
|
65 |
+
<div class="updated error">
|
66 |
+
<p>
|
67 |
+
<?php echo esc_html( sprintf( __( 'Your login base %s is highly insecure! We strongly reccomend using another login URL to ensure maximum security.', 'lockdown-wp-admin' ), $this->login_base ) ); ?>
|
68 |
</p>
|
69 |
</div>
|
70 |
<?php endif; ?>
|
71 |
<blockquote>
|
72 |
+
<h4><?php esc_html_e( 'Please Note Something!', 'lockdown-wp-admin' ); ?></h4>
|
73 |
+
<p>
|
74 |
+
<?php esc_html_e( 'If you are using a cache plugin (WTC, WP Super Cache, etc), you need to enable it
|
75 |
to not cache the above base. That means (for most caching plugins) adding
|
76 |
whatever you enter into the box above into your plugins Caching Whitelist, that
|
77 |
+
is the list of URLs that your plugin doesn\'t cache. If you have any questions, tweet
|
78 |
+
me', 'lockdown-wp-admin' ); ?>
|
79 |
+
<a href="http://twitter.com/srtfisher">@srtfisher</a>.
|
80 |
+
</p>
|
81 |
</blockquote>
|
82 |
+
<h3><?php esc_html_e( 'HTTP Authentication', 'lockdown-wp-admin' ); ?></h3>
|
83 |
+
<p>
|
84 |
+
<?php esc_html_e( 'Please read about HTTP Authentication on', 'lockdown-wp-admin' ); ?> <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">http://en.wikipedia.org/wiki/Basic_access_authentication</a>.</p>
|
85 |
+
<?php $http_auth_type = $this->instance->application->getHttpAuth(); ?>
|
86 |
<label>
|
87 |
+
<input name="http_auth" type="radio" value="none" <?php if ( empty( $http_auth_type ) || 'none' === $http_auth_type ) { ?>checked<?php } ?>>
|
88 |
+
<?php esc_html_e( 'Disable HTTP Auth.', 'lockdown-wp-admin' ); ?>
|
89 |
+
</label>
|
90 |
<div class="clear"></div>
|
91 |
<label>
|
92 |
+
<input type="radio" name="http_auth" <?php if ( 'wp_creds' === $http_auth_type ) { ?>checked<?php } ?> value="wp_creds">
|
93 |
+
<?php esc_html_e( 'WordPress Login Credentials', 'lockdown-wp-admin' ); ?>
|
94 |
+
</label>
|
95 |
<div class="clear"></div>
|
96 |
<label>
|
97 |
+
<input type="radio" name="http_auth" <?php if ( 'private' === $http_auth_type ) { ?>checked<?php } ?> value="private">
|
98 |
+
<?php esc_html_e( 'Private Usernames/Passwords', 'lockdown-wp-admin' ); ?>
|
99 |
+
</label>
|
100 |
<div class="clear"></div>
|
101 |
<br>
|
102 |
<input type="hidden" name="did_update" value="yes_we_did">
|
103 |
+
<input class='button-primary' type='submit' value='<?php echo esc_attr( __( 'Save Options', 'lockdown-wp-admin' ) ); ?>' id='submitbutton' />
|
104 |
</form>
|
105 |
</div>
|