├── .htaccess ├── images ├── welaika.png ├── welaika.16x16.png └── welaika.32x32.png ├── assets ├── icon-128x128.png ├── icon-256x256.png └── banner-772x250.jpg ├── admin.php ├── footer.html.php ├── javascripts └── constants.js ├── wordless-extender ├── WordlessCheck.php ├── WordlessExtenderDB.php ├── WordlessExtenderFilesystem.php ├── WordlessExtenderMenu.php ├── WordlessExtenderConstantCollection.php ├── WordlessExtenderWpconfig.php ├── WordlessExtender.php ├── WordlessExtenderConstantForm.php ├── WordlessExtenderSecurity.php ├── WordlessExtenderPluginManager.php └── WordlessExtenderConstantManager.php ├── stylesheets └── wordless-extender.css ├── wordless-extender.php ├── functions.php ├── constants.html.php ├── resources ├── wp-config.tpl └── htaccess.tpl ├── README.md ├── deploy.sh ├── plugins.html.php ├── readme.txt └── security.html.php /.htaccess: -------------------------------------------------------------------------------- 1 | Options -Indexes 2 | -------------------------------------------------------------------------------- /images/welaika.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/images/welaika.png -------------------------------------------------------------------------------- /assets/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/assets/icon-128x128.png -------------------------------------------------------------------------------- /assets/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/assets/icon-256x256.png -------------------------------------------------------------------------------- /assets/banner-772x250.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/assets/banner-772x250.jpg -------------------------------------------------------------------------------- /images/welaika.16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/images/welaika.16x16.png -------------------------------------------------------------------------------- /images/welaika.32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welaika/wordless-extender/HEAD/images/welaika.32x32.png -------------------------------------------------------------------------------- /admin.php: -------------------------------------------------------------------------------- 1 | 2 | Wordless Extender is developed by weLaika.
3 | View README for more details.
4 | Report issues or suggestions here.
5 | Discover a better WordPress workflow visiting wordpress.welaika.com. 6 |

7 | -------------------------------------------------------------------------------- /javascripts/constants.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function($){ 2 | 3 | function randomString(length, chars) { 4 | var result = ''; 5 | for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))]; 6 | return result; 7 | } 8 | 9 | // On key generator button click generate randomString() in target named input 10 | 11 | $('.keygen_js').click(function(){ 12 | $target = $("[name=\""+ $(this).data('target') +"\"]"); 13 | $target.val(randomString(65, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')); 14 | }); 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /wordless-extender/WordlessCheck.php: -------------------------------------------------------------------------------- 1 | is_wordless_installed()){ 21 | $data = get_plugin_data(WP_PLUGIN_DIR . '/wordless/wordless.php'); 22 | return $data; 23 | } else { 24 | return false; 25 | } 26 | } 27 | 28 | private function get_wordless_version() 29 | { 30 | if ($this->wordless_data()){ 31 | $data = $this->wordless_data(); 32 | $version = (float) $data['Version']; 33 | return $version; 34 | } 35 | } 36 | 37 | public function is_wordless_menu_present() 38 | { 39 | return $this->get_wordless_version() > 0.3 ? true : false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /stylesheets/wordless-extender.css: -------------------------------------------------------------------------------- 1 | .description ul { list-style: disc inside; } table#wordless-extender col.status { width: 10%; } table#wordless-extender col.name { width: 34%; } table#wordless-extender col.version, table#wordless-extender col.install, table#wordless-extender col.upgrade, table#wordless-extender col.activate, table#wordless-extender col.deactivate, table#wordless-extender col.delete, table#wordless-extender col.details { width: 8%; } table#wordless-extender thead, table#wordless-extender tfoot { font-weight: bold; } table#wordless-extender tbody tr:nth-child(2n) { background-color: #f4f4f4; } table#wordless-extender tbody tr.not-installed { background-color: #ffebe8; } table#wordless-extender tbody tr.not-installed td.status { color: #996655; font-weight: bold; text-shadow: white 0px 1px 0px; } table#wordless-extender tbody tr.not-active { background-color: #ffffdd; } table#wordless-extender tbody tr.not-active td.status { color: #aa8844; font-weight: bold; text-shadow: white 0px 1px 0px; } table#wordless-extender tbody tr td { line-height: 1.5em; padding: 10px 0; padding-left: 10px; } .red{ color: red;} 2 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderDB.php: -------------------------------------------------------------------------------- 1 | getMessage(), "\n"; 30 | } 31 | 32 | require_once WordlessExtender::$path . 'admin.php'; 33 | 34 | $wordless_extender_security = new WordlessExtenderSecurity; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 |

' . $message . '

'; 21 | } 22 | 23 | 24 | // Enqueue constants javascript 25 | function wle_constants_scripts(){ 26 | wp_register_script("wle_constants", WordlessExtender::$url ."/javascripts/constants.js", 'jquery', false, true); 27 | wp_enqueue_script("wle_constants"); 28 | } 29 | 30 | add_action('admin_enqueue_scripts', 'wle_constants_scripts' ); 31 | 32 | // Enqueue WLE stylesheets 33 | function wle_stylesheets(){ 34 | wp_register_style("wle_style", WordlessExtender::$url ."/stylesheets/wordless-extender.css"); 35 | wp_enqueue_style("wle_style"); 36 | } 37 | 38 | add_action('admin_enqueue_scripts', 'wle_stylesheets' ); 39 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderFilesystem.php: -------------------------------------------------------------------------------- 1 | 8 |
9 |

10 |

Config Constants

11 |
12 |

13 | wp-config.php has a lot of configurations that you want to remember.
14 | You can discover and manage them within this panel.
15 | 16 | At every update a wp-config.php.orig with previous version will be created.
17 | Remember to delete your cookies and don't worry about new login requests after keys updates.
18 | 19 | Use the power with care! 20 |

21 |
22 | 23 | initialized ){ 25 | 26 | ?> 27 | 28 |
29 | 30 |

Constants list

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | $args ) { 48 | $form->print_row( $name, $args ); 49 | } 50 | 51 | ?> 52 | 53 |
Constant NameDescriptionValueExtra Controls
54 | 55 |

56 | 57 |

58 | 59 |
60 | 63 | 64 |
65 | print_inconsistences(); 67 | $cmanager->print_init_buttons(); 68 | ?> 69 |
70 |
71 | 72 | 73 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderMenu.php: -------------------------------------------------------------------------------- 1 | 'wordless', 9 | // 'page_title' => 'Plugin Manager', 10 | // 'menu_title' => 'Plugin Manager', 11 | // 'capability' => 'install_plugins', 12 | // 'menu_slug' => 'plugin_manager', 13 | // 'function' => 'wle_plugin_manager' 14 | // ); 15 | 16 | private $constants_submenu = array( 17 | 'parent_slug' => 'wordless', 18 | 'page_title' => 'Config Constants', 19 | 'menu_title' => 'Config Constants', 20 | 'capability' => 'install_plugins', 21 | 'menu_slug' => 'config_constants', 22 | 'function' => 'wle_constants' 23 | ); 24 | 25 | private $fixes_submenu = array( 26 | 'parent_slug' => 'wordless', 27 | 'page_title' => 'Security Fixes', 28 | 'menu_title' => 'Security Fixes', 29 | 'capability' => 'install_plugins', 30 | 'menu_slug' => 'security_fixes', 31 | 'function' => 'wle_security' 32 | ); 33 | 34 | public function __construct($wordless_menu_presence) 35 | { 36 | $this->constants_menu = array( 37 | 'page_title' => 'Wordless Extender', 38 | 'menu_title' => 'Wordless Extender', 39 | 'capability' => 'install_plugins', 40 | 'menu_slug' => 'wordless', 41 | 'function' => 'wle_constants', 42 | 'icon_url' => WordlessExtender::$path, 43 | 'position' => 59 44 | ); 45 | 46 | $this->has_wordless_menu = $wordless_menu_presence; 47 | } 48 | 49 | public function create_menu($value) 50 | { 51 | add_menu_page( 52 | $value['page_title'], 53 | $value['menu_title'], 54 | $value['capability'], 55 | $value['menu_slug'], 56 | $value['function'], 57 | $value['icon_url'], 58 | $value['position'] 59 | ); 60 | } 61 | 62 | public function create_submenu($value) 63 | { 64 | add_submenu_page( 65 | $value['parent_slug'], 66 | $value['page_title'], 67 | $value['menu_title'], 68 | $value['capability'], 69 | $value['menu_slug'], 70 | $value['function'] 71 | ); 72 | } 73 | 74 | public function create_menus() 75 | { 76 | $this->create_menu($this->constants_menu); 77 | // $this->create_submenu($this->constants_submenu); 78 | $this->create_submenu($this->fixes_submenu); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderConstantCollection.php: -------------------------------------------------------------------------------- 1 | null, 'description' => '', 'extra_controls' => self::salt_attributes('AUTH_KEY') ); 10 | $list['SECURE_AUTH_KEY'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('SECURE_AUTH_KEY') ); 11 | $list['LOGGED_IN_KEY'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('LOGGED_IN_KEY') ); 12 | $list['NONCE_KEY'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('NONCE_KEY') ); 13 | $list['AUTH_SALT'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('AUTH_SALT') ); 14 | $list['SECURE_AUTH_SALT'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('SECURE_AUTH_SALT') ); 15 | $list['LOGGED_IN_SALT'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('LOGGED_IN_SALT') ); 16 | $list['NONCE_SALT'] = array( 'type' => null, 'description' => '', 'extra_controls' => self::salt_attributes('NONCE_SALT') ); 17 | $list['WP_DEBUG'] = array( 'type' => 'bool', 'description' => '' ); 18 | $list['DISALLOW_FILE_EDIT'] = array( 'type' => 'bool', 'description' => '' ); 19 | $list['CONCATENATE_SCRIPTS'] = array( 'type' => 'bool', 'description' => '' ); 20 | $list['WPLANG'] = array( 'type' => 'text', 'description' => 'Set in the format it_IT' ); 21 | $list['EMPTY_TRASH_DAYS'] = array( 'type' => 'number', 'description' => 'Use an integer to set the maximum trashed contents retention in days' ); 22 | $list['WP_POST_REVISIONS'] = array( 'type' => 'number', 'description' => 'Use an integer to set the maximum kept revisions per post' ); 23 | $list['DISABLE_WP_CRON'] = array( 'type' => 'bool', 'description' => '' ); 24 | $list['WP_ALLOW_REPAIR'] = array( 'type' => 'bool', 'description' => '' ); 25 | $list['FS_METHOD'] = array( 'type' => 'text', 'description' => 'It forces the filesystem method. It should only be "direct", "ssh2", "ftpext", or "ftpsockets". For details view codex' ); 26 | 27 | return $list; 28 | } 29 | 30 | 31 | // Generate custom array for key constant fields passing $key 32 | private static function salt_attributes($key){ 33 | return array("tag" => "div", "text" => 'Generate Key', "attrs" => array("data-target" => $key, "class" => "button keygen_js"), "self_closing" => false ); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /resources/wp-config.tpl: -------------------------------------------------------------------------------- 1 | set_path(); 12 | $this->set_content(); 13 | $this->set_tpl(); 14 | } 15 | 16 | private function set_path() 17 | { 18 | $this->path = ABSPATH . 'wp-config.php'; 19 | } 20 | 21 | private function get_path() 22 | { 23 | return $this->path; 24 | } 25 | 26 | private function set_content() 27 | { 28 | $this->content = $this->read($this->get_path()); 29 | } 30 | 31 | private function get_content() 32 | { 33 | return $this->content; 34 | } 35 | 36 | private function set_tpl() 37 | { 38 | $this->tpl = $this->read(WordlessExtender::$path . 'resources/wp-config.tpl'); 39 | } 40 | 41 | public function get_tpl() 42 | { 43 | return $this->tpl; 44 | } 45 | 46 | public function read( $what = "" ) 47 | { 48 | $file = empty($what) ? $this->path : $what; 49 | 50 | if (file_get_contents($file)) 51 | return file_get_contents($file); 52 | 53 | wle_show_message('Impossible to read from ' . $file, true); 54 | return FALSE; 55 | } 56 | 57 | public function write( $what, $where = null ) 58 | { 59 | $file = is_null($where) ? $this->path : $where; 60 | 61 | $retval = file_put_contents($file, $what); 62 | 63 | if ($retval === FALSE ){ 64 | wle_show_message("Impossible to write in {$file}", true); 65 | return FALSE; 66 | } 67 | } 68 | 69 | public function search( $needle ) 70 | { 71 | if (strstr($needle, 'WLE_')){ 72 | $pattern = '/^#'.$needle.'(.*)#END_'.$needle.'$/ms'; 73 | } else { 74 | $pattern = '/^#WLE_'.$needle.'(.*)#END_WLE'.$needle.'$/ms'; 75 | } 76 | preg_match($pattern, $this->get_content(), $matches); 77 | 78 | return (!empty($matches)) ? $matches[0] : FALSE; 79 | } 80 | 81 | public function search_schema( $needle ) 82 | { 83 | return strstr( addcslashes($this->get_content(), '$'), addcslashes($needle, '$') ); 84 | } 85 | 86 | public function replace_constant( $name, $newvalue ) 87 | { 88 | $pattern = "/^(#WLE_{$name}).*(#END_WLE_{$name})$/ms"; 89 | $replacement = "$1\r\n"; 90 | $replacement .= "$newvalue\r\n"; 91 | $replacement .= "$2"; 92 | 93 | $newdata = preg_replace($pattern, $replacement, $this->get_content(), 1, $count); 94 | 95 | if (is_null($newdata)){ 96 | wle_show_message("Error updating {$name}", true); 97 | throw new Exception("The updated wp-config.php would be empty, so I'm giving up", 1); 98 | } 99 | 100 | return $newdata; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtender.php: -------------------------------------------------------------------------------- 1 | is_wordless_menu_present()); 14 | add_action('admin_menu', array($wleMenu, 'create_menus'), 10); 15 | 16 | $this->set_site_url(); 17 | $this->set_path($path); 18 | $this->set_dirname($path); 19 | $this->set_url(); 20 | $this->set_to_be_installed_plugins(); 21 | $this->set_admin_actions(); 22 | $this->set_repository_url(); 23 | } 24 | 25 | private function set_repository_url() 26 | { 27 | self::$repository_url = 'https://github.com/welaika/wordless-extender/'; 28 | } 29 | 30 | private function set_site_url() 31 | { 32 | self::$site_url = get_bloginfo('url'); 33 | } 34 | 35 | public function get_site_url() 36 | { 37 | return self::$site_url; 38 | } 39 | 40 | private function set_path($path) 41 | { 42 | self::$path = $path; 43 | } 44 | 45 | public function get_path() 46 | { 47 | return self::$path; 48 | } 49 | 50 | private function set_dirname($path) 51 | { 52 | self::$dirname = basename(self::$path); 53 | } 54 | 55 | public function get_dirname() 56 | { 57 | return self::$dirname; 58 | } 59 | 60 | private function set_url() 61 | { 62 | self::$url = plugins_url(self::$dirname); 63 | } 64 | 65 | public function get_url() 66 | { 67 | return self::$url; 68 | } 69 | 70 | private function set_admin_actions() 71 | { 72 | $constant_manager = WordlessExtenderConstantManager::get_instance(); 73 | add_action('admin_action_update_constants', array( $constant_manager, 'update_constants' ) ); 74 | add_action('admin_action_update_securities', array( 'WordlessExtenderSecurity', 'update_securities' ) ); 75 | 76 | } 77 | 78 | private function set_to_be_installed_plugins() 79 | { 80 | $pluginlist = array( 81 | 'Wordless', 82 | 'Users to Csv', 83 | array('Name' => 'InfiniteWP - Client', 'Slug' => 'iwp-client'), 84 | 'Advanced Custom Fields', 85 | array('Name' => 'Advanced Custom Fields: Date and Time Picker', 'Slug' => 'acf-field-date-time-picker'), 86 | 'Debug Bar', 87 | 'Debug Bar Console', 88 | 'Debug Bar Extender', 89 | 'Formidable', 90 | 'Limit Login Attempts', 91 | 'Regenerate Thumbnails' 92 | ); 93 | self::$to_be_installed_plugins = $pluginlist; 94 | } 95 | 96 | public static function get_message($code = 0) 97 | { 98 | $messages = array(0 => false, 1 => 'Successfully updated', 2 => 'Already done!'); 99 | return $messages[$code]; 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /resources/htaccess.tpl: -------------------------------------------------------------------------------- 1 | # BEGIN wordless-extender 2 | 3 | 4 | Order Allow,Deny 5 | Deny from all 6 | 7 | 8 | 9 | RewriteEngine On 10 | RewriteBase / 11 | RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC] 12 | RewriteRule ^(.*)$ - [F,L] 13 | RewriteCond %{QUERY_STRING} \.\.\/ [NC,OR] 14 | RewriteCond %{QUERY_STRING} boot\.ini [NC,OR] 15 | RewriteCond %{QUERY_STRING} tag\= [NC,OR] 16 | RewriteCond %{QUERY_STRING} ftp\: [NC,OR] 17 | RewriteCond %{QUERY_STRING} http\: [NC,OR] 18 | RewriteCond %{QUERY_STRING} https\: [NC,OR] 19 | RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR] 20 | RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR] 21 | RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR] 22 | RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>|ê|"|;|\?|\*|=$).* [NC,OR] 23 | RewriteCond %{QUERY_STRING} ^.*("|'|<|>|\|{||).* [NC,OR] 24 | RewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR] 25 | RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127\.0).* [NC,OR] 26 | RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR] 27 | RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare).* [NC] 28 | RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$ 29 | RewriteRule ^(.*)$ - [F,L] 30 | 31 | 32 | Options +FollowSymLinks 33 | 34 | RewriteEngine On 35 | RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR] 36 | RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] 37 | RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) 38 | RewriteRule ^(.*)$ index.php [F,L] 39 | 40 | Options All -Indexes 41 | 42 | Order allow,deny 43 | Deny from all 44 | 45 | 46 | Order allow,deny 47 | Deny from all 48 | 49 | 50 | Order allow,deny 51 | Deny from all 52 | 53 | 54 | Order allow,deny 55 | Deny from all 56 | 57 | 58 | Order allow,deny 59 | Deny from all 60 | 61 | 62 | Order allow,deny 63 | Deny from all 64 | 65 | 66 | Order allow,deny 67 | Deny from all 68 | 69 | 70 | Order allow,deny 71 | Deny from all 72 | 73 | 74 | Order allow,deny 75 | Deny from all 76 | 77 | 78 | Order allow,deny 79 | Deny from all 80 | 81 | 82 | Order allow,deny 83 | Deny from all 84 | 85 | 86 | Order allow,deny 87 | Deny from all 88 | 89 | 90 | Order allow,deny 91 | Deny from all 92 | 93 | 94 | Order allow,deny 95 | Deny from all 96 | 97 | 98 | Order allow,deny 99 | Deny from all 100 | 101 | 102 | # Block the include-only files. 103 | RewriteEngine On 104 | RewriteBase / 105 | RewriteRule ^wp-admin/includes/ - [F,L] 106 | RewriteRule !^wp-includes/ - [S=3] 107 | RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] 108 | RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] 109 | RewriteRule ^wp-includes/theme-compat/ - [F,L] 110 | 111 | # END wordless-extender 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wordless Extender 2 | 3 | ![logo](http://welaika.github.com/wordless-extender/assets/images/wordless-extender.png) 4 | 5 | ![unmaintained](https://img.shields.io/badge/status-unmaintained-red) 6 | 7 | > ## **⚠️ This repository has been archived and is no longer actively maintained.** 8 | > 9 | > 10 | > ### What this means: 11 | > 12 | > - No further updates, bug fixes, or security patches will be provided. 13 | > - Issues and pull requests will not be addressed. 14 | > - Use this code at your own risk. 15 | 16 | [Wordless](https://github.com/welaika/wordless) is the WP themes framework developed and used by [weLaika](http://dev.welaika.com). 17 | 18 | As we wrote in the Wordless README: 19 | 20 | « Wordless is not meant to be a bloated, all-included tool. 21 | This is why we recommend adding some other plugins 22 | to get the most out of your beautiful WP developer life » 23 | 24 | *Wordless Extender* (WLE from now on) is a starting point for every Wordless theme. 25 | Let's take a look in depth. 26 | 27 | ### Config Constants 28 | 29 | Manage WP constants (stored in your wp-config.php) directly within the WP backend. 30 | 31 | We got inspired by WordPress [guidelines](http://codex.wordpress.org/Editing_wp-config.php) and we crafted this little control panel. It is intended for advanced users: we are not interested in making things easy, but we'd like to remember important/complex/abstruse settings and have them always just one click away. 32 | 33 | Everytime you'll update these configs `wp-config.php` file will be backed-up in `wp-config.php.orig`. Keep in mind. 34 | 35 | ### Security fixes 36 | 37 | This is the most important section: improving security. 38 | Most of the tricks are directly from [Hardening Wordpress](http://codex.wordpress.org/Hardening_WordPress) guide; others are tricks discovered on battlefield. 39 | 40 | You have to know what you are doing. Follow the comments in the panel if you are confused. Remind that when you'll let the plugin rewrite your `.htaccess` file, it will take a backup copy of the last version in `.htaccess.orig`. 41 | 42 | If you are asking about the things are we doing with your `.htaccess` go read the template in `resources/htaccess.tpl`. 43 | Essentially we'll block access to various files and locations. 44 | We are always at work to improve this section, so if you have some tips open an issue or send a pull request. 45 | 46 | ## Wordless integration 47 | 48 | WLE menu in the WP backend, will be integrated with the Wordless 0.4+ backend menu, creating _one place to rule them all!_ 49 | 50 | ## Need more tools? 51 | Visit [Wordpress Tools](http://wptools.it). 52 | 53 | ## Author 54 | 55 | made with ❤️ and ☕️ by [weLaika](http://dev.welaika.com) 56 | 57 | ## License 58 | 59 | (The MIT License) 60 | 61 | Copyright © 2014-2019 [weLaika](http://dev.welaika.com) 62 | 63 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 64 | 65 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 66 | 67 | THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Source: https://raw.github.com/thenbrent/multisite-user-management/master/deploy.sh 3 | # http://thereforei.am/2011/04/21/git-to-svn-automated-wordpress-plugin-deployment/ 4 | # A modification of Dean Clatworthy's deploy script as found here: https://github.com/deanc/wordpress-plugin-git-svn 5 | # The difference is that this script lives in the plugin's git repo & doesn't require an existing SVN repo. 6 | 7 | # main config 8 | PLUGINSLUG=${PWD##*/} # returns basename of current directory 9 | CURRENTDIR=`pwd` 10 | MAINFILE="wordless-extender.php" # this should be the name of your main php file in the wordpress plugin 11 | SVNUSER="welaika" # your svn username (case sensitive) 12 | CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) 13 | 14 | # git config 15 | GITPATH="$CURRENTDIR/" # this file should be in the base of your git repository 16 | 17 | # svn config 18 | SVNPATH="/tmp/$PLUGINSLUG" # path to a temp SVN repo. No trailing slash required and don't add trunk. 19 | SVNURL="http://plugins.svn.wordpress.org/$PLUGINSLUG" # Remote SVN repo on wordpress.org, with no trailing slash 20 | 21 | # Let's begin... 22 | echo ".........................................." 23 | echo 24 | echo "Preparing to deploy WordPress plugin" 25 | echo 26 | echo ".........................................." 27 | echo 28 | 29 | # Check version in readme.txt is the same as plugin file 30 | NEWVERSION1=`grep "^Stable tag" "$GITPATH/readme.txt" | awk -F' ' '{print $3}' | sed 's/[[:space:]]//g'` 31 | echo "readme version: $NEWVERSION1" 32 | NEWVERSION2=`grep "^Version" "$GITPATH/$MAINFILE" | awk -F' ' '{print $2}' | sed 's/[[:space:]]//g'` 33 | echo "$MAINFILE version: $NEWVERSION2" 34 | 35 | if [ "$NEWVERSION1" != "$NEWVERSION2" ]; then echo "Versions don't match. Exiting...."; exit 1; fi 36 | 37 | echo "Versions match in readme.txt and PHP file. Let's proceed..." 38 | 39 | if [ 'master' != $CURRENT_GIT_BRANCH ]; then 40 | echo "Please do the deploy from your master branch. Exiting...." 41 | exit 1 42 | fi 43 | 44 | cd "$GITPATH" 45 | echo -e "Enter a commit message for this new version: \c" 46 | read COMMITMSG 47 | # git commit -am "$COMMITMSG" 48 | 49 | echo "Tagging new version in git" 50 | git tag -a "$NEWVERSION1" -m "Tagging version $NEWVERSION1" 51 | 52 | echo "Pushing latest commit to origin, with tags" 53 | git push origin master 54 | git push origin master --tags 55 | 56 | echo 57 | echo "Creating local copy of SVN repo ..." 58 | svn co $SVNURL $SVNPATH 59 | 60 | echo "Exporting the HEAD of master from git to the trunk of SVN" 61 | git checkout-index -a -f --prefix=$SVNPATH/trunk/ 62 | 63 | echo "Ignoring github specific files and deployment script" 64 | svn propset svn:ignore "deploy.sh 65 | README.md 66 | README.mdown 67 | .git 68 | .gitignore 69 | .travis.yml 70 | Rakefile 71 | docs 72 | tests" "$SVNPATH/trunk/" 73 | 74 | echo "Changing directory to SVN and committing to trunk" 75 | cd $SVNPATH/trunk/ 76 | # Add all new files that are not set to be ignored 77 | svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}' | xargs svn add 78 | svn commit --username=$SVNUSER -m "$COMMITMSG" 79 | 80 | echo "Creating new SVN tag & committing it" 81 | cd $SVNPATH 82 | svn copy trunk/ tags/$NEWVERSION1/ 83 | # Remove trunk directories from tag directory 84 | svn delete --force --quiet $SVNPATH/tags/$NEWVERSION2/trunk 85 | 86 | cd $SVNPATH/tags/$NEWVERSION1 87 | svn commit --username=$SVNUSER -m "Tag $NEWVERSION1" 88 | 89 | echo "Coping assets" 90 | cd $SVNPATH 91 | 92 | echo "Clearing assets from the SVN directory..." 93 | svn delete assets/* 94 | 95 | echo "...and copying updated assets inside of it" 96 | svn copy trunk/assets/* assets/ 97 | cd $SVNPATH/assets/ 98 | svn commit --username=$SVNUSER -m "Assets $NEWVERSION1" 99 | 100 | echo "Removing temporary directory $SVNPATH" 101 | rm -fr $SVNPATH/ 102 | 103 | echo "*** FIN ***" 104 | -------------------------------------------------------------------------------- /plugins.html.php: -------------------------------------------------------------------------------- 1 | initialize_plugins(); 4 | $plugin_data = $pluginManager->get_plugin_istances(); 5 | 6 | wp_enqueue_script( 'plugin-install' ); 7 | add_thickbox(); 8 | 9 | ?> 10 | 11 |
12 |

13 |

Plugin Manager

14 | 15 |
16 |

17 | Community contribuited plugins are essential part of WP itself.
18 | We consider plugins as good ones if they are tested, are actively contribuited, are doing well a single task and have readable code. 19 | 20 |

21 | Here's a list of tested-by-weLaika® plugins with a control panel. 22 |

23 |
24 | 25 |

Plugin list

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 | 52 | 53 | 54 | 55 | 60 | 61 | 66 | 67 | 72 | 73 | 78 | 79 | 84 | 85 | 90 | 91 | 94 | 95 | 96 | 97 |
StatusNameVersionOptions
get_status(); ?>get_data('Name'); ?> 56 | is_installed()) : ?> 57 | get_data('Version'); ?> 58 | 59 | 62 | is_installed()) : ?> 63 | Install 64 | 65 | 68 | is_installed()) : ?> 69 | Update 70 | 71 | 74 | is_installed() && !$p->is_active()) : ?> 75 | Activate 76 | 77 | 80 | is_active()) : ?> 81 | Deactivate 82 | 83 | 86 | is_installed() && !$p->is_active()) : ?> 87 | Delete 88 | 89 | 92 | Details 93 |
98 | 99 |
100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderConstantForm.php: -------------------------------------------------------------------------------- 1 | $value) { 12 | $retval .= "{$key}=\"{$value}\" "; 13 | } 14 | 15 | return $retval; 16 | } 17 | 18 | private function input( $options ) 19 | { 20 | $label = ( isset($options['label']) ) ? $options['label'] : ''; 21 | $checked = ( isset($options['checked'] ) && $options['checked'] == $options['value']) ? 'checked' : ''; 22 | $value = ( isset($options['value']) ) ? $options['value'] : ''; 23 | 24 | return " {$label}"; 25 | } 26 | 27 | private function html_tag( $options ) 28 | { 29 | $html_options = ''; 30 | foreach ($options['attrs'] as $key => $value){ 31 | $html_options .= "{$key}=\"{$value}\" "; 32 | } 33 | 34 | if ( $options['self_closing'] ){ 35 | $close = " />"; 36 | } else{ 37 | $close = ">{$options['text']}"; 38 | } 39 | 40 | return "<{$options['tag']} {$html_options} {$close} "; 41 | } 42 | 43 | private function td( $content ) 44 | { 45 | echo '' . $content . ''; 46 | } 47 | 48 | private function tr_open() 49 | { 50 | echo ''; 51 | } 52 | 53 | private function tr_close() 54 | { 55 | echo ''; 56 | } 57 | 58 | private function parse_input_type( $name, $inputType, $constantObj ) 59 | { 60 | $ret = array(); 61 | 62 | if ( is_null($inputType) || $inputType == 'text' ){ 63 | $ret[] = array( 64 | "type" => 'text', 65 | "name" => $name, 66 | "value" => $constantObj->get_value(), 67 | 'label' => '' 68 | ); 69 | } elseif ( $inputType == 'number' ) { 70 | $ret[] = array( 71 | "type" => 'number', 72 | "name" => $name, 73 | "value" => (int)$constantObj->get_value(), 74 | 'label' => '' 75 | ); 76 | } elseif ( $inputType == 'bool' ) { 77 | $ret[] = array( 78 | "type" => 'radio', 79 | "name" => $name, 80 | "value" => 'true', 81 | 'label' => 'true' 82 | ); 83 | $ret[] = array( 84 | "type" => 'radio', 85 | "name" => $name, 86 | "value" => 'false', 87 | 'label' => 'false' 88 | ); 89 | 90 | foreach ($ret as &$array) { 91 | $array['checked'] = $constantObj->get_value(); 92 | } 93 | } else { 94 | wle_show_message("Unsupported type of input for the constant {$name}", true); 95 | return false; 96 | } 97 | 98 | return $ret; 99 | } 100 | 101 | public function print_row( $name, $args = array( 'type' => null, 'description' => '', 'extra_controls' => array() )) 102 | { 103 | 104 | if ( !is_array($args) ){ 105 | $args = array( 'type' => null, 'description' => '', 'extra_controls' => array() ); 106 | } 107 | 108 | $inputtype = $args['type']; 109 | $description = $args['description']; 110 | if ( isset( $args['extra_controls'] ) ) 111 | $extra_controls = $args['extra_controls']; 112 | 113 | $html = ''; 114 | $cmanager = WordlessExtenderConstantManager::get_instance(); 115 | 116 | $constantObj = $cmanager->init_constant($name); 117 | if (!empty($description)) 118 | $constantObj->set_description($description); 119 | 120 | $inputs = $this->parse_input_type( $name, $inputtype, $constantObj ); 121 | 122 | $this->tr_open(); 123 | $this->td($constantObj->get_name()); 124 | $this->td($constantObj->get_description()); 125 | 126 | foreach ($inputs as $input) { 127 | $html .= $this->input( $input ); 128 | } 129 | $this->td( $html ); 130 | 131 | if (empty( $extra_controls ) ){ 132 | 133 | $this->td(''); 134 | 135 | }else{ 136 | 137 | $this->td( $this->html_tag( $extra_controls ) ); 138 | } 139 | $this->tr_close(); 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Wordless Extender === 2 | Contributors: welaika 3 | Tags: security, configuration, wordless, htaccess, wp-config, development 4 | Requires at least: 4.0 5 | Tested up to: 4.7 6 | Stable tag: 1.2.1 7 | License: MIT 8 | 9 | Wordless Extender is a starting point for everyone: list of commonly used plugins, wp-config.php / .htaccess configuration and security improvements. 10 | 11 | == Description == 12 | 13 | [Wordless](https://github.com/welaika/wordless) is the WP themes framework developed and used by [weLaika](http://dev.welaika.com). 14 | 15 | As we wrote in the Wordless README: 16 | 17 | « Wordless is not meant to be a bloated, all-included tool. 18 | This is why we recommend adding some other plugins 19 | to get the most out of your beautiful WP developer life » 20 | 21 | *Wordless Extender* (WLE from now on) is a starting point for every Wordless theme. 22 | Let's take a look in depth. 23 | 24 | ### Plugin Manager 25 | 26 | Never change a winning team! These are our _starred_ plugins; with these we cover the 90% of our developing needs. 27 | You'll have a control panel inside WLE to list, enable, disable and upgrade plugins from the collection; never search that useful plugin crawling the WP.org repo and have team kickstart projects with always the same plugin set. 28 | 29 | ### Config Constants 30 | 31 | Manage WP constants (stored in your wp-config.php) directly within the WP backend. 32 | 33 | We got inspired by WordPress [guidelines](http://codex.wordpress.org/Editing_wp-config.php) and we crafted this little control panel. It is intended for advanced users: we are not interested in making things easy, but we'd like to remember important/complex/abstruse settings and have them always just one click away. 34 | 35 | Everytime you'll update these configs `wp-config.php` file will be backed-up in `wp-config.php.orig`. Keep in mind. 36 | 37 | ### Security fixes 38 | 39 | This is the most important section: improving security. 40 | Most of the tricks are directly from [Hardening Wordpress](http://codex.wordpress.org/Hardening_WordPress) guide; others are tricks discovered on battlefield. 41 | 42 | You have to know what you are doing. Follow the comments in the panel if you are confused. Remind that when you'll let the plugin rewrite your `.htaccess` file, it will take a backup copy of the last version in `.htaccess.orig`. 43 | 44 | If you are asking about the things are we doing with your `.htaccess` go read the template in `resources/htaccess.tpl`. 45 | Essentially we'll block access to various files and locations. 46 | We are always at work to improve this section, so if you have some tips open an issue or send a pull request. 47 | 48 | ## Wordless integration 49 | 50 | WLE menu in the WP backend, will be integrated with the Wordless 0.4+ backend menu, creating _one place to rule them all!_ 51 | 52 | ## Need more tools? 53 | Visit [Wordpress Tools](http://wptools.it). 54 | 55 | ## Licence 56 | 57 | (The MIT License) 58 | 59 | Copyright © 2014-2015 weLaika 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 64 | 65 | THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | 67 | 68 | == Installation == 69 | 70 | 1. Install Wordless Extender either via the WordPress.org plugin directory, or by uploading the files to your server. 71 | 2. Activate the plugin. 72 | 3. Manage plugin settings. 73 | 4. That's it. You are ready to go! 74 | 75 | == Changelog == 76 | 77 | = 1.2.1 = 78 | * minor fix 79 | 80 | = 1.2.0 = 81 | * update constants manager 82 | * add twentyseventeen theme to security-fixes options 83 | * minor fixes 84 | 85 | = 1.1.3 = 86 | * univocal htaccess 87 | 88 | = 1.1.2 = 89 | * fix htaccess hardening 90 | 91 | = 1.1.1 = 92 | * minor fixes 93 | 94 | = 1.1.0 = 95 | * autoload table prefix 96 | * disabled: plugin manager 97 | 98 | = 1.0.8 = 99 | * fix wp-config update functions 100 | * fix deploy script 101 | 102 | = 1.0.7 = 103 | * update plugins names in plugin manager section 104 | * fix rrmdir function call 105 | * add 2015 and 2016 themes remover to security-fixes options 106 | * updated deprecated autoload method - and so fix on latest WP with latest PHP 107 | 108 | = 1.0.6 = 109 | * Update documentation 110 | 111 | = 1.0.5 = 112 | * Add plugin logo 113 | 114 | = 1.0.4 = 115 | * Update documentation 116 | 117 | = 1.0.3 = 118 | * Update documentation 119 | 120 | = 1.0.2 = 121 | * First stable and wordpress.org-ready release 122 | 123 | == Upgrade Notice == 124 | 125 | = 1.0.2 = 126 | * Actually nothing :) 127 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderSecurity.php: -------------------------------------------------------------------------------- 1 | set_paths(); 12 | $this->set_htaccess_contents(); 13 | 14 | if ( WordlessExtenderDB::take('REMOVE_META_INFOS') === 'true' ) 15 | $this->remove_meta_infos(); 16 | 17 | if ( is_array( $target = WordlessExtenderDB::take('REMOVE_DEFAULT_THEMES_AND_PLUGINS') ) ) 18 | $this->remove_default_themes_and_plugins( $target ); 19 | 20 | if ( WordlessExtenderDB::take('REMOVE_XMLRPC') === 'true' ) 21 | $this->remove_xmlrpc(); 22 | 23 | if ( WordlessExtenderDB::take('REMOVE_README') === 'true' ) 24 | $this->remove_readme(); 25 | 26 | if (( WordlessExtenderDB::take('HARDEN_HTACCESS') === 'true' ) && $this->wle_htaccess_check()) 27 | $this->harden_htaccess(); 28 | 29 | if ( WordlessExtenderDB::take('REMOVE_LICENSE') === 'true' ) 30 | $this->remove_license(); 31 | } 32 | 33 | private function set_paths() 34 | { 35 | self::$xmlrpc_path = ABSPATH . 'xmlrpc.php'; 36 | self::$readme_path = ABSPATH . 'readme.html'; 37 | self::$license_path = ABSPATH . 'license.txt'; 38 | self::$htaccess_path = ABSPATH . '.htaccess'; 39 | self::$htaccess_tpl_path = WordlessExtender::$path . 'resources/htaccess.tpl'; 40 | } 41 | 42 | private function set_htaccess_contents() 43 | { 44 | self::$current_htaccess = WordlessExtenderFilesystem::read_file( self::$htaccess_path ); 45 | self::$htaccess_pattern = '/#\sBEGIN\swordless-extender.*#\sEND\swordless-extender/s'; 46 | } 47 | 48 | private function wle_htaccess_check() 49 | { 50 | preg_match(self::$htaccess_pattern, self::$current_htaccess, $matches); 51 | if ( count($matches) > 0 ) { 52 | return false; 53 | } 54 | return true; 55 | } 56 | 57 | private function harden_htaccess() 58 | { 59 | $new_content = WordlessExtenderFilesystem::read_file( self::$htaccess_tpl_path ); 60 | $new_content .= preg_replace( self::$htaccess_pattern, ' ', self::$current_htaccess ); 61 | 62 | WordlessExtenderFilesystem::backup_and_update_file( self::$htaccess_path, $new_content ); 63 | } 64 | 65 | private function remove_default_themes_and_plugins( $targets ) 66 | { 67 | foreach ( $targets as $target ) { 68 | WordlessExtenderFilesystem::delete( $target ); 69 | } 70 | WordlessExtenderDB::clear('REMOVE_DEFAULT_THEMES_AND_PLUGINS'); 71 | } 72 | 73 | private function remove_xmlrpc() 74 | { 75 | WordlessExtenderFilesystem::delete( self::$xmlrpc_path ); 76 | WordlessExtenderDB::clear('REMOVE_XMLRPC'); 77 | } 78 | 79 | private function remove_readme() 80 | { 81 | WordlessExtenderFilesystem::delete( self::$readme_path ); 82 | WordlessExtenderDB::clear('REMOVE_README'); 83 | } 84 | 85 | private function remove_license() 86 | { 87 | WordlessExtenderFilesystem::delete( self::$license_path ); 88 | WordlessExtenderDB::clear('REMOVE_LICENSE'); 89 | } 90 | 91 | private function remove_meta_infos() 92 | { 93 | 94 | // Remove generator name and version from your Website pages and from the RSS feed. 95 | add_filter('the_generator', create_function('', 'return "";')); 96 | //Display the XHTML generator that is generated on the wp_head hook, WP version 97 | remove_action( 'wp_head', 'wp_generator' ); 98 | //Remove the link to the Windows Live Writer manifest file. 99 | remove_action('wp_head', 'wlwmanifest_link'); 100 | //Remove EditURI 101 | remove_action('wp_head', 'rsd_link'); 102 | //Remove index link. 103 | remove_action('wp_head', 'index_rel_link'); 104 | //Remove previous link. 105 | remove_action('wp_head', 'parent_post_rel_link', 10, 0); 106 | //Remove start link. 107 | remove_action('wp_head', 'start_post_rel_link', 10, 0); 108 | //Remove relational links (previous and next) for the posts adjacent to the current post. 109 | remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0); 110 | //Remove shortlink if it is defined. 111 | remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0); 112 | // Remove scripts' version 113 | add_filter( 'style_loader_src', array($this, 'remove_ver_scripts'), 102, 4 ); 114 | add_filter( 'script_loader_src', array($this, 'remove_ver_scripts'), 102, 4 ); 115 | 116 | } 117 | 118 | public function remove_ver_scripts($src) 119 | { 120 | if ( strpos( $src, 'ver=' ) ) 121 | $src = remove_query_arg( 'ver', $src ); 122 | 123 | return $src; 124 | } 125 | 126 | private static function updatables() 127 | { 128 | return array( 'REMOVE_META_INFOS', 'REMOVE_DEFAULT_THEMES_AND_PLUGINS', 'REMOVE_README', 'REMOVE_XMLRPC', 'HARDEN_HTACCESS', 'REMOVE_LICENSE' ); 129 | } 130 | 131 | public static function update_securities() 132 | { 133 | foreach (self::updatables() as $field) { 134 | if (isset($_POST[$field]) && ( $_POST[$field] != WordlessExtenderDB::take($field) ) ) { 135 | WordlessExtenderDB::save( $field, $_POST[$field] ); 136 | } 137 | } 138 | 139 | $clean_url = preg_replace('/&message=[0-9]{0,2}/', '', $_SERVER['HTTP_REFERER']); 140 | wp_redirect( $clean_url .'&message=1' ); 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderPluginManager.php: -------------------------------------------------------------------------------- 1 | plugin_list = $args; 11 | } 12 | 13 | public function get_plugin_list() 14 | { 15 | return $this->plugin_list; 16 | } 17 | 18 | public function get_all_installed_plugins() 19 | { 20 | return get_plugins(); 21 | } 22 | 23 | public function initialize_plugins() 24 | { 25 | foreach ($this->plugin_list as $plugin) { 26 | $this->plugin_istances[] = new WlePlugin($plugin); 27 | } 28 | } 29 | 30 | public function get_plugin_istances() 31 | { 32 | return $this->plugin_istances; 33 | } 34 | } 35 | 36 | class WlePlugin extends WordlessExtenderPluginManager{ 37 | 38 | private $is_installed, $is_active, $data, $urls, $status; 39 | 40 | public function __construct( $plugin ) 41 | { 42 | if (is_array($plugin)) { 43 | $name = $plugin['Name']; 44 | $slug = $plugin['Slug']; 45 | } else { 46 | $name = $plugin; 47 | $slug = NULL; 48 | } 49 | $this->set_is_installed($name); 50 | $this->set_data($name, $slug); 51 | $this->set_is_active($name); 52 | $this->set_status(); 53 | $this->set_urls(); 54 | } 55 | 56 | private function set_is_installed($plugin) 57 | { 58 | foreach ($this->get_all_installed_plugins() as $p){ 59 | if ($plugin == $p['Name']){ 60 | $this->is_installed = true; 61 | return; 62 | } 63 | } 64 | $this->is_installed = false; 65 | } 66 | 67 | private function set_data($plugin, $slug) 68 | { 69 | if (!$slug) { 70 | $slug = sanitize_title( $plugin, $fallback_title = '', $context = 'save' ); 71 | } 72 | 73 | if (!$this->is_installed){ 74 | $this->data = array( 75 | 'Name' => $plugin, 76 | 'Slug' => $slug, 77 | 'Version' => NULL, 78 | 'Path' => NULL 79 | ); 80 | return; 81 | } 82 | 83 | foreach ($this->get_all_installed_plugins() as $key => $value){ 84 | if ($plugin == $value['Name']){ 85 | $this->data = get_plugin_data( WP_PLUGIN_DIR.'/'.$key, $markup = false, $translate = true ); 86 | $this->data['Slug'] = $slug; 87 | $this->data['Path'] = $key; 88 | return; 89 | } 90 | } 91 | } 92 | 93 | private function set_is_active($plugin) 94 | { 95 | if (!$this->is_installed){ 96 | $return = false; 97 | } 98 | foreach ($this->get_all_installed_plugins() as $key => $value){ 99 | if ($plugin != $value['Name']) 100 | continue; 101 | $return = (is_plugin_active( $key )) ? true : false; 102 | } 103 | $this->is_active = $return; 104 | } 105 | 106 | private function set_status() 107 | { 108 | if ( $this->is_installed() && $this->is_active() ){ 109 | 110 | $this->status = 'Active'; 111 | 112 | } elseif ( $this->is_installed() && !$this->is_active() ){ 113 | 114 | $this->status = 'Inactive'; 115 | 116 | } elseif ( !$this->is_installed() ) { 117 | 118 | $this->status = 'Not installed'; 119 | 120 | } else { 121 | 122 | $this->status = 'Unknown'; 123 | 124 | } 125 | 126 | } 127 | 128 | public function get_status(){ 129 | 130 | return $this->status; 131 | 132 | } 133 | 134 | public function is_installed() 135 | { 136 | return $this->is_installed; 137 | } 138 | 139 | 140 | public function is_active() 141 | { 142 | return $this->is_active; 143 | } 144 | 145 | public function get_data($arg){ 146 | if (!$this->data[$arg]) 147 | return 'Unknown type of data requested'; 148 | return $this->data[$arg]; 149 | } 150 | 151 | private function set_urls() 152 | { 153 | include_once( ABSPATH . WPINC . '/pluggable.php'); 154 | $this->set_install_url(); 155 | $this->set_update_url(); 156 | $this->set_activate_url(); 157 | $this->set_deactivate_url(); 158 | $this->set_delete_url(); 159 | $this->set_details_url(); 160 | } 161 | 162 | private function set_install_url() 163 | { 164 | $this->urls['install'] = get_bloginfo( 'url' ) . '/wp-admin/' . wp_nonce_url( 165 | 'update.php?action=install-plugin&plugin=' . $this->data['Slug'], 166 | 'install-plugin_' . $this->data['Slug'] 167 | ); 168 | } 169 | 170 | private function set_update_url() 171 | { 172 | $this->urls['update'] = get_bloginfo( 'url' ) . '/wp-admin/' . wp_nonce_url( 173 | 'update.php?action=upgrade-plugin&plugin=' . $this->data['Slug'], 174 | 'upgrade-plugin_' . $this->data['Slug'] ); 175 | } 176 | 177 | private function set_activate_url() 178 | { 179 | $this->urls['activate'] = get_bloginfo( 'url' ) . '/wp-admin/' . wp_nonce_url( 180 | 'plugins.php?action=activate&plugin=' . $this->data['Path'] . '&plugin_status=all&paged=1&s', 181 | 'activate-plugin_' . $this->data['Path']); 182 | } 183 | 184 | private function set_deactivate_url() 185 | { 186 | $this->urls['deactivate'] = get_bloginfo( 'url' ) . '/wp-admin/' . wp_nonce_url( 187 | 'plugins.php?action=deactivate&plugin=' . $this->data['Path'] . '&plugin_status=all&paged=1&s', 188 | 'deactivate-plugin_' . $this->data['Path']); 189 | } 190 | 191 | private function set_delete_url() 192 | { 193 | $this->urls['delete'] = get_bloginfo( 'url' ) . '/wp-admin/' . wp_nonce_url( 194 | 'plugins.php?action=delete-selected&checked[]=' . $this->data['Path'] . '&plugin_status=all&paged=1&s', 195 | 'bulk-plugins'); 196 | } 197 | 198 | private function set_details_url() 199 | { 200 | $this->urls['details'] = get_bloginfo( 'url' ) . '/wp-admin/' . 'plugin-install.php?tab=plugin-information&plugin=' . $this->data['Slug'] . '&TB_iframe=true'; 201 | } 202 | 203 | public function get_urls($arg) 204 | { 205 | if (!$this->urls[$arg]) 206 | return 'Unknown type of url requested'; 207 | return $this->urls[$arg]; 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /security.html.php: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 |

9 |

Security Fixes

10 |
11 |

12 | This is a collection of security tricks.
13 | These are taken from Hardening Wordpress and from our WP experience.
14 | Please, pay attention to the warnings. 15 |

16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 45 | 46 | 47 | 48 | 49 | 50 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | 85 | 86 | 87 | 88 | 89 | 96 | 97 | 98 | 99 | 100 | 101 | 108 | 109 | 110 | 111 | 112 | 113 | 125 | 126 | 127 |
FixDescriptionValue
.htaccessMake your .htaccess more solid. A backup is stored in .htaccess.orig 33 | Sure? 44 |
Plugins and themesRemove default WordPress plugins and themes. Warning: you can't undo this action! 51 | 62 | > Theme: TwentyTen
63 | > Theme: TwentyEleven
64 | > Theme: TwentyTwelve
65 | > Theme: TwentyThirteen
66 | > Theme: TwentyFourteen
67 | > Theme: TwentyFifteen
68 | > Theme: TwentySixteen
69 | > Theme: TwentySeventeen
70 | > Plugin: Hello Dolly 71 |
XMLRPCRemove xmlrpc.php file. Warning: you can't undo this action! 78 | 79 | Sure? 80 | 83 |
READMERemove readme.html file. Warning: you can't undo this action! 90 | 91 | Sure? 92 | 95 |
LicenseRemove license.txt file. Warning: you can't undo this action! 102 | 103 | Sure? 104 | 107 |
Meta infosRemove Wordpress meta info from header and feeds. 114 | 122 | > False 123 | > True 124 |
128 | 129 |

130 | 131 |

132 | 133 |
134 | 135 |
136 | 137 | 138 | -------------------------------------------------------------------------------- /wordless-extender/WordlessExtenderConstantManager.php: -------------------------------------------------------------------------------- 1 | wpconfig = new WordlessExtenderWpconfig; 23 | $this->initialized = $this->check_init(); 24 | 25 | if (!$this->initialized){ 26 | $this->init(); 27 | } 28 | 29 | } 30 | 31 | public function print_inconsistences(){ 32 | if ( !empty($this->inconstistent_constants) ) 33 | wle_show_message("WARNING: " . join( ', ', $this->inconstistent_constants) . " is/are probably being modified by hand in wp-config.php. This is a risky situation. Check plugin's and file's value and correct them", 1); 34 | } 35 | 36 | private function check_init() 37 | { 38 | return (get_option('WLE_INIT') && $this->wpconfig->search('WLE_DB_NAME')) ? true : false; 39 | } 40 | 41 | public function print_init_buttons() 42 | { 43 | if ($this->check_init()){ 44 | return; 45 | } else { 46 | echo '
47 |
48 | 49 |
50 |
'; 51 | } 52 | } 53 | 54 | private function init_db() 55 | { 56 | if (!isset($_POST['WLE_INIT']) || empty($_POST['WLE_INIT'])) 57 | return; 58 | 59 | WordlessExtenderDB::save('INIT', 'OK'); 60 | 61 | } 62 | 63 | private function init_wpconfig() 64 | { 65 | $tpl_content = $this->get_tpl_with_table_prefix_synched(); 66 | $orig = $this->wpconfig->read(); 67 | 68 | $constants_to_migrate_into_new_wpconfig = array( 69 | 'DB_PASSWORD' => DB_PASSWORD, 70 | 'DB_USER' => DB_USER, 71 | 'DB_NAME' => DB_NAME, 72 | 'DB_HOST' => DB_HOST 73 | ); 74 | 75 | if ($tpl_content){ 76 | $this->wpconfig->write($orig, ABSPATH . 'wp-config.php.'.time().'.orig'); 77 | $this->wpconfig->write($tpl_content); 78 | } 79 | 80 | foreach ($constants_to_migrate_into_new_wpconfig as $c_name => $c_value ) { 81 | $c = new WordlessConstant( $c_name, array( 'new_value' => $c_value ) ); 82 | } 83 | } 84 | 85 | private function get_tpl_with_table_prefix_synched() 86 | { 87 | global $wpdb; 88 | return preg_replace('/table_prefix = \'wp_\';/', 'table_prefix = \''.$wpdb->base_prefix.'\';', $this->wpconfig->get_tpl()); 89 | } 90 | 91 | private function init() 92 | { 93 | if (!isset($_POST['WLE_INIT']) || empty($_POST['WLE_INIT'])) 94 | return; 95 | 96 | $this->init_wpconfig(); 97 | $this->init_db(); 98 | } 99 | 100 | public function init_constant( $name ) 101 | { 102 | $sub_class = 'WLE_' . $name; 103 | if (class_exists($sub_class)) 104 | $constant = new $sub_class($name); 105 | else 106 | $constant = new WordlessConstant($name); 107 | 108 | 109 | if ( !$constant->is_consistent() ) 110 | $this->inconstistent_constants[] = $constant->name; 111 | 112 | return $constant; 113 | } 114 | 115 | public function update_constants() 116 | { 117 | $constants_collection = WordlessExtenderConstantCollection::get_list(); 118 | 119 | foreach ($constants_collection as $name => $args) { 120 | new WordlessConstant( $name ); 121 | } 122 | 123 | $clean_url = preg_replace('/&message=[0-9]{0,2}/', '', $_SERVER['HTTP_REFERER']); 124 | wp_redirect( $clean_url .'&message=1' ); 125 | } 126 | 127 | } 128 | 129 | Class WordlessConstant{ 130 | public $description; 131 | public $name; 132 | private $value; 133 | private $new_value; 134 | private $presence_in_db; 135 | private $presence_in_wpconfig; 136 | private $to_be_updated; 137 | private $wpconfig; 138 | 139 | public function __construct( $constant_name, $options = array( 'new_value' => null ) ) 140 | { 141 | $this->wpconfig = new WordlessExtenderWpconfig; 142 | 143 | $this->set_name( $constant_name ); 144 | $this->set_presence_in_db(); 145 | $this->set_old_value(); 146 | $this->set_new_value( $options['new_value'] ); 147 | $this->set_presence_in_wpconfig(); 148 | $this->set_to_be_updated(); 149 | 150 | if ($this->to_be_updated){ 151 | $this->update_value($this->new_value); 152 | $this->update_wpc(); 153 | } 154 | } 155 | 156 | private function set_name( $constant_name ) 157 | { 158 | $this->name = $constant_name; 159 | } 160 | 161 | public function get_name() 162 | { 163 | return $this->name; 164 | } 165 | 166 | private function set_presence_in_db() 167 | { 168 | $this->presence_in_db = ( WordlessExtenderDB::take($this->name) === false ) ? false : true; 169 | } 170 | 171 | private function set_presence_in_wpconfig() 172 | { 173 | if ( $this->wpconfig->search_schema($this->get_schema()) ){ 174 | $this->presence_in_wpconfig = true; 175 | } else { 176 | $this->presence_in_wpconfig = false; 177 | } 178 | 179 | } 180 | 181 | private function set_old_value() 182 | { 183 | $this->value = WordlessExtenderDB::take($this->name); 184 | } 185 | 186 | private function set_new_value( $new_value ) 187 | { 188 | if ( !empty( $new_value ) && !is_null($new_value) ) 189 | $v = $new_value; 190 | elseif ( isset( $_POST[$this->name] ) && !is_null($_POST[$this->name]) ) 191 | // 'EMPTY_TRASH_DAYS' and 'WP_POST_REVISIONS' are numeric field. This type of field can't be empty 192 | if ( empty( $_POST[$this->name] ) && ( in_array( $this->name, array('EMPTY_TRASH_DAYS', 'WP_POST_REVISIONS') ) ) ) 193 | $v_for_number = '0'; 194 | else 195 | $v = $_POST[$this->name]; 196 | else 197 | $v = ''; 198 | 199 | if ( isset( $v_for_number ) ) 200 | $this->new_value = $v_for_number; 201 | elseif ( $v ) 202 | $this->new_value = $v; 203 | else 204 | $this->new_value = $this->value; 205 | 206 | } 207 | 208 | public function is_consistent() 209 | { 210 | if ($this->presence_in_wpconfig === $this->presence_in_db) 211 | return true; 212 | 213 | return false; 214 | } 215 | 216 | private function set_to_be_updated() 217 | { 218 | #check is performed between the wp-config.php.orig and persistent data in DB and between the NEW wp-config.php and persistent data in DB. 219 | if ( !$this->presence_in_db ){ 220 | $this->to_be_updated = true; 221 | return; 222 | } 223 | $orig_db_check = ($this->value === $this->new_value) ? false : true; 224 | 225 | $wle_definition = $this->get_wpconfig_by_name(); 226 | $pattern = $this->build_wle_pattern_by_name(); 227 | 228 | preg_match($pattern, $wle_definition, $matches); 229 | 230 | if ( !$orig_db_check && !empty($matches[1]) ) { 231 | $this->to_be_updated = ($this->value === $matches[1]) ? false : true; 232 | } 233 | else { 234 | $this->to_be_updated = $orig_db_check; 235 | } 236 | } 237 | 238 | private function get_wpconfig_by_name() 239 | { 240 | return trim(preg_replace('/\s+/', ' ', $this->wpconfig->search("WLE_".$this->name))); 241 | } 242 | 243 | private function build_wle_pattern_by_name() 244 | { 245 | return '/^#WLE_'.$this->name.' define\(\''.$this->name.'\', \'(.*)\'\); #END_WLE_'.$this->name.'$/ms'; 246 | } 247 | 248 | public function get_value() 249 | { 250 | return $this->value; 251 | } 252 | 253 | /** 254 | * The schema defining the constant. It has just a return 255 | * that instruct the class about how your constant has to be defined. 256 | * The standard form is e.g.: 257 | * 258 | * return "define('{$this->name}', {$this->get_casted_value()});"; 259 | * 260 | * Where {$this->name} is mandatory as the constant name definition. 261 | * 262 | * @see WordlessConstant::get_casted_value() 263 | * 264 | * @return mixed The entire definition code for the constant 265 | */ 266 | public function get_schema() 267 | { 268 | return "define('{$this->name}', {$this->get_casted_value()});"; 269 | } 270 | 271 | /** 272 | * Get the description in the backend on the line of the constant. 273 | * 274 | * @return string The description paragraph 275 | */ 276 | public function get_description() 277 | { 278 | if ( isset($this->description) ) 279 | return $this->description; 280 | 281 | return "Defines the {$this->name}"; 282 | } 283 | 284 | public function set_description( $description ) 285 | { 286 | $this->description = $description; 287 | } 288 | 289 | private function update_value($value) 290 | { 291 | WordlessExtenderDB::save($this->name, $value); 292 | $this->set_old_value(); 293 | } 294 | 295 | private function update_wpc() 296 | { 297 | $new_wpconfig = $this->wpconfig->replace_constant( $this->name, $this->get_schema()); 298 | $this->wpconfig->write( $new_wpconfig ); 299 | } 300 | 301 | protected function get_casted_value() 302 | { 303 | $value = $this->new_value; 304 | switch ($value) { 305 | case 'true': 306 | case 'TRUE': 307 | return 'true'; 308 | break; 309 | 310 | case 'false': 311 | case 'FALSE': 312 | return 'false'; 313 | break; 314 | 315 | case null: 316 | case '': 317 | return "''"; 318 | break; 319 | 320 | case is_numeric($value): 321 | return (int) $value; 322 | break; 323 | 324 | default: 325 | return "'{$value}'"; 326 | break; 327 | } 328 | 329 | } 330 | 331 | } 332 | --------------------------------------------------------------------------------