PageRenderTime 111ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/justjs/wp-content/plugins/askapache-password-protect/askapache-password-protect.php

https://github.com/jkreska/test1
PHP | 2269 lines | 1674 code | 346 blank | 249 comment | 352 complexity | ea848229c023828fc09bf41737fe970e MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. Plugin Name: AskApache Password Protect
  4. Plugin URI: http://www.askapache.com/htaccess/htaccess-security-block-spam-hackers.html
  5. Description: Advanced Security: Password Protection, Anti-Spam, Anti-Exploits, more to come...
  6. Version: 4.6.5.2
  7. Author: AskApache
  8. Author URI: http://www.askapache.com/
  9. */
  10. /**
  11. * AskApache Password Protect WordPress Plugin for .htaccess Files
  12. * Copyright (C) 2008 AskApache.comi
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. */
  27. if ( defined( 'AA_PP_DEBUG' ) ) return;
  28. // define( 'AA_PP_LOG_FILE', ABSPATH.'/askapache-passpro-log.txt' ); // set this to any file to log to
  29. define( 'AA_PP_DEBUG', false ); // set this to 1 for verbose debugging
  30. define( 'AA_PP_NET_DEBUG', false ); // set this to 1 for verbose network debugging
  31. register_activation_hook( __FILE__, 'aa_pp_activate' );
  32. register_deactivation_hook( __FILE__, 'aa_pp_deactivate' );
  33. add_action( 'admin_menu', 'aa_pp_setup_options' );
  34. if ( strpos( $_SERVER['REQUEST_URI'], basename( __FILE__ ) ) !== false ) add_action( 'admin_head', 'aa_pp_admin_header' );
  35. if ( !defined('WP_CONTENT_DIR') ) define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
  36. /**
  37. * aa_pp_setup_options()
  38. *
  39. * @return
  40. */
  41. function aa_pp_setup_options()
  42. {
  43. add_filter( 'plugin_action_links', 'aa_pp_plugin_settings', 10, 2 );
  44. add_options_page( __( 'AskApache Password Protection', 'askapache-password-protection' ), __( 'AA PassPro', 'askapache-password-protection' ), 8, basename( __FILE__ ), 'aa_pp_main_page' );
  45. }
  46. /**
  47. * aa_pp_plugin_settings()
  48. *
  49. * @param mixed $links
  50. * @param mixed $file
  51. * @return
  52. */
  53. function aa_pp_plugin_settings( $links, $file )
  54. {
  55. static $this_plugin;
  56. if ( !$this_plugin ) $this_plugin = plugin_basename( __FILE__ );
  57. if ( $file == $this_plugin ) $links = array_merge( array( '<a href="' . attribute_escape( 'options-general.php?page=askapache-password-protect.php' ) . '">Settings</a>' ), $links );
  58. return $links;
  59. }
  60. /**
  61. * aa_pp_deactivate()
  62. *
  63. * @return
  64. */
  65. function aa_pp_deactivate()
  66. {
  67. global $aa_PP, $aa_SIDS;
  68. $aa_PP = get_option( 'askapache_password_protect' );
  69. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  70. aa_pp_deactivate_sid( 'PASSPRO', 'ASKAPACHE ', $aa_PP['root_htaccess'] );
  71. aa_pp_deactivate_sid( 'PASSPRO', 'ASKAPACHE ', $aa_PP['admin_htaccess'] );
  72. delete_option( 'askapache_password_protect' );
  73. delete_option( 'askapache_password_protect_sids' );
  74. }
  75. /**
  76. * aa_pp_activate()
  77. *
  78. * @return
  79. */
  80. function aa_pp_activate()
  81. {
  82. global $wpdb, $aa_PP, $aa_SIDS;
  83. $aa_PP = $s = $aa_SIDS = array();
  84. foreach ( array( 'home_folder', 'wpadmin_folder', 'htpasswd_file', 'htaccess_file', 'original_htpasswd', 'original_htaccess', 'plugin_message', 'plugin_version', 'home', 'wpadmin', 'htpasswd_f', 'htaccess_f', 'user', 'plugin_message', 'home_folder', 'wpadmin_folder', 'htpasswd_file', 'htaccess_file', 'original_htpasswd', 'original_htaccess', 'plugin_message', 'plugin_version', 'pp_docroot_htaccess', 'pp_wp_includes_htaccess', 'pp_wp_content_htaccess', 'pp_wp_includes_htaccess', 'pp_main_base64', 'pp_ok' ) as $option ) delete_option( 'aa_'.$option );
  85. $home = get_option( 'siteurl' );
  86. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "home: $home" );
  87. $su = parse_url( $home );
  88. $path = ( !isset( $su['path'] ) || empty( $su['path'] ) ) ? '/' : rtrim( $su['path'], '/' ) . '/';
  89. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "path: $path" );
  90. $scheme = ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on' && $su['scheme'] == 'https' ) ? 'https' : 'http';
  91. $home_path = rtrim( get_home_path(), '/' ) . '/';
  92. $hu = str_replace( $scheme . '://', '', $home );
  93. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "hu: $hu" );
  94. $url = $scheme . '://' . rtrim( str_replace( rtrim( $path, '/' ), '', $hu ), '/' );
  95. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "url: $url" );
  96. $authdomain = "/ {$url}/";
  97. update_option( 'askapache_password_protect', array(
  98. 'step' => 'welcome',
  99. 'setup_complete' => 0,
  100. 'scheme' => $scheme,
  101. 'host' => $su['host'],
  102. 'root_path' => $path,
  103. 'home_path' => $home_path,
  104. 'test_dir' => WP_CONTENT_DIR.'/askapache',
  105. 'root_htaccess' => $home_path . '.htaccess',
  106. 'admin_htaccess' => $home_path . 'wp-admin/.htaccess',
  107. 'admin_mail' => get_option( 'admin_email' ),
  108. 'authdomain' => $authdomain,
  109. 'authname' => 'Protected By AskApache',
  110. 'authuserfile' => $home_path . '.htpasswda3',
  111. 'authuserdigest' => 'AuthDigestFile',
  112. 'algorithm' => 'md5',
  113. 'key' => wp_hash_password( wp_generate_password() ),
  114. 'htaccess_support' => 0,
  115. 'mod_alias_support' => 0,
  116. 'mod_rewrite_support' => 0,
  117. 'mod_security_support' => 0,
  118. 'mod_auth_digest_support' => 0,
  119. 'basic_support' => 0,
  120. 'digest_support' => 0,
  121. 'crypt_support' => 0,
  122. 'sha1_support' => 0,
  123. 'md5_support' => 0,
  124. 'revision_support' => 0,
  125. 'apache_version' => '',
  126. 'revisions' => array(),
  127. 'plugin_data' => get_plugin_data( __FILE__ ),
  128. ) );
  129. update_option( 'askapache_password_protect_sids', array(
  130. 60000001 => array( 'Version' => '1.3',
  131. 'Name' => 'Directory Protection',
  132. 'Description' => 'Enable the DirectoryIndex Protection, preventing directory index listings and defaulting.',
  133. 'Rules' =>
  134. 'Options -Indexes%n%' .
  135. 'DirectoryIndex index.html index.php %relative_root%index.php'
  136. ),
  137. 60000002 => array( 'Version' => '1.0',
  138. 'Name' => 'Loop Stopping Code',
  139. 'Description' => 'Stops Internal Redirect Loops',
  140. 'Rules' =>
  141. 'RewriteCond %{ENV:REDIRECT_STATUS} 200%n%' .
  142. 'RewriteRule .* - [L]%n%'
  143. ),
  144. 10140001 => array( 'Version' => '1.1',
  145. 'Name' => 'Stop Hotlinking',
  146. 'Description' => 'Denies any request for static files (images, css, etc) if referrer is not local site or empty.',
  147. 'Rules' =>
  148. 'RewriteCond %{HTTP_REFERER} !^$%n%' .
  149. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  150. 'RewriteCond %{HTTP_REFERER} !^%scheme%://%host%.*$ [NC]%n%' .
  151. 'RewriteRule \.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$ - [F,NS,L]'
  152. ),
  153. 20030001 => array( 'Version' => '1.3',
  154. 'Name' => 'Password Protect wp-login.php',
  155. 'Description' => 'Requires a valid user/pass to access the login page..',
  156. 'Rules' =>
  157. '<Files wp-login.php>%n%' .
  158. 'Satisfy Any%n%' .
  159. '%generate_auth%%n%' .
  160. '</Files>'
  161. ),
  162. 21030002 => array( 'Version' => '1.3',
  163. 'Name' => 'Password Protect wp-admin',
  164. 'Description' => 'Requires a valid user/pass to access any non-static (css, js, images) file in this directory...',
  165. 'Rules' =>
  166. '%generate_auth%%n%' .
  167. '<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$">%n%' .
  168. 'Allow from All%n%' .
  169. '</FilesMatch>%n%' .
  170. '<FilesMatch "(async-upload|admin-ajax)\.php$">%n%' .
  171. '<IfModule mod_security.c>%n%' .
  172. 'SecFilterEngine Off%n%' .
  173. '</IfModule>%n%' .
  174. 'Allow from All%n%' .
  175. '</FilesMatch>'
  176. ),
  177. 30140003 => array( 'Version' => '1.1',
  178. 'Name' => 'Forbid Proxies',
  179. 'Description' => 'Denies POST Request using a Proxy Server. Can access site, but not comment. See <a href="http://perishablepress.com/press/2008/04/20/how-to-block-proxy-servers-via-htaccess/">Perishable Press</a>',
  180. 'Rules' =>
  181. 'RewriteCond %{HTTP:VIA}%{HTTP:FORWARDED}%{HTTP:USERAGENT_VIA}%{HTTP:X_FORWARDED_FOR}%{HTTP:PROXY_CONNECTION} !^$ [OR]%n%' .
  182. 'RewriteCond %{HTTP:XPROXY_CONNECTION}%{HTTP:HTTP_PC_REMOTE_ADDR}%{HTTP:HTTP_CLIENT_IP} !^$%n%' .
  183. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  184. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  185. 'RewriteRule .* - [F,NS,L]'
  186. ),
  187. 30140004 => array( 'Version' => '1.1',
  188. 'Name' => 'Real wp-comments-post.php',
  189. 'Description' => 'Denies any POST attempt made to a non-existing wp-comments-post.php..',
  190. 'Rules' =>
  191. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%.*/wp-comments-post\.php.*\ HTTP/ [NC]%n%' .
  192. 'RewriteRule .* - [F,NS,L]'
  193. ),
  194. 30140005 => array( 'Version' => '1.1',
  195. 'Name' => 'BAD Content Length',
  196. 'Description' => 'Denies any POST request that doesnt have a Content-Length Header..',
  197. 'Rules' =>
  198. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  199. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  200. 'RewriteCond %{HTTP:Content-Length} ^$%n%' .
  201. 'RewriteRule .* - [F,NS,L]'
  202. ),
  203. 30140006 => array( 'Version' => '1.1',
  204. 'Name' => 'BAD Content Type',
  205. 'Description' => 'Denies any POST request with a content type other than application/x-www-form-urlencoded|multipart/form-data..',
  206. 'Rules' =>
  207. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  208. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  209. 'RewriteCond %{HTTP:Content-Type} !^(application/x-www-form-urlencoded|multipart/form-data.*(boundary.*)?)$ [NC]%n%' .
  210. 'RewriteRule .* - [F,NS,L]'
  211. ),
  212. 30140007 => array( 'Version' => '1.1',
  213. 'Name' => 'NO HOST:',
  214. 'Description' => 'Denies requests that dont contain a HTTP HOST Header...',
  215. 'Rules' =>
  216. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  217. 'RewriteCond %{HTTP_HOST} ^$%n%' .
  218. 'RewriteRule .* - [F,NS,L]'
  219. ),
  220. 30140008 => array( 'Version' => '1.1',
  221. 'Name' => 'No UserAgent, No Post',
  222. 'Description' => 'Denies POST requests by blank user-agents. May prevent a small number of visitors from POSTING.',
  223. 'Rules' =>
  224. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  225. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  226. 'RewriteCond %{HTTP_USER_AGENT} ^-?$%n%' .
  227. 'RewriteRule .* - [F,NS,L]'
  228. ),
  229. 30140009 => array( 'Version' => '1.1',
  230. 'Name' => 'No Referer, No Comment',
  231. 'Description' => 'Denies any comment attempt with a blank HTTP_REFERER field, highly indicative of spam. May prevent some visitors from POSTING.',
  232. 'Rules' =>
  233. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*/wp-comments-post\.php.*\ HTTP/ [NC]%n%' .
  234. 'RewriteCond %{HTTP_REFERER} ^-?$%n%' .
  235. 'RewriteRule .* - [F,NS,L]'
  236. ),
  237. 30140010 => array( 'Version' => '1.1',
  238. 'Name' => 'Trackback Spam',
  239. 'Description' => 'Denies obvious trackback spam. See <a href="http://ocaoimh.ie/2008/07/03/more-ways-to-stop-spammers-and-unwanted-traffic/">Holy Shmoly!</a>',
  240. 'Rules' =>
  241. 'RewriteCond %{HTTP_USER_AGENT} ^.*(opera|mozilla|firefox|msie|safari).*$ [NC,OR]%n%' .
  242. 'RewriteCond %{HTTP_USER_AGENT} ^-?$%n%' .
  243. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+/trackback/?\ HTTP/ [NC]%n%' .
  244. 'RewriteCond %{REQUEST_METHOD} =POST%n%' .
  245. 'RewriteRule .* - [F,NS,L]'
  246. ),
  247. 40140011 => array( 'Version' => '1.2',
  248. 'Name' => 'Protect wp-content',
  249. 'Description' => 'Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes',
  250. 'Rules' =>
  251. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%wp-content/.*$ [NC]%n%' .
  252. 'RewriteCond %{REQUEST_FILENAME} !^.+(flexible-upload-wp25js|media)\.php$%n%' .
  253. 'RewriteCond %{REQUEST_FILENAME} ^.+\.(php|html|htm|txt)$%n%' .
  254. 'RewriteRule .* - [F,NS,L]'
  255. ),
  256. 40140012 => array( 'Version' => '1.2',
  257. 'Name' => 'Protect wp-includes',
  258. 'Description' => 'Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes',
  259. 'Rules' =>
  260. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ %relative_root%wp-includes/.*$ [NC]%n%' .
  261. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ %relative_root%wp-includes/js/.+/.+\ HTTP/ [NC]%n%' .
  262. 'RewriteCond %{REQUEST_FILENAME} ^.+\.php$%n%' .
  263. 'RewriteRule .* - [F,NS,L]'
  264. ),
  265. 40140013 => array( 'Version' => '1.1',
  266. 'Name' => 'Common Exploit',
  267. 'Description' => 'Block common exploit requests with 403 Forbidden. These can help alot, may break some plugins.',
  268. 'Rules' =>
  269. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  270. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ ///.*\ HTTP/ [NC,OR]%n%' .
  271. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR]%n%' .
  272. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR]%n%' .
  273. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC,OR]%n%' .
  274. 'RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(htpasswd|htaccess|aahtpasswd).*\ HTTP/ [NC]%n%' .
  275. 'RewriteRule .* - [F,NS,L]'
  276. ),
  277. 50140001 => array( 'Version' => '1.1',
  278. 'Name' => 'Safe Request Methods',
  279. 'Description' => 'Denies any request not using <a href="/online-tools/request-method-scanner/">GET,PROPFIND,POST,OPTIONS,PUT,HEAD</a>..',
  280. 'Rules' =>
  281. 'RewriteCond %{REQUEST_METHOD} !^(GET|HEAD|POST|PROPFIND|OPTIONS|PUT)$ [NC]%n%' .
  282. 'RewriteRule .* - [F,NS,L]'
  283. ),
  284. 50140002 => array( 'Version' => '1.1',
  285. 'Name' => 'HTTP PROTOCOL',
  286. 'Description' => 'Denies any badly formed HTTP PROTOCOL in the request, 0.9, 1.0, and 1.1 only..',
  287. 'Rules' =>
  288. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ .+\ HTTP/(0\.9|1\.0|1\.1) [NC]%n%' .
  289. 'RewriteRule .* - [F,NS,L]'
  290. ),
  291. 50140003 => array( 'Version' => '1.1',
  292. 'Name' => 'SPECIFIC CHARACTERS',
  293. 'Description' => 'Denies any request for a url containing characters other than "a-zA-Z0-9.+/-?=&" - REALLY helps but may break your site depending on your links.',
  294. 'Rules' =>
  295. 'RewriteCond %{REQUEST_URI} !^%relative_root%(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]%n%' .
  296. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [A-Z0-9\.\+_/\-\?\=\&\%\#]+\ HTTP/ [NC]%n%' .
  297. 'RewriteRule .* - [F,NS,L]'
  298. ),
  299. 50140004 => array( 'Version' => '1.1',
  300. 'Name' => 'Directory Traversal',
  301. 'Description' => 'Denies Requests containing ../ or ./. which is a directory traversal exploit attempt..',
  302. 'Rules' =>
  303. 'RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ .*([\.]+[\.]+).*\ HTTP/ [NC]%n%' .
  304. 'RewriteRule .* - [F,NS,L]'
  305. ),
  306. 50140005 => array( 'Version' => '1.1',
  307. 'Name' => 'PHPSESSID Cookie',
  308. 'Description' => 'Only blocks when a PHPSESSID cookie is sent by the user and it contains characters other than 0-9a-z..',
  309. 'Rules' =>
  310. 'RewriteCond %{HTTP_COOKIE} ^.*PHPSESS?ID.*$%n%' .
  311. 'RewriteCond %{HTTP_COOKIE} !^.*PHPSESS?ID=([0-9a-z]+);.*$%n%' .
  312. 'RewriteRule .* - [F,NS,L]'
  313. ),
  314. 50140006 => array( 'Version' => '1.1',
  315. 'Name' => 'Bogus Graphics Exploit',
  316. 'Description' => 'Denies obvious exploit using bogus graphics..',
  317. 'Rules' =>
  318. 'RewriteCond %{HTTP:Content-Disposition} \.php [NC]%n%' .
  319. 'RewriteCond %{HTTP:Content-Type} image/.+ [NC]%n%' .
  320. 'RewriteRule .* - [F,NS,L]' )
  321. )
  322. );
  323. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  324. $sids = array_keys( $aa_SIDS );
  325. foreach ( $sids as $sid )
  326. {
  327. $newinfo = aa_pp_sid_info( $sid );
  328. $aa_SIDS[$sid] = array_merge( $aa_SIDS[$sid], $newinfo );
  329. }
  330. update_option( 'askapache_password_protect_sids', $aa_SIDS );
  331. }
  332. /**
  333. * aa_pp_admin_header()
  334. *
  335. * @return
  336. */
  337. function aa_pp_admin_header()
  338. {
  339. global $wpdb, $aa_PP, $aa_SIDS;
  340. if ( !user_can_access_admin_page() ) wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
  341. if ( !current_user_can( 8 ) )wp_die( __( "You are not allowed to be here without upload permissions" ) );
  342. $aa_PP = get_option( 'askapache_password_protect' );
  343. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  344. @set_time_limit( 60 );
  345. @set_magic_quotes_runtime( 0 );
  346. }
  347. /**
  348. * aa_pp_get_post_values()
  349. *
  350. * @param mixed $v
  351. * @return
  352. */
  353. function aa_pp_get_post_values( $v )
  354. {
  355. global $aa_PP, $aa_SIDS;
  356. $errors = new WP_Error;
  357. $action = 'none';
  358. foreach( array( 'a_htaccess_support', 'a_mod_alias_support', 'a_mod_rewrite_support', 'a_mod_security_support', 'a_mod_auth_digest_support', 'a_digest_support', 'a_basic_support' ) as $k )
  359. {
  360. if ( isset( $_POST[$k] ) && $v[$k] != 1 )
  361. {
  362. check_admin_referer( 'askapache-passpro-form' );
  363. $v[substr( $k, 2 )] = 1;
  364. }
  365. }
  366. foreach( array( 'a_user', 'a_authdomain', 'a_authtype', 'a_algorithm', 'a_authname', 'a_authuserfile', 'a_step', 'a_admin_email', 'a_root_htaccess', ) as $k )
  367. {
  368. if ( isset( $_POST[$k] ) && !empty( $_POST[$k] ) && $_POST[$k] != $v[$k] )
  369. {
  370. check_admin_referer( 'askapache-passpro-form' );
  371. $v[substr( $k, 2 )] = $_POST[$k];
  372. }
  373. }
  374. foreach ( array( 'activate-selected', 'deactivate-selected', 'delete-selected', 'm_move' ) as $action_key )
  375. {
  376. if ( isset( $_POST[$action_key] ) )
  377. {
  378. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Setting action to {$action_key}" );
  379. $action = $action_key;
  380. break;
  381. }
  382. }
  383. if ( $action == 'm_move' )
  384. {
  385. check_admin_referer( 'askapache-move-area' );
  386. foreach( array( 'm_read', 'm_reset', 'm_sid', 'm_setup', 'm_test', 'm_welcome', 'm_contact' ) as $where )
  387. {
  388. if ( isset( $_POST[$where] ) )
  389. {
  390. $aa_PP['step'] = substr( $where, 2 );
  391. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Setting step to {$aa_PP['step']}" );
  392. break;
  393. }
  394. }
  395. return true;
  396. }
  397. foreach ( array( 'deactivate-sid', 'activate-sid', 'view-revision', 'activate-revision', 'delete-revision' ) as $ak )
  398. {
  399. if ( isset( $_GET[$ak] ) )
  400. {
  401. $action = $ak;
  402. break;
  403. }
  404. }
  405. if ( isset( $_POST['a_pass1'] ) && isset( $_POST['a_pass2'] ) )
  406. {
  407. if ( empty( $_POST['a_pass1'] ) || empty( $_POST['a_pass2'] ) )$errors->add( 'password-required', __( '<strong>ERROR</strong>: A password is required' ) );
  408. if ( $_POST['a_pass1'] != $_POST['a_pass2'] )$errors->add( 'passwords-notsame', __( '<strong>ERROR</strong>: The passwords do not match.' ) );
  409. else $pass = $_POST['a_pass1'];
  410. }
  411. if ( isset( $_POST['a_user'] ) && isset( $_POST['a_admin_email'] ) )
  412. {
  413. if ( empty( $_POST['a_user'] ) )$errors->add( 'username-required', __( '<strong>ERROR</strong>: A username is required.' ) );
  414. if ( empty( $_POST['a_admin_email'] ) )$errors->add( 'adminemail-required', __( '<strong>ERROR</strong>: An admin email is required.' ) );
  415. if ( !is_email( $_POST['a_admin_email'] ) )$errors->add( 'adminemail-bad', __( '<strong>ERROR</strong>: A valid admin email is required.' ) );
  416. }
  417. if ( isset( $v['authtype'] ) && !in_array( $v['authtype'], array( 'Digest', 'Basic' ) ) ) $errors->add( 'bad-authtype', __( '<strong>ERROR</strong>: Incorrect authtype' ) );
  418. if ( isset( $v['algorithm'] ) && !in_array( $v['algorithm'], array( 'crypt', 'md5', 'sha1' ) ) ) $errors->add( 'bad-algorithm', __( '<strong>ERROR</strong>: Incorrect algorithm' ) );
  419. if ( isset($v['user']) && strpos( $v['user'], ':' ) !== false ) $errors->add( 'bad-username', __( '<strong>ERROR</strong>: Username cannot contain the : character' ) );
  420. if ( isset($v['authname']) && strlen( $v['authname'] ) > 65 ) $errors->add( 'bad-authname', __( '<strong>ERROR</strong>: Authname cannot exceed 65 characters, yours was ' . strlen( $v['authname'] ) . ' characters' ) );
  421. if ( isset($v['authtype']) && $v['authtype'] == 'Digest' && $v['algorithm'] != 'md5' ) $errors->add( 'algorithm-authtype-mismatch', __( '<strong>ERROR</strong>: Digest Authentication can only use the md5 algorithm' ) );
  422. foreach( array( $v['authuserfile'], $v['admin_htaccess'], $v['root_htaccess'] ) as $f )
  423. {
  424. if ( strpos( basename( $f ), '.ht' ) === false ) $errors->add( 'bad-authuserfilename', __( '<strong>ERROR</strong>: File names must start with .ht like .htaccess or .htpasswd-new3' ) );
  425. if ( (int)$v['setup_complete'] != 0 )
  426. {
  427. if ( aa_pp_htaccess_file_init() && !@touch($f) || !@is_writable( $f ) ) $errors->add( 'unwritable-file', __( '<strong>ERROR</strong>: Please make ' . $f . ' writable and readable' ) );
  428. }
  429. }
  430. if ( count( $errors->errors ) == 0 )
  431. {
  432. $aa_PP = $v;
  433. switch ( $action )
  434. {
  435. case 'activate-revision':
  436. $file = $_GET['activate-revision'];
  437. check_admin_referer( 'activate-revision_' . $file );
  438. break;
  439. case 'view-revision':
  440. $file = $_GET['view-revision'];
  441. check_admin_referer( 'view-revision_' . $file );
  442. break;
  443. case 'delete-revision':
  444. $file = $_GET['delete-revision'];
  445. check_admin_referer( 'delete-revision_' . $file );
  446. $g = array();
  447. foreach( $aa_PP['revisions'] as $item )if ( $item['id'] != $file )$g[] = $item;
  448. $v['revisions'] = $g;
  449. break;
  450. case 'activate-sid':
  451. $sid = ( int )$_GET['activate-sid'];
  452. check_admin_referer( 'activate-sid_' . $sid );
  453. if ( !aa_pp_activate_sid( $sid ) ) $errors->add( 'sid-activation-failed', __( "Failed to activate sid {$sid}" ) );
  454. echo '<img src="askapache-reset.bmp?' . rand( 1, 1000 ) . '" style="width:1px;height:1px;" />';
  455. break;
  456. case 'deactivate-sid':
  457. $sid = ( int )$_GET['deactivate-sid'];
  458. check_admin_referer( 'deactivate-sid_' . $sid );
  459. if ( !aa_pp_deactivate_sid( $sid ) ) $errors->add( 'sid-deactivation-failed', __( "Failed to deactivate sid {$sid}" ) );
  460. break;
  461. case 'activate-selected':
  462. case 'deactivate-selected':
  463. check_admin_referer( 'askapache-bulk-sids' );
  464. break;
  465. }
  466. if ( isset( $pass ) && count( $errors->errors ) == 0 )
  467. {
  468. $message_headers = 'From: "' . $blog_title . '" <wordpress@' . str_replace( 'www.', '', $aa_PP['host'] ) . '>';
  469. $message = sprintf( __( "Your new username and password has been successfully set up at:\n\n%1\$s\n\nYou can log in to the administrator area with the following information:\n\n\nUsername: %2\$s\nPassword: %3\$s\n\nWe hope you enjoy your new protection. Thanks!\n\n--The AskApache Team\nhttp://www.askapache.com/" ), get_option( 'siteurl' ) . '/wp-admin/', $v['user'], $pass );
  470. if ( !aa_pp_file_put_c( $v['authuserfile'], aa_pp_hashit( $v['authtype'], $v['user'], $pass, $v['authname'] ), false ) )
  471. $errors->add( 'failed-create-authuserfile', __( '<strong>ERROR</strong>: Failed to create ' . $v['authuserfile'] ) );
  472. else if ( !wp_mail( $aa_PP['admin_email'], __( '__New AskApache User' ), $message, $message_headers ) )
  473. $errors->add( 'failed-wp-mail', __( '<strong>ERROR</strong>: Failed to mail to ' . $aa_PP['admin_email'] ) );
  474. }
  475. }
  476. if ( count( $errors->errors ) > 0 ) $v['step'] = $aa_PP['step'];
  477. if ( $v['step'] == 'sid' && (int)$v['setup_complete'] != 1 )$v['setup_complete'] = 1;
  478. $aa_PP = $v;
  479. if ( count( $errors->errors ) > 0 ) return $errors;
  480. else return true;
  481. }
  482. /**
  483. * aa_pp_main_page()
  484. *
  485. * @return
  486. */
  487. function aa_pp_main_page()
  488. {
  489. global $aa_PP, $aa_SIDS;
  490. $aa_PP = get_option( 'askapache_password_protect' );
  491. $aa_SIDS = get_option( 'askapache_password_protect_sids' );
  492. ?>
  493. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-move-area' );
  494. ?>
  495. <div class="tablenav">
  496. <div class="alignleft">
  497. <?php if ( $aa_PP['setup_complete'] != 0 ) {?>
  498. <input type="submit" name="m_test" id="m_test" value="Self-Diagnostics" class="button-secondary" />
  499. <input type="submit" name="m_read" id="m_read" value="Htaccess Files" class="button-secondary" />
  500. <input type="submit" name="m_setup" id="m_setup" value="Password Configuration" class="button-secondary" />
  501. <input type="submit" name="m_sid" id="m_sid" value="SID Module Management" class="button-secondary" />
  502. <input type="submit" name="m_contact" id="m_contact" value="Improvements" class="button-secondary" />
  503. <input type="hidden" name="m_move" id="m_move" value="m_move" />
  504. <?php } ?>
  505. </div>
  506. <p style="float:right; margin-top:0;padding-top:0;"><a href="http://www.askapache.com/htaccess/apache-htaccess.html">AskApache .htaccess Tutorial</a></p>
  507. </div>
  508. <br class="clear" />
  509. </form>
  510. <?php
  511. $errors = aa_pp_get_post_values( $aa_PP );
  512. aa_pp_errors( $errors );
  513. if ( (int)$aa_PP['setup_complete'] != 0 )
  514. {
  515. $errors = aa_pp_update_revisions( $aa_PP['admin_htaccess'] );
  516. aa_pp_errors( $errors );
  517. $errors = aa_pp_update_revisions( $aa_PP['root_htaccess'] );
  518. aa_pp_errors( $errors );
  519. }
  520. update_option( 'askapache_password_protect', $aa_PP );
  521. if ( isset( $_POST['notice'] ) ) echo '<div id="message" class="updated fade"><p>' . $_POST['notice'] . '</p></div>';
  522. if ( (bool)AA_PP_DEBUG === true )
  523. {
  524. echo '<pre>';
  525. print_r( $aa_PP );
  526. print_r(aa_pp_active_sids());
  527. //print_r(get_defined_constants());
  528. echo '</pre>';
  529. }
  530. switch ( $aa_PP['step'] )
  531. {
  532. case 'contact':
  533. ?>
  534. <div class="wrap" style="max-width:95%;">
  535. <h3>Bug Fixes</h3>
  536. <p>10/17/08 - Fixed known bugs.. Improved Testing with debug output automatically for failed tests.</p>
  537. <p><br class="clear" /></p>
  538. <h3>Backups and Revisioning</h3>
  539. <p>8/19/08 - Ok so version 4.6 has some nice automatic revisioning/backup features... the next release will let us compare the new .htaccess file with the old .htaccess files just like wikis. (based once again on wordpress core)..</p>
  540. <p>So now that the SID module system is pretty stable and there is now decent backups going on, the next thing I'll be adding is multi-user and group management. And much more access control by IP address and other ids.</p>
  541. <p>The point of doing all that is so the plugin will be stable enough code-wise so we can focus in on developing custom SIDs for protecting wordpress blogs.. Mod_Security rules are on the way....</p>
  542. <p><br class="clear" /></p>
  543. <h3>The SID Module Redesigned</h3>
  544. <p>8/14/08 - I'm finally mostly happy with the system now used by this plugin to update/modify/and use the different modules. The old code just wasn't future-proofed enough. This new version is based very much off of the WordPress Plugins code, so it is future proofed.</p>
  545. <p>This "Improvements" page is the start of whats to come, Basically each of the security modules (and there are a LOT of great mod_security ones coming) will have their own very Basic settings. So you can tweak the settings. If someone finds an improvement they can send it for review. New ideas and modules can be submitted here also.</p>
  546. </div>
  547. <?php
  548. break;
  549. case 'welcome':
  550. aa_pp_welcome_form();
  551. break;
  552. case 'test':
  553. aa_pp_run_tests();
  554. break;
  555. case 'setup':
  556. aa_pp_setup_form();
  557. break;
  558. case 'sid':
  559. aa_pp_sid_management();
  560. break;
  561. case 'reset':
  562. aa_pp_activate();
  563. break;
  564. case 'read':
  565. aa_pp_htaccess_history();
  566. break;
  567. default:
  568. aa_pp_welcome_form();
  569. break;
  570. }
  571. update_option( 'askapache_password_protect', $aa_PP );
  572. }
  573. /**
  574. * aa_pp_welcome_form()
  575. *
  576. * @return
  577. */
  578. function aa_pp_welcome_form()
  579. {
  580. global $aa_PP, $aa_SIDS;?>
  581. <div class="wrap" style="max-width:95%;">
  582. <h2>Test for Compatibility and Capability</h2>
  583. <form action="options-general.php?page=askapache-password-protect.php" method="post"><?php wp_nonce_field( 'askapache-passpro-form' );?>
  584. <input type="hidden" id="a_step" name="a_step" value="test" />
  585. <p>First we need to run a series of tests on your server to determine what capabilities your site has and also to locate any potential installation problems.</p>
  586. <p>The tests will be run on temporary files I'll create in your /wp-content/askapache/ folder. They will create .htaccess and .htpasswd files in that temp location and then use fsockopen networking functions to query those files. This tells us exactly how your server handles .htaccess configurations, HTTP authentication schemes, Apache Module capability, etc..</p></p>
  587. <table class="form-table">
  588. <tr valign="top">
  589. <th scope="row">Known Support<br /><p>Only check these if you are 100% sure your server supports them. This bypasses auto-detecting support.</p></th>
  590. <td><label for="a_htaccess_support"><input type="checkbox" name="a_htaccess_support" id="a_htaccess_support" <?php if ( $aa_PP['htaccess_support'] != 0 )echo 'checked="checked"';?> /> .htaccess file support</label><br />
  591. <label for="a_mod_alias_support"><input type="checkbox" name="a_mod_alias_support" id="a_mod_alias_support" <?php if ( $aa_PP['mod_alias_support'] != 0 )echo 'checked="checked"';?> /> mod_alias Redirects supported</label><br />
  592. <label for="a_mod_rewrite_support"><input type="checkbox" name="a_mod_rewrite_support" id="a_mod_rewrite_support" <?php if ( $aa_PP['mod_rewrite_support'] != 0 )echo 'checked="checked"';?> /> mod_rewrite supported</label><br />
  593. <label for="a_mod_security_support"><input type="checkbox" name="a_mod_security_support" id="a_mod_security_support" <?php if ( $aa_PP['mod_security_support'] != 0 )echo 'checked="checked"';?> /> mod_security supported</label><br />
  594. <label for="a_mod_auth_digest_support"><input type="checkbox" name="a_mod_auth_digest_support" id="a_mod_auth_digest_support" <?php if ( $aa_PP['mod_auth_digest_support'] != 0 )echo 'checked="checked"';?> /> mod_auth_digest supported</label><br />
  595. <label for="a_digest_support"><input type="checkbox" name="a_digest_support" id="a_digest_support" <?php if ( $aa_PP['digest_support'] != 0 )echo 'checked="checked"';?> /> digest authentication supported</label><br />
  596. <label for="a_basic_support"><input type="checkbox" name="a_basic_support" id="a_basic_support" <?php if ( $aa_PP['basic_support'] != 0 )echo 'checked="checked"';?> /> basic authentication supported</label></td>
  597. </tr>
  598. <!--<tr valign="top">
  599. <th scope="row"><label for="a_root_htaccess">Root .htaccess Location</label></th>
  600. <td><input size="70" style="width: 85%;" class="wide code" name="a_root_htaccess" id="a_root_htaccess" type="text" value="<?php echo $aa_PP['root_htaccess'];?>" /><br />
  601. Check to make sure that this is the correct location of your .htaccess file. Getting this wrong could fudge the whole plugin.</td>
  602. </tr>-->
  603. </table>
  604. <p>Several tests send specially crafted HTTP requests which are designed to elicit very specific HTTP Protocol Responses to accurately determine your servers capabilities.</p>
  605. <p>Other important checks will run: file permissions, function availability, much more boring testing. The tests are fast and you can re-run them whenever you want. If you'd like to see the action, define AA_PP_DEBUG to 1 in the source of this file. Good Luck!</p>
  606. <p class="submit"><input name="sub" type="submit" id="sub" value="Initiate Tests &raquo;" /></p>
  607. </form>
  608. </div>
  609. <?php
  610. }
  611. /**
  612. * aa_pp_setup_form()
  613. *
  614. * @return
  615. */
  616. function aa_pp_setup_form()
  617. {
  618. global $aa_PP, $aa_SIDS;
  619. aa_pp_htaccess_file_init();?>
  620. <div class="wrap" style="max-width:95%;">
  621. <h2>Setup Password Protection</h2>
  622. <form action="options-general.php?page=askapache-password-protect.php" method="post"><?php wp_nonce_field( 'askapache-passpro-form' );?>
  623. <input type="hidden" id="a_step" name="a_step" value="sid" />
  624. <h3>Create User</h3>
  625. <table class="form-table">
  626. <tbody>
  627. <tr valign="top">
  628. <th scope="row"><label for="a_admin_email">Admin Email</label><br />Username and Password sent here in case you forget it.</th>
  629. <td><input size="40" name="a_admin_email" type="text" id="a_admin_email" value="<?php echo $aa_PP['admin_mail'];?>" /></td>
  630. </tr>
  631. <tr valign="top">
  632. <th scope="row"><label for="a_user">Username</label></th>
  633. <td><input size="40" name="a_user" type="text" id="a_user" value="<?php echo $aa_PP['user'];?>" /></td>
  634. </tr>
  635. <tr valign="top">
  636. <th><label for="a_pass">Password (twice)</label></th>
  637. <td><input size="40" type="password" name="a_pass1" id="a_pass1" value="<?php if ( isset( $_POST['a_pass1'] ) && !empty( $_POST['a_pass1'] ) ) echo htmlentities( $_POST['a_pass1'] );?>" /><br />
  638. <input size="40" type="password" name="a_pass2" id="a_pass2" value="<?php if ( isset( $_POST['a_pass2'] ) && !empty( $_POST['a_pass2'] ) ) echo htmlentities( $_POST['a_pass2'] );?>" /><br /></td>
  639. </tr>
  640. </tbody>
  641. </table>
  642. <h3>Authentication Scheme</h3>
  643. <table class="form-table">
  644. <tr valign="top">
  645. <th scope="row">Choose Scheme </th>
  646. <td><fieldset>
  647. <p>
  648. <label><input name="a_authtype" type="radio" value="Digest" <?php echo ( $aa_PP['digest_support'] != 1 ) ? ' disabled="disabled"' : ' checked="checked"';?> /> <strong>Digest</strong> &#8212; Much better than Basic, MD5 crypto hashing with nonce's to prevent cryptanalysis.</label>
  649. <br />
  650. <label><input name="a_authtype" type="radio" value="Basic" <?php if ( $aa_PP['basic_support'] != 1 ) echo ' disabled="disabled"';
  651. else if ( $aa_PP['digest_support'] != 1 ) echo ' checked="checked"';?> /> <strong>Basic</strong> &#8212; Cleartext authentication using a user-ID and a password for each authname.</label>
  652. <br /><br /> This is the mechanism by which your credentials are authenticated (Digest is <a href="http://tools.ietf.org/html/rfc2617">strongly preferred</a>) </p>
  653. </fieldset></td>
  654. </tr>
  655. </tbody>
  656. </table>
  657. <h3>Authentication Settings</h3>
  658. <table class="form-table">
  659. <tbody>
  660. <tr valign="top">
  661. <th scope="row"><label for="a_authuserfile">Password File Location</label></th>
  662. <td><input size="70" style="width: 85%;" class="wide code" name="a_authuserfile" id="a_authuserfile" type="text" value="<?php echo $aa_PP['authuserfile'];?>" /><br />
  663. Use a location inaccessible from a web-browser if possible. Do not put it in the directory that it protects. </td>
  664. </tr>
  665. <tr valign="top">
  666. <th scope="row"><label for="a_authname">Realm Name</label></th>
  667. <td><input size="70" style="width: 85%;" class="wide code" name="a_authname" id="a_authname" type="text" value="<?php echo $aa_PP['authname'];?>" /><br />
  668. The authname or "Realm" serves two major functions. Part of the password dialog box. Second, it is used by the client to determine what password to send for a given authenticated area. </td>
  669. </tr>
  670. <tr valign="top">
  671. <th scope="row"><label for="a_authdomain">Protection Space Domains</label></th>
  672. <td><input size="70" style="width: 85%;" class="wide code" name="a_authdomain" id="a_authdomain" type="text" value="<?php echo $aa_PP['authdomain'];?>" /><br />
  673. One or more URIs in the same protection space (i.e. use the same authname and username/password info). The URIs may be either absolute or relative URIs. Omitting causes client to send Authorization header for every request. </td>
  674. </tr>
  675. </tbody>
  676. </table>
  677. <h3>Encryption Preferences</h3>
  678. <table class="form-table">
  679. <tbody>
  680. <tr valign="top">
  681. <th scope="row">Password File Algorithm</th>
  682. <td><fieldset>
  683. <label><input type="radio" name="a_algorithm" value="crypt" id="a_algorithm_crypt"<?php if ( $aa_PP['crypt_support'] != 1 )
  684. echo ' disabled="disabled"';
  685. else if ( $aa_PP['algorithm'] == 'crypt' && $aa_PP['authtype'] != 'Digest' )
  686. echo ' checked="checked"';?> /> <strong>CRYPT</strong> &#8212; Unix only. Uses the traditional Unix crypt(3) function with a randomly-generated 32-bit salt (only 12 bits used) and the first 8 characters of the password.</label>
  687. <br />
  688. <label><input type="radio" name="a_algorithm" value="md5" id="a_algorithm_md5"<?php if ( $aa_PP['md5_support'] != 1 )
  689. echo ' disabled="disabled"';
  690. else if ( $aa_PP['algorithm'] == 'md5' )
  691. echo ' checked="checked"';?> /> <strong>MD5</strong> &#8212; Apache-specific algorithm using an iterated (1,000 times) MD5 Digest of various combinations of a random 32-bit salt and the password.</label>
  692. <br />
  693. <label><input type="radio" name="a_algorithm" value="sha1" id="a_algorithm_sha1"<?php if ( $aa_PP['sha1_support'] != 1 )
  694. echo ' disabled="disabled"';
  695. else if ( $aa_PP['algorithm'] == 'sha1' && $aa_PP['authtype'] != 'Digest' )
  696. echo ' checked="checked"';?> /> <strong>SHA1</strong> &#8212; Base64-encoded SHA-1 Digest of the password.</label>
  697. <br />
  698. </fieldset></td>
  699. </tr>
  700. </tbody>
  701. </table>
  702. <p>Note I do not store or save your password anywhere, so you will need to type it in each time you update this page.. for now.</p>
  703. <p class="submit"><input name="sub" type="submit" id="sub" value="Save Settings &raquo;" /></p>
  704. </form>
  705. </div>
  706. <?php
  707. }
  708. /**
  709. * aa_pp_update_revisions()
  710. *
  711. * @param mixed $file
  712. * @return
  713. */
  714. function aa_pp_update_revisions( $file )
  715. {
  716. global $aa_PP;
  717. clearstatcache();
  718. if ( !file_exists( $file ) || filesize( $file ) < 5 )return;
  719. $md5_val = md5_file( $file );
  720. $md5s = array();
  721. foreach( $aa_PP['revisions'] as $f ) $md5s[] = $f['md5'];
  722. if ( in_array( $md5_val, $md5s ) )return;
  723. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Creating new revision for {$file}" );
  724. $data = aa_pp_readfile( $file );
  725. if ( $aa_PP['gzip_support'] != 1 )$data_compress = base64_encode( $data );
  726. else $data_compress = base64_encode( gzcompress( $data, 9 ) );
  727. $tag = ( strpos( $file, 'wp-admin' ) !== false )?1:0;
  728. $aa_PP['revisions'][] =
  729. array(
  730. 'file' => $file,
  731. 'id' => $tag . count( $aa_PP['revisions'] ),
  732. 'md5' => $md5_val,
  733. 'time' => current_time( 'timestamp', 1 ),
  734. 'size' => filesize( $file ),
  735. 'data' => $data_compress,
  736. );
  737. }
  738. /**
  739. * aa_pp_htaccess_history()
  740. *
  741. * @return
  742. */
  743. function aa_pp_htaccess_history()
  744. {
  745. global $aa_PP;
  746. ?>
  747. <div class="wrap" style="max-width:95%;">
  748. <h2>.htaccess File Revisions</h2>
  749. <p><br class="clear" /></p>
  750. <?php
  751. if ( isset( $_GET['view-revision'] ) )aa_pp_view_revision( $_GET['view-revision'] );
  752. else aa_pp_print_history( $aa_PP['revisions'], 'root' );
  753. ?>
  754. </div>
  755. <?php
  756. }
  757. /**
  758. * aa_pp_view_revision()
  759. *
  760. * @param mixed $id
  761. * @return
  762. */
  763. function aa_pp_view_revision( $id )
  764. {
  765. global $aa_PP;
  766. $ids = array();
  767. foreach( $aa_PP['revisions'] as $n => $revs )
  768. {
  769. if ( $revs['id'] == $id )
  770. {
  771. $file = $revs;
  772. break;
  773. }
  774. }
  775. if ( !current_user_can( 'edit_plugins' ) )
  776. wp_die( '<p>' . __( 'You do not have sufficient permissions to edit templates for this blog.' ) . '</p>' );
  777. if ( $aa_PP['gzip_support'] != 1 )$content = base64_decode( $file['data'] );
  778. else $content = gzuncompress( base64_decode( $file['data'] ) );
  779. echo '<pre style="border:3px solid #CCC; padding:1em;font-family:"Andale Mono","Lucida Console","Bitstream Vera Sans Mono","Courier New",monospace;*font-size:108%;line-height:99%;">';
  780. echo htmlspecialchars( $content );
  781. echo '</pre>';
  782. }
  783. /**
  784. * aa_pp_print_history()
  785. *
  786. * @param mixed $revision_files
  787. * @param mixed $context
  788. * @return
  789. */
  790. function aa_pp_print_history( $revision_files, $context )
  791. {
  792. global $aa_PP, $aa_SIDS;
  793. if ( sizeof( $revision_files ) < 1 )return;
  794. ?>
  795. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-bulk-sids' ); ?>
  796. <div class="tablenav">
  797. <h3 style="text-align:right; width:70%; line-height:2em; margin:0;float:right;padding-right:30px;" id="current-<?php echo $context;?>">.htaccess File Revisions</h3>
  798. <br class="clear" />
  799. </div>
  800. <br class="clear" />
  801. <table class="widefat" id="revisions-table">
  802. <thead>
  803. <tr>
  804. <th scope="col">ID</th>
  805. <th scope="col">Created</th>
  806. <th scope="col">Size</th>
  807. <th scope="col">Compressed Size</th>
  808. <th scope="col">File Location</th>
  809. <th scope="col">MD5 Hash</th>
  810. <th scope="col" class="action-links"><?php _e( 'Action' );?></th>
  811. </tr>
  812. </thead>
  813. <tbody class="plugins">
  814. <?php
  815. foreach ( $revision_files as $file )
  816. {
  817. $fi = $file['file'];
  818. $ts = $file['time'];
  819. $id = $file['id'];
  820. $hash = $file['md5'];
  821. $created = sprintf( '%s at %s', date( get_option( 'date_format' ), $ts ), date( get_option( 'time_format' ), $ts ) );
  822. $size = $file['size'];
  823. $datasize = strlen( $file['data'] );
  824. $action_links = array();
  825. $action_links[] = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;view-revision=' . $id, 'view-revision_' . $id ) . '" class="view">' . __( 'View' ) . '</a>';
  826. $action_links[] = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;delete-revision=' . $id, 'delete-revision_' . $id ) . '" class="delete">' . __( 'Delete' ) . '</a>';
  827. echo "<tr>
  828. <td class='id' style='width:75px;'>{$id}</td>
  829. <td class='created'>{$created}</td>
  830. <td class='size' style='width:75px;'>{$size}</td>
  831. <td class='datasize' style='width:75px;'>{$datasize}</td>
  832. <td class='file'>{$fi}</td>
  833. <td class='md5'>{$hash}</td>
  834. <td class='togl action-links'>";
  835. if ( !empty( $action_links ) ) echo implode( ' | ', $action_links );
  836. echo '</td>
  837. </tr>';
  838. }
  839. ?>
  840. </tbody>
  841. </table>
  842. </form>
  843. <p><br class="clear" /></p>
  844. <?php
  845. }
  846. /**
  847. * aa_pp_sid_management()
  848. *
  849. * @return
  850. */
  851. function aa_pp_sid_management()
  852. {
  853. global $aa_PP, $aa_SIDS;
  854. $sids = array_keys( $aa_SIDS );
  855. $sid_table = array();
  856. $active_sids = aa_pp_active_sids();
  857. $sid_table['password'] = $sid_table['general'] = $sid_table['antispam'] = $sid_table['wordpress_exploit'] = $sid_table['general_exploit'] = $sid_table['protection'] = array();
  858. $sid_table['active'] = array_values( $active_sids );
  859. foreach ( $sids as $sid )
  860. {
  861. $s = ( string )$sid;
  862. switch ( ( int )$s{0} )
  863. {
  864. case 1:
  865. $sid_table['protection'][] = $sid;
  866. break;
  867. case 2:
  868. $sid_table['password'][] = $sid;
  869. break;
  870. case 3:
  871. $sid_table['antispam'][] = $sid;
  872. break;
  873. case 4:
  874. $sid_table['wordpress_exploit'][] = $sid;
  875. break;
  876. case 5:
  877. $sid_table['general_exploit'][] = $sid;
  878. break;
  879. case 6:
  880. $sid_table['general'][] = $sid;
  881. break;
  882. }
  883. }
  884. ?>
  885. <div class="wrap" style="max-width:95%;">
  886. <h2>Manage Security Modules</h2>
  887. <p>Modules are inserted into your server .htaccess configuration files. Once a module is installed, you may activate it or deactivate it here.</p>
  888. <p><br class="clear" /></p>
  889. <?php foreach( array_reverse( $sid_table ) as $n => $arr ) aa_pp_print_sids_table( $arr, $n );?>
  890. </div>
  891. <?php
  892. }
  893. /**
  894. * aa_pp_print_sids_table()
  895. *
  896. * @param mixed $sids
  897. * @param mixed $context
  898. * @return
  899. */
  900. function aa_pp_print_sids_table( $sids, $context )
  901. {
  902. global $aa_PP, $aa_SIDS;
  903. $aa_SIDS_Active = aa_pp_active_sids();
  904. if ( $context !== 'active' )
  905. {
  906. $ns = array();
  907. $active = array_values( $aa_SIDS_Active );
  908. foreach ( $sids as $sid )
  909. {
  910. if ( !in_array( $sid, $active ) )
  911. $ns[] = $sid;
  912. }
  913. $sids = $ns;
  914. }
  915. if ( sizeof( $sids ) < 1 )return;
  916. $ti = str_replace( '_', ' ', $context );
  917. if ( strpos( $ti, ' ' ) !== false )
  918. {
  919. $word = '';
  920. foreach( explode( " ", $ti ) as $wrd )
  921. $word .= substr_replace( $wrd, strtoupper( substr( $wrd, 0, 1 ) ), 0, 1 ) . " ";
  922. $ti = rtrim( $word, " " );
  923. }
  924. else $ti = substr_replace( $ti, strtoupper( substr( $ti, 0, 1 ) ), 0, 1 );
  925. ?>
  926. <form method="post" action="options-general.php?page=askapache-password-protect.php"><?php wp_nonce_field( 'askapache-bulk-sids' );?>
  927. <div class="tablenav">
  928. <h3 style="text-align:right; width:70%; line-height:2em; margin:0;float:right;padding-right:30px;" id="current-<?php echo $context;?>"><?php echo $ti; ?></h3>
  929. <br class="clear" />
  930. </div>
  931. <br class="clear" />
  932. <table class="widefat" id="<?php echo $context;?>-plugins-table">
  933. <thead>
  934. <tr>
  935. <th scope="col">Name</th>
  936. <th scope="col">Description</th>
  937. <th scope="col">Response</th>
  938. <th scope="col">Apache Modules</th>
  939. <th scope="col">File</th>
  940. <th scope="col" class="action-links">Action</th>
  941. </tr>
  942. </thead>
  943. <tbody class="plugins">
  944. <?php
  945. foreach ( $sids as $sid )
  946. {
  947. $st = $oya = '';
  948. $the_sid = $aa_SIDS[$sid];
  949. $file_title = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  950. if ( $context == 'active' )
  951. {
  952. $st = 'active';
  953. $oya = $the_sid['Type'] . '<br />';
  954. $action_links = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;deactivate-sid=' . $sid, 'deactivate-sid_' . $sid ) . '" class="delete">' . __( 'Deactivate' ) . '</a>';
  955. }
  956. else $action_links = '<a href="' . wp_nonce_url( 'options-general.php?page=askapache-password-protect.php&amp;activate-sid=' . $sid, 'activate-sid_' . $sid ) . '" class="edit">' . __( 'Activate' ) . '</a>';
  957. echo "<tr class='{$st}'>
  958. <td class='name' style='width:200px;'>" . $oya . "<dfn style='font-style:normal;color:#3366CC;' title='SID: " . $sid . " Version: " . $the_sid['Version'] . "'>" . $the_sid['Name'] . "</dfn></td>
  959. <td class='desc' style='width:450px;'><p>" . $the_sid['Description'] . "</p></td>
  960. <td class='vers'>" . $the_sid['Response'] . "</td>
  961. <td class='file'>" . $the_sid['Module'] . "</td>
  962. <td class='file'><dfn style='font-style:normal;color:#9999DD;' title='" . $file_title . "'>" . $the_sid['File'] . "</dfn></td>
  963. <td class='action-links'>" . $action_links . '</td></tr>';
  964. }
  965. ?>
  966. </tbody>
  967. </table>
  968. </form>
  969. <p><br class="clear" /></p>
  970. <?php
  971. }
  972. /**
  973. * aa_pp_active_sids()
  974. *
  975. * @param mixed $file
  976. * @return
  977. */
  978. function aa_pp_active_sids( $file = false )
  979. {
  980. global $aa_PP, $aa_SIDS;
  981. $result = array();
  982. $files = array( $aa_PP['root_htaccess'], $aa_PP['admin_htaccess'] );
  983. foreach ( $files as $f )
  984. {
  985. if ( !is_readable( $f ) )return new WP_Error( 'not-readable', __( "aa_pp_active_sids cant read from {$f}" ) );
  986. if ( $markerdata = @explode( "\n", @implode( '', @file( $f ) ) ) )
  987. {
  988. foreach ( $markerdata as $line )
  989. {
  990. if ( strpos( $line, "# +SID " ) !== false ) $result[] = ( int )str_replace( '# +SID ', '', rtrim( $line ) );
  991. }
  992. }
  993. }
  994. return array_unique( $result );
  995. }
  996. /**
  997. * aa_pp_gen_sid()
  998. *
  999. * @param mixed $incoming
  1000. * @return
  1001. */
  1002. function aa_pp_gen_sid( $incoming )
  1003. {
  1004. global $aa_PP, $aa_SIDS;
  1005. if ( $aa_PP['authtype'] == 'Basic' ) $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthUserFile %authuserfile%%n%Require user %user%';
  1006. else $replacement = 'AuthType %authtype%%n%AuthName "%authname%"%n%AuthDigestDomain %authdomain%%n%'.$aa_PP['authuserdigest'].' %authuserfile%%n%Require valid-user';
  1007. if ( strpos( $aa_PP['apache_version'], '2.2' ) !== false && $aa_PP['authtype'] != 'Basic' )$replacement = str_replace( 'AuthDigestFile', 'AuthUserFile', $replacement );
  1008. $aa_S = array( '%n%', '%authname%', '%user%', '%authuserfile%', '%relative_root%', '%scheme%', '%authdomain%', '%host%', '%authtype%', '%generate_auth%' );
  1009. $aa_R = array( "\n", $aa_PP['authname'], $aa_PP['user'], $aa_PP['authuserfile'], $aa_PP['root_path'], $aa_PP['scheme'], $aa_PP['authdomain'], $aa_PP['host'], $aa_PP['authtype'], $replacement );
  1010. return str_replace( $aa_S, $aa_R, str_replace( $aa_S, $aa_R, $incoming ) );
  1011. }
  1012. /**
  1013. * aa_pp_deactivate_sid()
  1014. *
  1015. * @param mixed $sid
  1016. * @param string $mark
  1017. * @param mixed $file
  1018. * @return
  1019. */
  1020. function aa_pp_deactivate_sid( $sid, $mark = 'SID ', $file = false )
  1021. {
  1022. global $aa_PP, $aa_SIDS;
  1023. if ( !$file )
  1024. {
  1025. $the_sid = $aa_SIDS[( int )$sid];
  1026. $file = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  1027. }
  1028. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1029. if ( !is_readable( $file ) || !is_writable( $file ) ) return new WP_Error( 'sid-deactivation-failed', __( "{$file} not readable/writable by aa_pp_deactivate_sid for {$the_sid['Name']}" ) );
  1030. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Deleting {$the_sid['Name']} from {$file}" );
  1031. $result = array();
  1032. if ( $markerdata = @explode( "\n", @implode( '', @file( $file ) ) ) )
  1033. {
  1034. $state = false;
  1035. if ( !$f = @fopen( $file, 'w' ) ) return new WP_Error( 'fopen-failed', __( "aa_pp_deactivate_sid couldnt fopen {$file}" ) );
  1036. foreach ( $markerdata as $n => $line )
  1037. {
  1038. if ( strpos( $line, "# +{$mark}{$sid}" ) !== false ) $state = true;
  1039. if ( !$state ) fwrite( $f, $line . "\n" );
  1040. if ( strpos( $line, "# -{$mark}{$sid}" ) !== false ) $state = false;
  1041. }
  1042. }
  1043. @$_POST['notice'] = "Successfully Deactivated {$the_sid['Name']}";
  1044. if ( !fclose( $f ) )return new WP_Error( 'fclose-failed', __( "fclose failed to close {$file} in aa_pp_deactivate_sid" ) );
  1045. return true;
  1046. }
  1047. /**
  1048. * aa_pp_activate_sid()
  1049. *
  1050. * @param mixed $sid
  1051. * @param mixed $file
  1052. * @return
  1053. */
  1054. function aa_pp_activate_sid( $sid, $file = false )
  1055. {
  1056. global $aa_PP, $aa_SIDS;
  1057. $the_sid = $aa_SIDS[( int )$sid];
  1058. if ( !$file ) $file = ( $the_sid['File'] == 'root' ) ? $aa_PP['root_htaccess'] : $aa_PP['admin_htaccess'];
  1059. $file = ( @is_readable( $file ) ) ? realpath( rtrim( $file, '/' ) ) : rtrim( $file, '/' );
  1060. if ( !is_readable( $file ) || !is_writable( $file ) ) return new WP_Error( 'not-writable', __( "{$file} not readable/writable by aa_pp_activate_sid for {$the_sid['Name']}" ) );
  1061. aa_pp_notify( __FUNCTION__ . ":" . __LINE__ . ' ' . "Activating {$the_sid['Name']} to {$file}" );
  1062. $rules = aa_pp_gen_sid( explode( "\n", $the_sid['Rules'] ) );
  1063. if ( !aa_pp_insert_sids( $file, $sid, $rules ) ) return new WP_Error( 'sid-activation-failed', __( "Failed to Activate {$the_sid['Name']}" ) );
  1064. else
  1065. {
  1066. @$_POST['notice'] = "Successfully Activated {$sid}: &quot;{$the_sid['Name']}&q…

Large files files are truncated, but you can click here to view the full file